jotai-state-tree 1.3.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-K2MLK6B7.mjs → chunk-MSLAD5CJ.mjs} +404 -1
- package/dist/index.d.mts +3 -122
- package/dist/index.d.ts +3 -122
- package/dist/index.js +103 -21
- package/dist/index.mjs +72 -387
- package/dist/react.d.mts +17 -3
- package/dist/react.d.ts +17 -3
- package/dist/react.js +520 -0
- package/dist/react.mjs +45 -1
- package/dist/{tree-C2ADWEka.d.mts → undo-BcBI_BQM.d.mts} +120 -1
- package/dist/{tree-C2ADWEka.d.ts → undo-BcBI_BQM.d.ts} +120 -1
- package/package.json +1 -1
- package/src/__tests__/app_example.test.tsx +277 -0
- package/src/__tests__/history_repro.test.ts +100 -0
- package/src/__tests__/react.react.test.tsx +50 -0
- package/src/array.ts +102 -24
- package/src/react.ts +76 -0
- package/src/undo.ts +38 -1
|
@@ -899,6 +899,406 @@ function unfreeze(target) {
|
|
|
899
899
|
}
|
|
900
900
|
}
|
|
901
901
|
|
|
902
|
+
// src/undo.ts
|
|
903
|
+
var UndoManager = class {
|
|
904
|
+
constructor(target, options = {}) {
|
|
905
|
+
this.historyEntries = [];
|
|
906
|
+
this.currentIndex = -1;
|
|
907
|
+
this.isUndoing = false;
|
|
908
|
+
this.isRedoing = false;
|
|
909
|
+
this.skipRecording = false;
|
|
910
|
+
this.grouping = false;
|
|
911
|
+
this.actionGrouping = false;
|
|
912
|
+
this.currentGroup = [];
|
|
913
|
+
this.currentGroupInverse = [];
|
|
914
|
+
this.disposer = null;
|
|
915
|
+
this.actionDisposer = null;
|
|
916
|
+
this.lastChangeTime = 0;
|
|
917
|
+
this.target = target;
|
|
918
|
+
this.options = {
|
|
919
|
+
maxHistoryLength: options.maxHistoryLength ?? 100,
|
|
920
|
+
groupByTime: options.groupByTime ?? false,
|
|
921
|
+
groupingWindow: options.groupingWindow ?? 200
|
|
922
|
+
};
|
|
923
|
+
this.disposer = onPatch(target, (patch, reversePatch) => {
|
|
924
|
+
this.recordPatch(patch, reversePatch);
|
|
925
|
+
});
|
|
926
|
+
this.actionDisposer = onAction(target, () => {
|
|
927
|
+
const current = getCurrentAction();
|
|
928
|
+
if (current && !current.parent) {
|
|
929
|
+
if (this.actionGrouping) {
|
|
930
|
+
this.endGroup();
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
get canUndo() {
|
|
936
|
+
return this.currentIndex >= 0;
|
|
937
|
+
}
|
|
938
|
+
get canRedo() {
|
|
939
|
+
return this.currentIndex < this.historyEntries.length - 1;
|
|
940
|
+
}
|
|
941
|
+
get undoLevels() {
|
|
942
|
+
return this.currentIndex + 1;
|
|
943
|
+
}
|
|
944
|
+
get redoLevels() {
|
|
945
|
+
return this.historyEntries.length - this.currentIndex - 1;
|
|
946
|
+
}
|
|
947
|
+
get history() {
|
|
948
|
+
return [...this.historyEntries];
|
|
949
|
+
}
|
|
950
|
+
get historyIndex() {
|
|
951
|
+
return this.currentIndex;
|
|
952
|
+
}
|
|
953
|
+
recordPatch(patch, reversePatch) {
|
|
954
|
+
if (this.isUndoing || this.isRedoing || this.skipRecording) {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
const node = getStateTreeNode(this.target);
|
|
958
|
+
if (node.getRoot().$isApplyingHistory) {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
const now = Date.now();
|
|
962
|
+
if (isActionRunning() && !this.grouping) {
|
|
963
|
+
this.grouping = true;
|
|
964
|
+
this.actionGrouping = true;
|
|
965
|
+
this.currentGroup = [];
|
|
966
|
+
this.currentGroupInverse = [];
|
|
967
|
+
Promise.resolve().then(() => {
|
|
968
|
+
if (this.actionGrouping) {
|
|
969
|
+
this.endGroup();
|
|
970
|
+
}
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
if (this.grouping) {
|
|
974
|
+
this.currentGroup.push(reversePatch);
|
|
975
|
+
this.currentGroupInverse.push({ ...patch });
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
if (this.options.groupByTime && this.historyEntries.length > 0 && now - this.lastChangeTime < this.options.groupingWindow && this.currentIndex === this.historyEntries.length - 1) {
|
|
979
|
+
const lastEntry = this.historyEntries[this.currentIndex];
|
|
980
|
+
lastEntry.patches.push(reversePatch);
|
|
981
|
+
lastEntry.inversePatches.push({ ...patch });
|
|
982
|
+
lastEntry.timestamp = now;
|
|
983
|
+
} else {
|
|
984
|
+
if (this.currentIndex < this.historyEntries.length - 1) {
|
|
985
|
+
this.historyEntries.splice(this.currentIndex + 1);
|
|
986
|
+
}
|
|
987
|
+
this.historyEntries.push({
|
|
988
|
+
patches: [reversePatch],
|
|
989
|
+
inversePatches: [{ ...patch }],
|
|
990
|
+
timestamp: now
|
|
991
|
+
});
|
|
992
|
+
this.currentIndex++;
|
|
993
|
+
if (this.historyEntries.length > this.options.maxHistoryLength) {
|
|
994
|
+
const excess = this.historyEntries.length - this.options.maxHistoryLength;
|
|
995
|
+
this.historyEntries.splice(0, excess);
|
|
996
|
+
this.currentIndex -= excess;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
this.lastChangeTime = now;
|
|
1000
|
+
}
|
|
1001
|
+
undo() {
|
|
1002
|
+
if (!this.canUndo) {
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
const node = getStateTreeNode(this.target);
|
|
1006
|
+
const rootNode = node.getRoot();
|
|
1007
|
+
const wasApplying = rootNode.$isApplyingHistory;
|
|
1008
|
+
rootNode.$isApplyingHistory = true;
|
|
1009
|
+
this.isUndoing = true;
|
|
1010
|
+
try {
|
|
1011
|
+
const entry = this.historyEntries[this.currentIndex];
|
|
1012
|
+
for (let i = entry.patches.length - 1; i >= 0; i--) {
|
|
1013
|
+
applyPatch(this.target, entry.patches[i]);
|
|
1014
|
+
}
|
|
1015
|
+
this.currentIndex--;
|
|
1016
|
+
} finally {
|
|
1017
|
+
this.isUndoing = false;
|
|
1018
|
+
rootNode.$isApplyingHistory = wasApplying;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
redo() {
|
|
1022
|
+
if (!this.canRedo) {
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
const node = getStateTreeNode(this.target);
|
|
1026
|
+
const rootNode = node.getRoot();
|
|
1027
|
+
const wasApplying = rootNode.$isApplyingHistory;
|
|
1028
|
+
rootNode.$isApplyingHistory = true;
|
|
1029
|
+
this.isRedoing = true;
|
|
1030
|
+
try {
|
|
1031
|
+
this.currentIndex++;
|
|
1032
|
+
const entry = this.historyEntries[this.currentIndex];
|
|
1033
|
+
for (const patch of entry.inversePatches) {
|
|
1034
|
+
applyPatch(this.target, patch);
|
|
1035
|
+
}
|
|
1036
|
+
} finally {
|
|
1037
|
+
this.isRedoing = false;
|
|
1038
|
+
rootNode.$isApplyingHistory = wasApplying;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
clear() {
|
|
1042
|
+
this.historyEntries = [];
|
|
1043
|
+
this.currentIndex = -1;
|
|
1044
|
+
this.currentGroup = [];
|
|
1045
|
+
this.currentGroupInverse = [];
|
|
1046
|
+
this.grouping = false;
|
|
1047
|
+
this.actionGrouping = false;
|
|
1048
|
+
}
|
|
1049
|
+
startGroup() {
|
|
1050
|
+
this.grouping = true;
|
|
1051
|
+
this.actionGrouping = false;
|
|
1052
|
+
this.currentGroup = [];
|
|
1053
|
+
this.currentGroupInverse = [];
|
|
1054
|
+
}
|
|
1055
|
+
endGroup() {
|
|
1056
|
+
if (!this.grouping) {
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
this.grouping = false;
|
|
1060
|
+
this.actionGrouping = false;
|
|
1061
|
+
if (this.currentGroup.length > 0) {
|
|
1062
|
+
if (this.currentIndex < this.historyEntries.length - 1) {
|
|
1063
|
+
this.historyEntries.splice(this.currentIndex + 1);
|
|
1064
|
+
}
|
|
1065
|
+
this.historyEntries.push({
|
|
1066
|
+
patches: this.currentGroup,
|
|
1067
|
+
inversePatches: this.currentGroupInverse,
|
|
1068
|
+
timestamp: Date.now()
|
|
1069
|
+
});
|
|
1070
|
+
this.currentIndex++;
|
|
1071
|
+
if (this.historyEntries.length > this.options.maxHistoryLength) {
|
|
1072
|
+
const excess = this.historyEntries.length - this.options.maxHistoryLength;
|
|
1073
|
+
this.historyEntries.splice(0, excess);
|
|
1074
|
+
this.currentIndex -= excess;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
this.currentGroup = [];
|
|
1078
|
+
this.currentGroupInverse = [];
|
|
1079
|
+
}
|
|
1080
|
+
withoutUndo(fn) {
|
|
1081
|
+
this.skipRecording = true;
|
|
1082
|
+
try {
|
|
1083
|
+
return fn();
|
|
1084
|
+
} finally {
|
|
1085
|
+
this.skipRecording = false;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
dispose() {
|
|
1089
|
+
if (this.disposer) {
|
|
1090
|
+
this.disposer();
|
|
1091
|
+
this.disposer = null;
|
|
1092
|
+
}
|
|
1093
|
+
if (this.actionDisposer) {
|
|
1094
|
+
this.actionDisposer();
|
|
1095
|
+
this.actionDisposer = null;
|
|
1096
|
+
}
|
|
1097
|
+
this.clear();
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
function createUndoManager(target, options) {
|
|
1101
|
+
return new UndoManager(target, options);
|
|
1102
|
+
}
|
|
1103
|
+
var TimeTravelManager = class {
|
|
1104
|
+
constructor(target, options = {}) {
|
|
1105
|
+
this.snapshots = [];
|
|
1106
|
+
this.index = -1;
|
|
1107
|
+
this.isApplying = false;
|
|
1108
|
+
this.disposer = null;
|
|
1109
|
+
this.actionDisposer = null;
|
|
1110
|
+
this.pendingRecord = false;
|
|
1111
|
+
this.actionGrouping = false;
|
|
1112
|
+
this.target = target;
|
|
1113
|
+
this.maxSnapshots = options.maxSnapshots ?? 50;
|
|
1114
|
+
this.autoRecord = options.autoRecord ?? false;
|
|
1115
|
+
this.record();
|
|
1116
|
+
if (this.autoRecord) {
|
|
1117
|
+
this.disposer = onPatch(target, () => {
|
|
1118
|
+
if (this.isApplying) return;
|
|
1119
|
+
const node = getStateTreeNode(this.target);
|
|
1120
|
+
if (node.getRoot().$isApplyingHistory) {
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
if (isActionRunning()) {
|
|
1124
|
+
this.pendingRecord = true;
|
|
1125
|
+
if (!this.actionGrouping) {
|
|
1126
|
+
this.actionGrouping = true;
|
|
1127
|
+
Promise.resolve().then(() => {
|
|
1128
|
+
if (this.actionGrouping) {
|
|
1129
|
+
this.commitPendingRecord();
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
} else {
|
|
1134
|
+
this.record();
|
|
1135
|
+
}
|
|
1136
|
+
});
|
|
1137
|
+
this.actionDisposer = onAction(target, () => {
|
|
1138
|
+
const current = getCurrentAction();
|
|
1139
|
+
if (current && !current.parent) {
|
|
1140
|
+
if (this.actionGrouping) {
|
|
1141
|
+
this.commitPendingRecord();
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
commitPendingRecord() {
|
|
1148
|
+
this.actionGrouping = false;
|
|
1149
|
+
if (this.pendingRecord) {
|
|
1150
|
+
this.pendingRecord = false;
|
|
1151
|
+
this.record();
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
get currentIndex() {
|
|
1155
|
+
return this.index;
|
|
1156
|
+
}
|
|
1157
|
+
get snapshotCount() {
|
|
1158
|
+
return this.snapshots.length;
|
|
1159
|
+
}
|
|
1160
|
+
get canGoBack() {
|
|
1161
|
+
return this.index > 0;
|
|
1162
|
+
}
|
|
1163
|
+
get canGoForward() {
|
|
1164
|
+
return this.index < this.snapshots.length - 1;
|
|
1165
|
+
}
|
|
1166
|
+
record() {
|
|
1167
|
+
if (this.index < this.snapshots.length - 1) {
|
|
1168
|
+
this.snapshots.splice(this.index + 1);
|
|
1169
|
+
}
|
|
1170
|
+
this.snapshots.push(getSnapshot(this.target));
|
|
1171
|
+
this.index++;
|
|
1172
|
+
if (this.snapshots.length > this.maxSnapshots) {
|
|
1173
|
+
const excess = this.snapshots.length - this.maxSnapshots;
|
|
1174
|
+
this.snapshots.splice(0, excess);
|
|
1175
|
+
this.index -= excess;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
goBack() {
|
|
1179
|
+
if (!this.canGoBack) return;
|
|
1180
|
+
this.goTo(this.index - 1);
|
|
1181
|
+
}
|
|
1182
|
+
goForward() {
|
|
1183
|
+
if (!this.canGoForward) return;
|
|
1184
|
+
this.goTo(this.index + 1);
|
|
1185
|
+
}
|
|
1186
|
+
goTo(index) {
|
|
1187
|
+
if (index < 0 || index >= this.snapshots.length) return;
|
|
1188
|
+
const node = getStateTreeNode(this.target);
|
|
1189
|
+
const rootNode = node.getRoot();
|
|
1190
|
+
const wasApplying = rootNode.$isApplyingHistory;
|
|
1191
|
+
rootNode.$isApplyingHistory = true;
|
|
1192
|
+
this.isApplying = true;
|
|
1193
|
+
try {
|
|
1194
|
+
this.index = index;
|
|
1195
|
+
applySnapshot(this.target, this.snapshots[index]);
|
|
1196
|
+
} finally {
|
|
1197
|
+
this.isApplying = false;
|
|
1198
|
+
rootNode.$isApplyingHistory = wasApplying;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
getSnapshot(index) {
|
|
1202
|
+
if (index < 0 || index >= this.snapshots.length) {
|
|
1203
|
+
throw new Error(`[jotai-state-tree] Invalid snapshot index: ${index}`);
|
|
1204
|
+
}
|
|
1205
|
+
return this.snapshots[index];
|
|
1206
|
+
}
|
|
1207
|
+
clear() {
|
|
1208
|
+
this.snapshots = [];
|
|
1209
|
+
this.index = -1;
|
|
1210
|
+
this.record();
|
|
1211
|
+
}
|
|
1212
|
+
dispose() {
|
|
1213
|
+
if (this.disposer) {
|
|
1214
|
+
this.disposer();
|
|
1215
|
+
this.disposer = null;
|
|
1216
|
+
}
|
|
1217
|
+
if (this.actionDisposer) {
|
|
1218
|
+
this.actionDisposer();
|
|
1219
|
+
this.actionDisposer = null;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
function createTimeTravelManager(target, options) {
|
|
1224
|
+
return new TimeTravelManager(target, options);
|
|
1225
|
+
}
|
|
1226
|
+
var ActionRecorder = class {
|
|
1227
|
+
constructor(target) {
|
|
1228
|
+
this.recording = false;
|
|
1229
|
+
this.recordedActions = [];
|
|
1230
|
+
this.disposer = null;
|
|
1231
|
+
this.target = target;
|
|
1232
|
+
}
|
|
1233
|
+
get isRecording() {
|
|
1234
|
+
return this.recording;
|
|
1235
|
+
}
|
|
1236
|
+
get actions() {
|
|
1237
|
+
return [...this.recordedActions];
|
|
1238
|
+
}
|
|
1239
|
+
start() {
|
|
1240
|
+
if (this.recording) return;
|
|
1241
|
+
this.recording = true;
|
|
1242
|
+
this.disposer = onAction(this.target, (action) => {
|
|
1243
|
+
this.recordedActions.push({
|
|
1244
|
+
...action,
|
|
1245
|
+
timestamp: Date.now()
|
|
1246
|
+
});
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
stop() {
|
|
1250
|
+
this.recording = false;
|
|
1251
|
+
if (this.disposer) {
|
|
1252
|
+
this.disposer();
|
|
1253
|
+
this.disposer = null;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
clear() {
|
|
1257
|
+
this.recordedActions = [];
|
|
1258
|
+
}
|
|
1259
|
+
replay(target) {
|
|
1260
|
+
const node = getStateTreeNode(target);
|
|
1261
|
+
for (const action of this.recordedActions) {
|
|
1262
|
+
let currentNode = node;
|
|
1263
|
+
if (action.path) {
|
|
1264
|
+
const parts = action.path.split("/").filter(Boolean);
|
|
1265
|
+
for (const part of parts) {
|
|
1266
|
+
const child = currentNode.getChild(part);
|
|
1267
|
+
if (!child) {
|
|
1268
|
+
console.warn(`[jotai-state-tree] Could not find path: ${action.path}`);
|
|
1269
|
+
continue;
|
|
1270
|
+
}
|
|
1271
|
+
currentNode = child;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
const instance = currentNode.getInstance();
|
|
1275
|
+
if (typeof instance[action.name] === "function") {
|
|
1276
|
+
instance[action.name](...action.args);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
export() {
|
|
1281
|
+
return JSON.stringify(this.recordedActions, null, 2);
|
|
1282
|
+
}
|
|
1283
|
+
import(json) {
|
|
1284
|
+
try {
|
|
1285
|
+
const actions = JSON.parse(json);
|
|
1286
|
+
if (Array.isArray(actions)) {
|
|
1287
|
+
this.recordedActions = actions;
|
|
1288
|
+
}
|
|
1289
|
+
} catch (e) {
|
|
1290
|
+
throw new Error(`[jotai-state-tree] Failed to import actions: ${e}`);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
dispose() {
|
|
1294
|
+
this.stop();
|
|
1295
|
+
this.clear();
|
|
1296
|
+
}
|
|
1297
|
+
};
|
|
1298
|
+
function createActionRecorder(target) {
|
|
1299
|
+
return new ActionRecorder(target);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
902
1302
|
export {
|
|
903
1303
|
setLifecycleHookHandlers,
|
|
904
1304
|
getIsApplyingSnapshotOrPatch,
|
|
@@ -961,5 +1361,8 @@ export {
|
|
|
961
1361
|
getOrCreatePath,
|
|
962
1362
|
freeze,
|
|
963
1363
|
isFrozen,
|
|
964
|
-
unfreeze
|
|
1364
|
+
unfreeze,
|
|
1365
|
+
createUndoManager,
|
|
1366
|
+
createTimeTravelManager,
|
|
1367
|
+
createActionRecorder
|
|
965
1368
|
};
|
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
|
|
2
|
-
export { L as CustomTypeOptions,
|
|
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';
|
|
3
3
|
import 'jotai/vanilla/internals';
|
|
4
4
|
import 'jotai';
|
|
5
5
|
|
|
@@ -493,125 +493,6 @@ declare function safeCreate<T extends IAnyType>(type: T, snapshot: unknown, env?
|
|
|
493
493
|
*/
|
|
494
494
|
declare function createWithDefaults<T extends IAnyType>(type: T, snapshot?: Partial<SnapshotIn<T>>, env?: unknown): Instance<T>;
|
|
495
495
|
|
|
496
|
-
/**
|
|
497
|
-
* Undo/Redo Manager for jotai-state-tree
|
|
498
|
-
* Provides time-travel debugging capabilities
|
|
499
|
-
*/
|
|
500
|
-
|
|
501
|
-
interface IUndoManagerOptions {
|
|
502
|
-
/** Maximum number of history entries to keep */
|
|
503
|
-
maxHistoryLength?: number;
|
|
504
|
-
/** Whether to group rapid changes together */
|
|
505
|
-
groupByTime?: boolean;
|
|
506
|
-
/** Time window for grouping changes (ms) */
|
|
507
|
-
groupingWindow?: number;
|
|
508
|
-
}
|
|
509
|
-
interface IHistoryEntry {
|
|
510
|
-
/** Patches to apply to undo this entry */
|
|
511
|
-
patches: IReversibleJsonPatch[];
|
|
512
|
-
/** Patches to apply to redo this entry */
|
|
513
|
-
inversePatches: IReversibleJsonPatch[];
|
|
514
|
-
/** Timestamp when this entry was created */
|
|
515
|
-
timestamp: number;
|
|
516
|
-
}
|
|
517
|
-
interface IUndoManager {
|
|
518
|
-
/** Whether there are entries that can be undone */
|
|
519
|
-
readonly canUndo: boolean;
|
|
520
|
-
/** Whether there are entries that can be redone */
|
|
521
|
-
readonly canRedo: boolean;
|
|
522
|
-
/** Number of undo entries available */
|
|
523
|
-
readonly undoLevels: number;
|
|
524
|
-
/** Number of redo entries available */
|
|
525
|
-
readonly redoLevels: number;
|
|
526
|
-
/** The full history */
|
|
527
|
-
readonly history: IHistoryEntry[];
|
|
528
|
-
/** Current position in history */
|
|
529
|
-
readonly historyIndex: number;
|
|
530
|
-
/** Undo the last change */
|
|
531
|
-
undo(): void;
|
|
532
|
-
/** Redo the last undone change */
|
|
533
|
-
redo(): void;
|
|
534
|
-
/** Clear all history */
|
|
535
|
-
clear(): void;
|
|
536
|
-
/** Start grouping changes */
|
|
537
|
-
startGroup(): void;
|
|
538
|
-
/** End grouping changes */
|
|
539
|
-
endGroup(): void;
|
|
540
|
-
/** Execute a function without recording history */
|
|
541
|
-
withoutUndo<T>(fn: () => T): T;
|
|
542
|
-
/** Stop tracking changes */
|
|
543
|
-
dispose(): void;
|
|
544
|
-
}
|
|
545
|
-
/**
|
|
546
|
-
* Create an undo manager for a state tree
|
|
547
|
-
*/
|
|
548
|
-
declare function createUndoManager(target: unknown, options?: IUndoManagerOptions): IUndoManager;
|
|
549
|
-
interface ITimeTravelManager {
|
|
550
|
-
/** Current snapshot index */
|
|
551
|
-
readonly currentIndex: number;
|
|
552
|
-
/** Total number of snapshots */
|
|
553
|
-
readonly snapshotCount: number;
|
|
554
|
-
/** Whether we can go back */
|
|
555
|
-
readonly canGoBack: boolean;
|
|
556
|
-
/** Whether we can go forward */
|
|
557
|
-
readonly canGoForward: boolean;
|
|
558
|
-
/** Record the current snapshot */
|
|
559
|
-
record(): void;
|
|
560
|
-
/** Go back to previous snapshot */
|
|
561
|
-
goBack(): void;
|
|
562
|
-
/** Go forward to next snapshot */
|
|
563
|
-
goForward(): void;
|
|
564
|
-
/** Go to a specific snapshot index */
|
|
565
|
-
goTo(index: number): void;
|
|
566
|
-
/** Get snapshot at index */
|
|
567
|
-
getSnapshot(index: number): unknown;
|
|
568
|
-
/** Clear all snapshots */
|
|
569
|
-
clear(): void;
|
|
570
|
-
/** Dispose and clean up */
|
|
571
|
-
dispose(): void;
|
|
572
|
-
}
|
|
573
|
-
/**
|
|
574
|
-
* Create a time travel manager for snapshot-based history
|
|
575
|
-
*/
|
|
576
|
-
declare function createTimeTravelManager(target: unknown, options?: {
|
|
577
|
-
maxSnapshots?: number;
|
|
578
|
-
autoRecord?: boolean;
|
|
579
|
-
}): ITimeTravelManager;
|
|
580
|
-
interface IActionRecording {
|
|
581
|
-
/** Name of the action */
|
|
582
|
-
name: string;
|
|
583
|
-
/** Path to the node where action was called */
|
|
584
|
-
path: string;
|
|
585
|
-
/** Arguments passed to the action */
|
|
586
|
-
args: unknown[];
|
|
587
|
-
/** Timestamp */
|
|
588
|
-
timestamp: number;
|
|
589
|
-
}
|
|
590
|
-
interface IActionRecorder {
|
|
591
|
-
/** Whether currently recording */
|
|
592
|
-
readonly isRecording: boolean;
|
|
593
|
-
/** All recorded actions */
|
|
594
|
-
readonly actions: IActionRecording[];
|
|
595
|
-
/** Start recording */
|
|
596
|
-
start(): void;
|
|
597
|
-
/** Stop recording */
|
|
598
|
-
stop(): void;
|
|
599
|
-
/** Clear recorded actions */
|
|
600
|
-
clear(): void;
|
|
601
|
-
/** Replay actions on a target */
|
|
602
|
-
replay(target: unknown): void;
|
|
603
|
-
/** Export actions as JSON */
|
|
604
|
-
export(): string;
|
|
605
|
-
/** Import actions from JSON */
|
|
606
|
-
import(json: string): void;
|
|
607
|
-
/** Dispose and clean up */
|
|
608
|
-
dispose(): void;
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Create an action recorder for debugging and testing
|
|
612
|
-
*/
|
|
613
|
-
declare function createActionRecorder(target: unknown): IActionRecorder;
|
|
614
|
-
|
|
615
496
|
/**
|
|
616
497
|
* The `types` namespace contains all type constructors.
|
|
617
498
|
* This matches the MobX-State-Tree API.
|
|
@@ -711,4 +592,4 @@ declare function typecheck<T>(type: {
|
|
|
711
592
|
is(v: unknown): v is T;
|
|
712
593
|
}, value: unknown): void;
|
|
713
594
|
|
|
714
|
-
export { DatePrimitive as Date, type DynamicReferenceOptions,
|
|
595
|
+
export { DatePrimitive as Date, type DynamicReferenceOptions, IAnyModelType, IAnyType, IArrayType, IDisposer, IEnumerationType, IFrozenType, IIdentifierNumberType, IIdentifierType, ILateType, ILiteralType, IMapType, IMaybeNullType, IMaybeType, type IMiddlewareEvent, type IMiddlewareHandler, IMixin, IModelType, IOptionalType, IReferenceType, IRefinementType, ISafeReferenceType, type ISerializedActionCall, ISimpleType, IType, IUnionType, Instance, MixinConfig, ModelProperties, ReferenceOptions, SnapshotIn, UnionOptions, addMiddleware, applyAction, array, boolean, cast, castToReferenceSnapshot, castToSnapshot, clearModelRegistry, cloneFrozen, compose, createWithDefaults, custom, types as default, dynamicReference, enumeration, escapeJsonPath, finite, float, flow, frozen, getDebugInfo, getIdentifierAttribute, getModelMetadata, getOrCreate, getRegisteredModelNames, getTypeName, getValidationError, hasIdentifier, identifier, identifierNumber, integer, isArrayType, isFrozenType, isIdentifierType, isInstanceOf, isLateType, isLiteralType, isMapType, isModelRegistered, isModelType, isOptionalType, isPrimitiveType, isProtected, isReferenceType, isType, isUnionType, isValidSnapshot, joinJsonPath, late, lateModel, literal, map, maybe, maybeNull, mixin, model, nullType, nullable, number, onModelRegistered, optional, printTree, protect, recordActions, reference, refinement, registerModel, resolveModel, resolveModelAsync, safeCreate, safeDynamicReference, safeReference, snapshotProcessor, splitJsonPath, string, tryResolveModel, typecheck, types, undefinedType, unescapeJsonPath, union, unprotect, unregisterModel };
|