tldraw/packages
Steve Ruiz 01bc73e750
Editor.run, locked shapes improvements (#4042)
This PR:
- creates `Editor.run` (previously `Editor.batch`)
- deprecates `Editor.batch`
- introduces a `ignoreShapeLock` option top the `Editor.run` method that
allows the editor to update and delete locked shapes
- fixes a bug with `updateShapes` that allowed updating locked shapes
- fixes a bug with `ungroupShapes` that allowed ungrouping locked shapes
- makes `Editor.history` private
- adds `Editor.squashToMark`
- adds `Editor.clearHistory`
- removes `History.ignore`
- removes `History.onBatchComplete`
- makes `_updateCurrentPageState` private

```ts
editor.run(() => {
  editor.updateShape({ ...myLockedShape })
  editor.deleteShape(myLockedShape)
}, { ignoreShapeLock: true })
```

It also:

## How it works

Normally `updateShape`/`updateShapes` and `deleteShape`/`deleteShapes`
do not effect locked shapes.

```ts
const myLockedShape = editor.getShape(myShapeId)!

// no change from update
editor.updateShape({ ...myLockedShape, x: 100 })
expect(editor.getShape(myShapeId)).toMatchObject(myLockedShape)

// no change from delete
editor.deleteShapes([myLockedShape])
expect(editor.getShape(myShapeId)).toMatchObject(myLockedShape)
```

The new `run` method adds the option to ignore shape lock.

```ts
const myLockedShape = editor.getShape(myShapeId)!

// update works
editor.run(() => { editor.updateShape({ ...myLockedShape, x: 100 }) }, { ignoreShapeLock: true })
expect(editor.getShape(myShapeId)).toMatchObject({ ...myLockedShape, x: 100 })

// delete works
editor.run(() => { editor.deleteShapes([myLockedShape]), { ignoreShapeLock: true })
expect(editor.getShape(myShapeId)).toBeUndefined()
```

## History changes

This is a related but not entirely related change in this PR.

Previously, we had a few ways to run code that ignored the history.

- `editor.history.ignore(() => { ... })`
- `editor.batch(() => { ... }, { history: "ignore" })`
- `editor.history.batch(() => { ... }, { history: "ignore" })`
- `editor.updateCurrentPageState(() => { ... }, { history: "ignore" })`

We now have one way to run code that ignores history:

- `editor.run(() => { ... }, { history: "ignore" })`

## Design notes

We want a user to be able to update or delete locked shapes
programmatically.

### Callback vs. method options?

We could have added a `{ force: boolean }` property to the
`updateShapes` / `deleteShapes` methods, however there are places where
those methods are called from other methods (such as
`distributeShapes`). If we wanted to make these work, we would have also
had to provide a `force` option / bag to those methods.

Using a wrapper callback allows for "regular" tldraw editor code to work
while allowing for updates and deletes.

### Interaction logic?

We don't want this change to effect any of our interaction logic.

A lot of our interaction logic depends on identifying which shapes are
locked and which shapes aren't. For example, clicking on a locked shape
will go to the `pointing_canvas` state rather than the `pointing_shape`.
This PR has no effect on that part of the library.

It only effects the updateShapes and deleteShapes methods. As an example
of this, when `_force` is set to true by default, the only tests that
should fail are in `lockedShapes.test.ts`. The "user land" experience of
locked shapes is identical to what it is now.

### Change type

- [x] `bugfix`
- [ ] `improvement`
- [x] `feature`
- [x] `api`
- [ ] `other`

### Test plan

1. Create a shape
2. Lock it
3. From the console, update it
4. From the console, delete it

- [x] Unit tests

### Release notes

- SDK: Adds `Editor.force()` to permit updating / deleting locked shapes
- Fixed a bug that would allow locked shapes to be updated
programmatically
- Fixed a bug that would allow locked group shapes to be ungrouped
programmatically

---------

Co-authored-by: alex <alex@dytry.ch>
2024-07-15 14:10:09 +00:00
..
assets serve icons via a single merged .svg file (#4150) 2024-07-15 11:03:11 +00:00
dotcom-shared license: show on dotcom dev mode (#4158) 2024-07-12 16:53:31 +00:00
editor Editor.run, locked shapes improvements (#4042) 2024-07-15 14:10:09 +00:00
namespaced-tldraw Update CHANGELOG.md [skip ci] 2024-06-25 13:27:57 +00:00
state Split @tldraw/state into @tldraw/state and @tldraw/state-react (#4170) 2024-07-15 11:18:59 +00:00
state-react Split @tldraw/state into @tldraw/state and @tldraw/state-react (#4170) 2024-07-15 11:18:59 +00:00
store Update CHANGELOG.md [skip ci] 2024-06-25 13:27:57 +00:00
sync [bemo] allow special chars in roomId (#4153) 2024-07-12 14:01:34 +00:00
sync-core [5/5] Move bemo from dotcom to examples (#4135) 2024-07-12 10:36:31 +00:00
tldraw Editor.run, locked shapes improvements (#4042) 2024-07-15 14:10:09 +00:00
tlschema [3/5] Automatically enable multiplayer UI when using demo sync (#4119) 2024-07-10 15:46:09 +00:00
utils Initial bemo worker setup (#4017) 2024-07-01 11:35:23 +00:00
validate Demo server bookmark unfurl endpoint (#4062) 2024-07-03 10:48:34 +00:00
worker-shared introduce images.tldraw.xyz image optimisation worker (#4069) 2024-07-08 16:25:53 +00:00