Merge pull request #78 from tldraw/feature]-add-history-(public-undo/redo-stack)

Update command ids, add undo/redo stack
This commit is contained in:
Steve Ruiz 2021-09-06 13:53:36 +01:00 committed by GitHub
commit 0c79bbce56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 249 additions and 17 deletions

View file

@ -67,6 +67,6 @@
"@tldraw/core": "^0.0.79",
"perfect-freehand": "^0.5.3",
"react-hotkeys-hook": "^3.4.0",
"rko": "^0.5.22"
"rko": "^0.5.23"
}
}

View file

@ -3,3 +3,126 @@
exports[` 1`] = `"[]"`;
exports[` 2`] = `undefined`;
exports[`TLDrawState Exposes undo/redo stack: history 1`] = `
Array [
Object {
"after": Object {
"document": Object {
"pageStates": Object {
"page1": Object {
"selectedIds": Array [
"rect1",
],
},
},
"pages": Object {
"page1": Object {
"shapes": Object {
"rect1": Object {
"childIndex": 1,
"id": "rect1",
"name": "Rectangle",
"parentId": "page1",
"point": Array [
0,
0,
],
"rotation": 0,
"size": Array [
100,
200,
],
"style": Object {
"color": "Black",
"dash": "Draw",
"isFilled": false,
"size": "Medium",
},
"type": "rectangle",
},
},
},
},
},
},
"before": Object {
"document": Object {
"pageStates": Object {
"page1": Object {
"selectedIds": Array [],
},
},
"pages": Object {
"page1": Object {
"shapes": Object {
"rect1": undefined,
},
},
},
},
},
"id": "create",
},
Object {
"after": Object {
"document": Object {
"pageStates": Object {
"page1": Object {
"selectedIds": Array [
"rect2",
],
},
},
"pages": Object {
"page1": Object {
"shapes": Object {
"rect2": Object {
"childIndex": 1,
"id": "rect2",
"name": "Rectangle",
"parentId": "page1",
"point": Array [
0,
0,
],
"rotation": 0,
"size": Array [
100,
200,
],
"style": Object {
"color": "Black",
"dash": "Draw",
"isFilled": false,
"size": "Medium",
},
"type": "rectangle",
},
},
},
},
},
},
"before": Object {
"document": Object {
"pageStates": Object {
"page1": Object {
"selectedIds": Array [
"rect1",
],
},
},
"pages": Object {
"page1": Object {
"shapes": Object {
"rect2": undefined,
},
},
},
},
},
"id": "create",
},
]
`;

View file

@ -50,7 +50,7 @@ export function align(data: Data, ids: string[], type: AlignType): TLDrawCommand
)
return {
id: 'align_shapes',
id: 'align',
before: {
document: {
pages: {

View file

@ -14,7 +14,7 @@ export function create(data: Data, shapes: TLDrawShape[]): TLDrawCommand {
})
return {
id: 'toggle_shapes',
id: 'create',
before: {
document: {
pages: {

View file

@ -12,7 +12,7 @@ export function deleteShapes(
const { before, after } = removeShapesFromPage(data, ids, pageId)
return {
id: 'delete_shapes',
id: 'delete',
before: {
document: {
pages: {

View file

@ -18,7 +18,7 @@ export function distribute(data: Data, ids: string[], type: DistributeType): TLD
)
return {
id: 'distribute_shapes',
id: 'distribute',
before: {
document: {
pages: {

View file

@ -58,7 +58,7 @@ export function flip(data: Data, ids: string[], type: FlipType): TLDrawCommand {
)
return {
id: 'flip_shapes',
id: 'flip',
before: {
document: {
pages: {

View file

@ -188,7 +188,7 @@ export function group(
})
return {
id: 'group_shapes',
id: 'group',
before: {
document: {
pages: {

View file

@ -217,7 +217,7 @@ export function move(data: Data, ids: string[], type: MoveType): TLDrawCommand {
})
return {
id: 'move_shapes',
id: 'move',
before: {
document: {
pages: {

View file

@ -44,7 +44,7 @@ export function rotate(data: Data, ids: string[], delta = -PI2 / 4): TLDrawComma
)
return {
id: 'toggle_shapes',
id: 'rotate',
before: {
document: {
pages: {

View file

@ -57,7 +57,7 @@ export function stretch(data: Data, ids: string[], type: StretchType): TLDrawCom
)
return {
id: 'stretch_shapes',
id: 'stretch',
before: {
document: {
pages: {

View file

@ -14,7 +14,7 @@ export function style(data: Data, ids: string[], changes: Partial<ShapeStyles>):
)
return {
id: 'style_shapes',
id: 'style',
before: {
document: {
pages: {

View file

@ -16,7 +16,7 @@ export function toggle(data: Data, ids: string[], prop: keyof TLDrawShape): TLDr
)
return {
id: 'toggle_shapes',
id: 'toggle',
before: {
document: {
pages: {

View file

@ -63,7 +63,7 @@ export function translate(data: Data, ids: string[], delta: number[]): TLDrawCom
})
return {
id: 'translate_shapes',
id: 'translate',
before: {
document: {
pages: {

View file

@ -99,7 +99,7 @@ export function ungroup(data: Data, groupId: string, pageId: string): TLDrawComm
})
return {
id: 'ungroup_shapes',
id: 'ungroup',
before: {
document: {
pages: {

View file

@ -28,7 +28,7 @@ export function update(
after.shapes = change.after
return {
id: 'translate_shapes',
id: 'update',
before: {
document: {
pages: {

View file

@ -359,4 +359,90 @@ describe('TLDrawState', () => {
expect(tlstate.getShape('rect5').childIndex).toBe(3)
})
})
it('Exposes undo/redo stack', () => {
const tlstate = new TLDrawState()
.loadDocument(mockDocument)
.createShapes({
id: 'rect1',
type: TLDrawShapeType.Rectangle,
point: [0, 0],
size: [100, 200],
})
.createShapes({
id: 'rect2',
type: TLDrawShapeType.Rectangle,
point: [0, 0],
size: [100, 200],
})
expect(tlstate.history.length).toBe(2)
expect(tlstate.history).toBeDefined()
expect(tlstate.history).toMatchSnapshot('history')
tlstate.history = []
expect(tlstate.history).toEqual([])
const before = tlstate.state
tlstate.undo()
const after = tlstate.state
expect(before).toBe(after)
})
it('Exposes undo/redo stack up to the current pointer', () => {
const tlstate = new TLDrawState()
.loadDocument(mockDocument)
.createShapes({
id: 'rect1',
type: TLDrawShapeType.Rectangle,
point: [0, 0],
size: [100, 200],
})
.createShapes({
id: 'rect2',
type: TLDrawShapeType.Rectangle,
point: [0, 0],
size: [100, 200],
})
.undo()
expect(tlstate.history.length).toBe(1)
})
it('Sets the undo/redo history', () => {
const tlstate = new TLDrawState('some_state_a')
.createShapes({
id: 'rect1',
type: TLDrawShapeType.Rectangle,
point: [0, 0],
size: [100, 200],
})
.createShapes({
id: 'rect2',
type: TLDrawShapeType.Rectangle,
point: [0, 0],
size: [100, 200],
})
// Save the history and document from the first state
const doc = tlstate.document
const history = tlstate.history
// Create a new state
const tlstate2 = new TLDrawState('some_state_b')
// Load the document and set the history
tlstate2.loadDocument(doc)
tlstate2.history = history
expect(tlstate2.shapes.length).toBe(2)
// We should be able to undo the change that was made on the first
// state, now that we've brought in its undo / redo stack
tlstate2.undo()
expect(tlstate2.shapes.length).toBe(1)
})
})

View file

@ -37,6 +37,7 @@ import {
TLDrawPage,
TLDrawBinding,
GroupShape,
TLDrawCommand,
} from '~types'
import { TLDR } from './tldr'
import { defaultStyle } from '~shape'
@ -646,6 +647,20 @@ export class TLDrawState extends StateManager<Data> {
return Vec.sub(Vec.div(point, camera.zoom), camera.point)
}
/**
* Get the current undo/redo stack.
*/
get history() {
return this.stack.slice(0, this.pointer + 1)
}
/**
* Replace the current history stack.
*/
set history(commands: TLDrawCommand[]) {
this.replaceHistory(commands)
}
/**
* The current document.
*/

View file

@ -11557,7 +11557,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
rko@^0.5.19, rko@^0.5.20, rko@^0.5.22:
rko@^0.5.19, rko@^0.5.20:
version "0.5.22"
resolved "https://registry.yarnpkg.com/rko/-/rko-0.5.22.tgz#d5a563beefd97a9cfdda3c29c1fbe119d782b576"
integrity sha512-aNXCHTLshLgq6XuWZzb3XKgy5RyS5YY6/YzCnrBa+tn7NTPC2HysbNhJwyt6bow3u8whiD36GajhUYR6oIbJWw==
@ -11565,6 +11565,14 @@ rko@^0.5.19, rko@^0.5.20, rko@^0.5.22:
idb-keyval "^5.1.3"
zustand "^3.5.9"
rko@^0.5.23:
version "0.5.23"
resolved "https://registry.yarnpkg.com/rko/-/rko-0.5.23.tgz#2613c05d518df71b08215bb031aa4680ede51302"
integrity sha512-u4c2n/99zE+j23WE7FoO5GA4ussYhvhZ5/fh/xJ9ctXyV6Vy+445r2jM2M2xegrCRkIw67RtPI5BmpCXZHnRxA==
dependencies:
idb-keyval "^5.1.3"
zustand "^3.5.9"
rollup-plugin-terser@^7.0.0:
version "7.0.2"
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d"