valtio-history 0.0.0 → 0.0.1
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/README.md +49 -0
- package/package.json +24 -1
- package/src/history-utility.d.ts +50 -0
- package/src/history-utility.js +97 -0
- package/src/history-utility.js.map +1 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +5 -0
- package/src/index.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# valtio-history
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/valtio-history)
|
|
4
|
+
|
|
5
|
+
valtio utility for creating a proxy state with history tracking
|
|
6
|
+
|
|
7
|
+
https://valtio.pmnd.rs/docs/api/utils/proxyWithHistory
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Migrating from `valtio/utils`
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
// replace the following line
|
|
15
|
+
// import { proxyWithHistory } from '`valtio/utils';
|
|
16
|
+
|
|
17
|
+
import { proxyWithHistory } from 'valtio-history';
|
|
18
|
+
import { useSnapshot } from 'valtio';
|
|
19
|
+
|
|
20
|
+
const state = proxyWithHistory({ count: 0 });
|
|
21
|
+
console.log(state.value); // ---> { count: 0 }
|
|
22
|
+
state.value.count += 1;
|
|
23
|
+
console.log(state.value); // ---> { count: 1 }
|
|
24
|
+
state.undo();
|
|
25
|
+
console.log(state.value); // ---> { count: 0 }
|
|
26
|
+
state.redo();
|
|
27
|
+
console.log(state.value); // ---> { count: 1 }
|
|
28
|
+
|
|
29
|
+
// React example
|
|
30
|
+
export default function App() {
|
|
31
|
+
const {
|
|
32
|
+
value,
|
|
33
|
+
undo,
|
|
34
|
+
redo,
|
|
35
|
+
history,
|
|
36
|
+
canUndo,
|
|
37
|
+
canRedo,
|
|
38
|
+
getCurrentChangeDate
|
|
39
|
+
} = useSnapshot(state);
|
|
40
|
+
|
|
41
|
+
...
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Notable changes
|
|
46
|
+
|
|
47
|
+
- the `history` object has changes
|
|
48
|
+
- `history.snapshots` is renamed to `history.nodes`
|
|
49
|
+
- a `HistoryNode` has the structure `{ createdAt: Date; snapshot: Snapshot<T> }`
|
package/package.json
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valtio-history",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"author": "Daishi Kato",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/valtiojs/valtio-history.git"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"history",
|
|
11
|
+
"valtio",
|
|
12
|
+
"undo",
|
|
13
|
+
"redo",
|
|
14
|
+
"proxy",
|
|
15
|
+
"utility",
|
|
16
|
+
"valtio-utility"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"tslib": "^2.3.0"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"valtio": ">=1.0.0"
|
|
23
|
+
},
|
|
24
|
+
"type": "commonjs",
|
|
25
|
+
"main": "./src/index.js",
|
|
26
|
+
"typings": "./src/index.d.ts"
|
|
4
27
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { INTERNAL_Snapshot as Snapshot } from 'valtio/vanilla';
|
|
2
|
+
export type HistoryNode<T> = {
|
|
3
|
+
createdAt: Date;
|
|
4
|
+
snapshot: Snapshot<T>;
|
|
5
|
+
};
|
|
6
|
+
export type History<T> = {
|
|
7
|
+
wip?: Snapshot<T>;
|
|
8
|
+
nodes: HistoryNode<T>[];
|
|
9
|
+
index: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* proxyWithHistory
|
|
13
|
+
*
|
|
14
|
+
* This creates a new proxy with history support.
|
|
15
|
+
* It includes following properties:
|
|
16
|
+
* - value: any value (does not have to be an object)
|
|
17
|
+
* - history: an object holding the history of snapshots and other metadata
|
|
18
|
+
* - history.index: the history index to the current snapshot
|
|
19
|
+
* - history.nodes: the nodes of the history for each change
|
|
20
|
+
* - history.wip: field for holding sandbox changes; used to avoid infinite loops
|
|
21
|
+
* - canUndo: a function to return true if undo is available
|
|
22
|
+
* - undo: a function to go back history
|
|
23
|
+
* - canRedo: a function to return true if redo is available
|
|
24
|
+
* - redo: a function to go forward history
|
|
25
|
+
* - saveHistory: a function to save history
|
|
26
|
+
* - getCurrentChangeDate: gets the date of the current change
|
|
27
|
+
*
|
|
28
|
+
* [Notes]
|
|
29
|
+
* - Suspense/promise is not supported.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* import { proxyWithHistory } from 'valtio/utils'
|
|
33
|
+
* const state = proxyWithHistory({
|
|
34
|
+
* count: 1,
|
|
35
|
+
* })
|
|
36
|
+
*/
|
|
37
|
+
export declare function proxyWithHistory<V>(initialValue: V, skipSubscribe?: boolean): {
|
|
38
|
+
value: V;
|
|
39
|
+
history: History<V> & {
|
|
40
|
+
$$valtioRef: true;
|
|
41
|
+
};
|
|
42
|
+
getCurrentChangeDate: () => Date;
|
|
43
|
+
clone: <T>(value: T) => T;
|
|
44
|
+
canUndo: () => boolean;
|
|
45
|
+
undo: () => void;
|
|
46
|
+
canRedo: () => boolean;
|
|
47
|
+
redo: () => void;
|
|
48
|
+
saveHistory: () => void;
|
|
49
|
+
subscribe: () => () => void;
|
|
50
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.proxyWithHistory = void 0;
|
|
4
|
+
const vanilla_1 = require("valtio/vanilla");
|
|
5
|
+
const isObject = (value) => !!value && typeof value === 'object';
|
|
6
|
+
let refSet;
|
|
7
|
+
const deepClone = (value) => {
|
|
8
|
+
if (!refSet) {
|
|
9
|
+
refSet = (0, vanilla_1.unstable_buildProxyFunction)()[2];
|
|
10
|
+
}
|
|
11
|
+
if (!isObject(value) || refSet.has(value)) {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
const baseObject = Array.isArray(value)
|
|
15
|
+
? []
|
|
16
|
+
: Object.create(Object.getPrototypeOf(value));
|
|
17
|
+
Reflect.ownKeys(value).forEach((key) => {
|
|
18
|
+
baseObject[key] = deepClone(value[key]);
|
|
19
|
+
});
|
|
20
|
+
return baseObject;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* proxyWithHistory
|
|
24
|
+
*
|
|
25
|
+
* This creates a new proxy with history support.
|
|
26
|
+
* It includes following properties:
|
|
27
|
+
* - value: any value (does not have to be an object)
|
|
28
|
+
* - history: an object holding the history of snapshots and other metadata
|
|
29
|
+
* - history.index: the history index to the current snapshot
|
|
30
|
+
* - history.nodes: the nodes of the history for each change
|
|
31
|
+
* - history.wip: field for holding sandbox changes; used to avoid infinite loops
|
|
32
|
+
* - canUndo: a function to return true if undo is available
|
|
33
|
+
* - undo: a function to go back history
|
|
34
|
+
* - canRedo: a function to return true if redo is available
|
|
35
|
+
* - redo: a function to go forward history
|
|
36
|
+
* - saveHistory: a function to save history
|
|
37
|
+
* - getCurrentChangeDate: gets the date of the current change
|
|
38
|
+
*
|
|
39
|
+
* [Notes]
|
|
40
|
+
* - Suspense/promise is not supported.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* import { proxyWithHistory } from 'valtio/utils'
|
|
44
|
+
* const state = proxyWithHistory({
|
|
45
|
+
* count: 1,
|
|
46
|
+
* })
|
|
47
|
+
*/
|
|
48
|
+
function proxyWithHistory(initialValue, skipSubscribe = false) {
|
|
49
|
+
const proxyObject = (0, vanilla_1.proxy)({
|
|
50
|
+
value: initialValue,
|
|
51
|
+
history: (0, vanilla_1.ref)({
|
|
52
|
+
wip: undefined,
|
|
53
|
+
nodes: [],
|
|
54
|
+
index: -1,
|
|
55
|
+
}),
|
|
56
|
+
getCurrentChangeDate: () => {
|
|
57
|
+
const node = proxyObject.history.nodes[proxyObject.history.index];
|
|
58
|
+
return node === null || node === void 0 ? void 0 : node.createdAt;
|
|
59
|
+
},
|
|
60
|
+
clone: deepClone,
|
|
61
|
+
canUndo: () => proxyObject.history.index > 0,
|
|
62
|
+
undo: () => {
|
|
63
|
+
var _a;
|
|
64
|
+
if (proxyObject.canUndo()) {
|
|
65
|
+
proxyObject.value = (proxyObject.history.wip = proxyObject.clone((_a = proxyObject.history.nodes[--proxyObject.history.index]) === null || _a === void 0 ? void 0 : _a.snapshot));
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
canRedo: () => proxyObject.history.index < proxyObject.history.nodes.length - 1,
|
|
69
|
+
redo: () => {
|
|
70
|
+
var _a;
|
|
71
|
+
if (proxyObject.canRedo()) {
|
|
72
|
+
proxyObject.value = (proxyObject.history.wip = proxyObject.clone((_a = proxyObject.history.nodes[++proxyObject.history.index]) === null || _a === void 0 ? void 0 : _a.snapshot));
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
saveHistory: () => {
|
|
76
|
+
proxyObject.history.nodes.splice(proxyObject.history.index + 1);
|
|
77
|
+
proxyObject.history.nodes.push({
|
|
78
|
+
createdAt: new Date(),
|
|
79
|
+
snapshot: (0, vanilla_1.snapshot)(proxyObject).value,
|
|
80
|
+
});
|
|
81
|
+
++proxyObject.history.index;
|
|
82
|
+
},
|
|
83
|
+
subscribe: () => (0, vanilla_1.subscribe)(proxyObject, (ops) => {
|
|
84
|
+
if (ops.every((op) => op[1][0] === 'value' &&
|
|
85
|
+
(op[0] !== 'set' || op[2] !== proxyObject.history.wip))) {
|
|
86
|
+
proxyObject.saveHistory();
|
|
87
|
+
}
|
|
88
|
+
}),
|
|
89
|
+
});
|
|
90
|
+
proxyObject.saveHistory();
|
|
91
|
+
if (!skipSubscribe) {
|
|
92
|
+
proxyObject.subscribe();
|
|
93
|
+
}
|
|
94
|
+
return proxyObject;
|
|
95
|
+
}
|
|
96
|
+
exports.proxyWithHistory = proxyWithHistory;
|
|
97
|
+
//# sourceMappingURL=history-utility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-utility.js","sourceRoot":"","sources":["../../../../packages/history-utility/src/history-utility.ts"],"names":[],"mappings":"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"}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './history-utility';
|
package/src/index.js
ADDED
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/history-utility/src/index.ts"],"names":[],"mappings":";;;AAAA,4DAAkC"}
|