This PR adds some things that we need for the Project Name feature on
tldraw.com.
It should be reviewed alongside
https://github.com/tldraw/tldraw-lite/pull/1814
## Name Property
This PR adds a `name` property to `TLDocument`. We use this to store a
project's name.
<img width="454" alt="Screenshot 2023-05-09 at 15 47 26"
src="https://github.com/tldraw/tldraw/assets/15892272/f3be438e-aa0f-4dec-8f51-8dfd9f9d0ced">
## Top Zone
This PR adds a `topZone` area of the UI that we can add stuff to,
similar to how `shareZone` works.
It also adds an example to show where the `topZone` and `shareZone` are:
<img width="1511" alt="Screenshot 2023-05-12 at 10 57 40"
src="https://github.com/tldraw/tldraw/assets/15892272/f5e1cd33-017e-4aaf-bfee-4d85119e2974">
## Breakpoints
This PR change's the UI's breakpoints a little bit.
It moves the action bar to the bottom a little bit earlier.
(This gives us more space at the top for the project name).
![2023-05-12 at 11 08 26 - Fuchsia
Bison](https://github.com/tldraw/tldraw/assets/15892272/34563cea-b1d1-47be-ac5e-5650ee0ba02d)
![2023-05-12 at 13 45 04 - Tan
Mole](https://github.com/tldraw/tldraw/assets/15892272/ab190bd3-51d4-4a8b-88de-c72ab14bcba6)
## Input Blur
This PR adds an `onBlur` parameter to `Input`.
This was needed because 'clicking off' the input wasn't firing
`onComplete` or `onCancel`.
<img width="620" alt="Screenshot 2023-05-09 at 16 12 58"
src="https://github.com/tldraw/tldraw/assets/15892272/3b28da74-0a74-4063-8053-e59e47027caf">
## Create Project Name
This PR adds an internal `createProjectName` property to
`TldrawEditorConfig`.
Similar to `derivePresenceState`, you can pass a custom function to it.
It lets you control what gets used as the default project name. We use
it to set different names in our local projects compared to shared
projects.
In the future, when we add more advanced project features, we could
handle this better within the UI.
<img width="454" alt="Screenshot 2023-05-09 at 15 47 26"
src="https://github.com/tldraw/tldraw/assets/15892272/da9a4699-ac32-40d9-a97c-6c682acfac41">
### Test Plan
1. Gradually reduce the width of the browser window.
2. Check that the actions menu jumps to the bottom before the style
panel moves to the bottom.
---
1. In the examples app, open the `/zones` example.
2. Check that there's a 'top zone' at the top.
- [ ] Unit Tests
- [ ] Webdriver tests
### Release Note
- [dev] Added a `topZone` area where you can put stuff.
- [dev] Added a `name` property to `TLDocument` - and `app` methods for
it.
- [dev] Added an internal `createProjectName` config property for
controlling the default project name.
- [dev] Added an `onBlur` parameter to `Input`.
- Moved the actions bar to the bottom on medium-sized screens.
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
Add support for locking shapes.
How it works right now:
- You can lock / unlock shapes from the context menu.
- You can also lock shapes with `⇧⌘L` keyboard shortcut.
- You cannot select locked shapes: clicking on the shape, double click
to edit, select all, brush select,... should not work.
- You cannot change props of locked shapes.
- You cannot delete locked shapes.
- If a shape is grouped or within the frame the same rules apply.
- If you delete a group, that contains locked shape it will also delete
those shapes. This seems to be what other apps use as well.
Solves #1445
### Change Type
- [x] `minor` — New Feature
### Test Plan
1. Insert a shape
2. Right click on it and lock it.
3. Test that you cannot select it, change its properties, delete it.
4. Do the same with locked groups.
5. Do the same with locked frames.
- [x] Unit Tests
- [ ] Webdriver tests
### Release Notes
- Add support for locking shapes.
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This PR updates our user-facing APIs for the Tldraw and TldrawEditor
components, as well as the Editor (App). It mainly incorporates surface
changes from #1450 without any changes to validators or migrators,
incorporating feedback / discussion with @SomeHats and @ds300.
Here we:
- remove the TldrawEditorConfig
- bring back a loose version of shape definitions
- make a separation between "core" shapes and "default" shapes
- do not allow custom shapes, migrators or validators to overwrite core
shapes
- but _do_ allow new shapes
## `<Tldraw>` component
In this PR, the `Tldraw` component wraps both the `TldrawEditor`
component and our `TldrawUi` component. It accepts a union of props for
both components. Previously, this component also added local syncing via
a `useLocalSyncClient` hook call, however that has been pushed down to
the `TldrawEditor` component.
## `<TldrawEditor>` component
The `TldrawEditor` component now more neatly wraps up the different ways
that the editor can be configured.
## The store prop (`TldrawEditorProps.store`)
There are three main ways for the `TldrawEditor` component to be run:
1. with an externally defined store
2. with an externally defined syncing store (local or remote)
3. with an internally defined store
4. with an internally defined locally syncing store
The `store` prop allows for these configurations.
If the `store` prop is defined, it may be defined either as a `TLStore`
or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will
assume that the store is ready to go; if it is defined as a SyncedStore,
then the component will display the loading / error screens as needed,
or the final editor once the store's status is "synced".
When the store is left undefined, then the `TldrawEditor` will create
its own internal store using the optional `instanceId`, `initialData`,
or `shapes` props to define the store / store schema.
If the `persistenceKey` prop is left undefined, then the store will not
be synced. If the `persistenceKey` is defined, then the store will be
synced locally. In the future, we may also here accept the API key /
roomId / etc for creating a remotely synced store.
The `SyncedStore` type has been expanded to also include types used for
remote syncing, e.g. with `ConnectionStatus`.
## Tools
By default, the App has two "baked-in" tools: the select tool and the
zoom tool. These cannot (for now) be replaced or removed. The default
tools are used by default, but may be replaced by other tools if
provided.
## Shapes
By default, the App has a set of "core" shapes:
- group
- embed
- bookmark
- image
- video
- text
That cannot by overwritten because they're created by the app at
different moments, such as when double clicking on the canvas or via a
copy and paste event. In follow up PRs, we'll split these out so that
users can replace parts of the code where these shapes are created.
### Change Type
- [x] `major` — Breaking Change
### Test Plan
- [x] Unit Tests
This diff modifies our canvas/rendering code to support shapes rendering
into a "background layer". The background layer isn't a layer in the
sense of our own html/svg/indicator layers, but is instead part of the
HTML canvas layer and is created by allocating z-indexes to shapes below
all others.
For most shapes, the background starts at the canvas. If a shape is in a
frame, then the frame is treated as the background.
![Kapture 2023-05-19 at 11 38
12](https://github.com/tldraw/tldraw/assets/1489520/3ab6e0c0-f71e-4bfd-a996-c5411be28a71)
Exports now use the `renderingShapes` algorithm which fixed a small bug
with exports where opacity wouldn't get correctly propagated down
through child shapes.
### The plan
1. initial highlighter shape/tool #1401
2. sandwich rendering for highlighter shapes #1418 **>you are here<**
3. shape styling - new colours and sizes, lightweight perfect freehand
changes
### Change Type
- [x] `minor` — New Feature
### Test Plan
not yet!
- [x] Unit Tests
### Release Notes
[not yet!]
This diff adds an initial version of the highlighter shape. At this
stage, it's a complete copy of the draw tool minus the following
features:
* Fills
* Stroke types
* Closed shapes
I've created a new shape util (a copy-paste of the draw one with stuff
renamed/deleted) but reused the state chart nodes for the draw shape.
Currently this new tool looks exactly like the draw tool, but that'll be
changing soon!
![Kapture 2023-05-17 at 15 37
33](https://github.com/tldraw/tldraw/assets/1489520/982e78f4-6495-4a68-aa51-c8f7b5bcdd01)
The UI here is extremely WIP. The highlighter tool is behind a feature
flag, but once enabled is accessible through the tool bar. There's a
first-draft highlighter icon (i didn't spend much time on this, it's not
super legible on non-retina displays yet imo), and the tool is bound to
the `i` key (any better suggestions? `h` is taken by the hand tool)
### The plan
1. initial highlighter shape/tool #1401 **>you are here<**
2. sandwich rendering for highlighter shapes #1418
3. shape styling - new colours and sizes, lightweight perfect freehand
changes
### Change Type
- [x] `minor` — New Feature
### Test Plan
(not yet)
### Release Notes
[internal only change layout ground work for highlighter]
This PR adds a user preference to reduce motion. When enabled the app
will not animate the camera (and perhaps skip other animations in the
future). It's actual implementation is as an `animateSpeed` property, so
we can also use it to speed up or slow down our animations if that's
something we want to do!
### Change Type
- [x] `minor` — New Feature
### Test Plan
1. Turn on reduce motion
2. Use minimap / camera features to zoom in / out / etc
- [x] Unit Tests
### Release Notes
- [editor] Add `reduceMotion` user preference
- Add reduce motion option to preferences
This PR replaces our webdriver end to end tests with playwright tests.
It:
- replaces our webdriver workflow with a new e2e workflow based on
playwright
- removes the webdriver project
- adds e2e tests to our examples app
- replaces all `data-wd` attributes with `data-testid`
### Coverage
Most of the tests from our previous e2e tests are reproduced here,
though there are some related to our gestures that will need to be done
in a different way—or not at all. I've also added a handful of new
tests, too.
### Where are they
The tests are now part of our examples app rather than being in its own
different app. This should help us test our different examples too. As
far as I can tell there are no downsides here in terms of the regular
developer experience, though they might complicate any CodeSandbox
projects that are hooked into the examples app.
### Change Type
- [x] `tests` — Changes to any testing-related code only (will not
publish a new version)
This PR adds an `isPageId` helper.
### Change Type
- [x] `internal` — Any other changes that don't affect the published
package (will not publish a new version)
### Release Notes
- [tlschema] Add `isPageId`
This PR renames our record types to avoid a type collision with the type
that they are based on. For example `TLCamera` is both a type and a
record; after this PR, we use `CameraRecordType` for the camera's record
type.
### Change Type
- [x] `major` — Breaking Change
### Release Notes
- [editor] rename record types
- Remove TLUser, TLUserPresence
- Add first-class support for user preferences that persists across
rooms and tabs
### Change Type
<!-- 💡 Indicate the type of change your pull request is. -->
<!-- 🤷♀️ If you're not sure, don't select anything -->
<!-- ✂️ Feel free to delete unselected options -->
<!-- To select one, put an x in the box: [x] -->
- [ ] `patch` — Bug Fix
- [ ] `minor` — New Feature
- [x] `major` — Breaking Change
- [ ] `dependencies` — Dependency Update (publishes a `patch` release,
for devDependencies use `internal`)
- [ ] `documentation` — Changes to the documentation only (will not
publish a new version)
- [ ] `tests` — Changes to any testing-related code only (will not
publish a new version)
- [ ] `internal` — Any other changes that don't affect the published
package (will not publish a new version)
### Test Plan
1. Add a step-by-step description of how to test your PR here.
2.
- [ ] Unit Tests
- [ ] Webdriver tests
### Release Notes
- Add a brief release note for your PR here.
We noticed that when inferring the type of a shape from its ID, it was
getting inferred as `any` which was hiding some issues. This diff
switches `BaseRecord`'s automatic ID to an explicit one, which lets us
pass in our correct `TLShapeId` definition and still have it play nicely
with other places.
### Change Type
- [x] `patch` — Bug Fix
### Release Notes
[internal only, covered by #1432 changelog]
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This PR restores `createTLSchema`.
It also:
- removes `TldrawEditorConfig.default`
- makes `config` a required property of `<TldrawEditor>`, though it's
created automatically in `<Tldraw>`.
- makes `config` a required property of `App`
- removes `TLShapeType` and replaces the rare usage with
`TLShape["type"]`
- adds `TLDefaultShape` for a union of our default shapes
- makes `TLShape` a union of `TLDefaultShape` and `TLUnknownShape`
### Change Type
- [x] `major` — Breaking Change
### Release Notes
- [editor] Simplifies custom shape definition
- [tldraw] Updates props for <TldrawEditor> component to require a
`TldrawEditorConfig`.
This PR removes `TLShapeDef` and associated helpers / references.
It purposely loosens the configuration and typings to better support
customization.
### Change Type
- [x] `major` — Breaking Change
### Test Plan
1. Use the app!
### Release Notes
- [tlschema] Update props of `createTLSchema`
- [editor] Update props of `TldrawEditorConfig`
- [editor] Remove `App.getShapeUtilByType`
- [editor] Update `App.getShapeUtil` to take a type rather than a shape
---------
Co-authored-by: alex <alex@dytry.ch>
This PR stops collaborator cursors wobbling while viewport-following.
It's a **new wobble** that we haven't seen before! (It crept in at some
point)
It happens when these three things happen at the same time:
* You're following someone
* They're panning
* They're not moving their pointer
eg: This happens when they're trackpad-panning.
So this is *not* the **old wobble** that we fixed before! That one is
still fixed.
---
The **new wobble** looks like this:
![2023-05-22 at 12 08 51 - Magenta
Urial](https://github.com/tldraw/tldraw/assets/15892272/4b738766-cde3-4a9c-9169-76d622bec3bf)
It's sometimes hard-to-spot because of the _smoothing_ that we do.
When we drastically increase the strength of smoothing... the **new
wobble** is less noticeable:
![2023-05-22 at 12 12 40 - Rose
Goat](https://github.com/tldraw/tldraw/assets/15892272/4ece229a-60e8-4923-89f8-4a0f9b702491)
But we can do better!
So for demonstration purposes... let's turn off _smoothing_ to let us
see the **new wobble** more clearly.
![2023-05-22 at 12 16 02 - Gold
Macaw](https://github.com/tldraw/tldraw/assets/15892272/9030cf2a-bdf3-47f0-87f0-a1195ab2fcbf)
Now we can clearly see what's going on...
The cursor is updating every animation **frame**.
The camera is updating every **tick**.
Depending on your screen's refresh rate, these _might be different_!
Let's test that theory by throttling the **tick** further.
As expected, it increases the **new wobble**:
![2023-05-22 at 14 16 21 - Blush
Caterpillar](https://github.com/tldraw/tldraw/assets/15892272/c70ee08c-8fd3-40ae-a4b3-95637c08acc7)
Let's test the theory again by trying on a screen where the _tick_ and
_frame_ are in sync.
As expected, the **new wobble** doesn't happen _most of the time_.
However, _frame_ and _tick_ can still get out of sync! Which causes the
occasional wobble:
![2023-05-22 at 14 38 21 - Lime
Eagle](https://github.com/tldraw/tldraw/assets/15892272/2a9d8c98-194f-4b73-a7ea-ee85ac1fa28f)
So let's fix both cases...
Instead of making the following-camera update every _tick_...
Let's make it update every _frame_!
![2023-05-22 at 15 28 47 - Salmon
Smelt](https://github.com/tldraw/tldraw/assets/15892272/e9f5c10c-d421-4611-b049-7a961218c087)
The perceptive among you might notice a slight wobble that's still
there...
This is an entirely **different wobble** caused by different things.
We can get to it in the future! But we're back at our original
wobble-quota for now.
![2023-05-22 at 14 32 18 - Brown
Tern](https://github.com/tldraw/tldraw/assets/15892272/e1250715-0bf2-4b87-b6e7-a357bccf4106)
When we turn smoothing back on, things look better than before 👍
![2023-05-22 at 14 42 48 - Cyan
Roundworm](https://github.com/tldraw/tldraw/assets/15892272/f3616c6f-7969-4a8d-80b1-26ee44e6f451)
### Change Type
- [x] `patch` — Bug Fix
### Test Plan
1. Open a single shared project in two different browser sessions.
2. Make one session's user follow the other.
3. Trackpad-pan the leader's camera around.
4. Check that the wobble has reduced.
This PR moves our "fractical indices" library into its own package.
- [x] `major` — Breaking Change
### Release Notes
- [@tldraw/editor] Remove fractional indices code into `@tldraw/indices`
- [@tldraw/indices] Create library for fractional indices code
This PR fixes a bug in firefox where the pointer can get stuck down
while pressing the control key.
It achieves this by taking a previous fix (specifically for
`useShapeEvents`), and it applies the fix at a deeper level (within
`app.dispatch`).
## Before
![2023-05-16 at 15 33 02 - Crimson
Coyote](https://github.com/tldraw/tldraw/assets/15892272/7d4b5bb1-a2e5-400c-9935-fddcc9645e52)
## After
![2023-05-16 at 15 34 03 - Purple
Panda](https://github.com/tldraw/tldraw/assets/15892272/34a598b2-bf6d-4847-8ce9-a3d52c418174)
### Change Type
- [x] `patch` — Bug Fix
### Test Plan
1. Use firefox.
2. On the canvas... pointer down (to start a selection box).
3. Control key down.
4. Pointer up.
5. Make sure that that the selection box is gone.
^ Repeat the above for:
Pointer down on a shape.
Pointer down on a handle.
### Release Notes
- [Firefox] Fixed a bug where the pointer could get stuck down when the
control key is held down.
Forgot to port over my fix for viewport following for the new ephemeral
state stuff.
### Change Type
<!-- 💡 Indicate the type of change your pull request is. -->
<!-- 🤷♀️ If you're not sure, don't select anything -->
<!-- ✂️ Feel free to delete unselected options -->
<!-- To select one, put an x in the box: [x] -->
- [x] `patch` — Bug Fix
- [ ] `minor` — New Feature
- [ ] `major` — Breaking Change
- [ ] `dependencies` — Dependency Update (publishes a `patch` release,
for devDependencies use `internal`)
- [ ] `documentation` — Changes to the documentation only (will not
publish a new version)
- [ ] `tests` — Changes to any testing-related code only (will not
publish a new version)
- [ ] `internal` — Any other changes that don't affect the published
package (will not publish a new version)
### Test Plan
1. Open a multiplayer room in two different browsers
2. Open the people menu and click the follow button next to the other
user's name.
3. pan and zoom in the viewport of the user being followed
4. the other viewport should follow the same movements
We were storing the state of whether or not a document is read-only in
the store. It does not need to be stored there, and it was creating
consistency problems for us, so let's not store it in there.
fixes https://github.com/tldraw/brivate/issues/1864
### Change Type
<!-- 💡 Indicate the type of change your pull request is. -->
<!-- 🤷♀️ If you're not sure, don't select anything -->
<!-- ✂️ Feel free to delete unselected options -->
<!-- To select one, put an x in the box: [x] -->
- [ ] `patch` — Bug Fix
- [ ] `minor` — New Feature
- [x] `major` — Breaking Change
- [ ] `dependencies` — Dependency Update (publishes a `patch` release,
for devDependencies use `internal`)
- [ ] `documentation` — Changes to the documentation only (will not
publish a new version)
- [ ] `tests` — Changes to any testing-related code only (will not
publish a new version)
- [ ] `internal` — Any other changes that don't affect the published
package (will not publish a new version)
### Test Plan
1. Create a multiplayer room
2. Create a read-only link for the room
3. Paste the link into a new browser tab (not incognito, needs to have
the same session state)
4. Check the room is read-only in the new tab
5. Check the room is still writable in the previous tab.
### Release Notes
- Removes the isReadOnly value from the `user_document_settings` record
type.
Fix setting the grid mode. The change was never saved due to the wrong
condition.
Resolves#1385
### Change Type
- [x] `patch` — Bug Fix
### Test Plan
1. Go to Preferences -> Show grid.
2. It should allow you to toggle the display of the grid.
- [ ] Unit Tests
- [ ] Webdriver tests
### Release Notes
- Fix grid mode toggle.
This PR removes some commented code from the events PR.
### Change Type
- [x] `internal` — Any other changes that don't affect the published
package (will not publish a new version)
This PR extracts a static query for the page states that are used when
deleting a shape.
### Change Type
<!-- 💡 Indicate the type of change your pull request is. -->
<!-- 🤷♀️ If you're not sure, don't select anything -->
<!-- ✂️ Feel free to delete unselected options -->
<!-- To select one, put an x in the box: [x] -->
- [x] `patch` — Bug Fix
### Release Notes
- Perf improvement for deleting shapes in a document with lots of pages.
This cleans up a couple of assumptions about the state of the world that
break down in multiplayer contexts:
1. updated shapes still exist while redoing
2. redoing the delete of a page that I am on will also redo switching
away from that page
### Change Type
<!-- 💡 Indicate the type of change your pull request is. -->
<!-- 🤷♀️ If you're not sure, don't select anything -->
<!-- ✂️ Feel free to delete unselected options -->
<!-- To select one, put an x in the box: [x] -->
- [x] `patch` — Bug Fix
- [ ] `minor` — New Feature
- [ ] `major` — Breaking Change
- [ ] `dependencies` — Dependency Update (publishes a `patch` release,
for devDependencies use `internal`)
- [ ] `documentation` — Changes to the documentation only (will not
publish a new version)
- [ ] `tests` — Changes to any testing-related code only (will not
publish a new version)
- [ ] `internal` — Any other changes that don't affect the published
package (will not publish a new version)
### Release Notes
- Fixes a couple of minor consistency bugs affecting shape updating and
page deletion in multiplayer contexts.
This fixes a bug where creating a page would fail if there were multiple
pages with the same index.
This also changes the store to use a throttled version of
requestAnimationFrame. This should be good for relieving backpressure in
situations where the store is updated many times in quick succession. It
also makes testing a lot easier since it has the mocking logic built in.
### Change Type
- [x] `patch` — Bug Fix
### Release Notes
- Fix a bug where creating a page could throw an error in some
multiplayer contexts.
I need to mock nanoid for the ephemeral state fuzz tests, to create
repeatable test runs. In order to do that properly it needs to have a
consistent version among all our packages.
At the same time I'm removing some old unused params in AppOptions
### Change Type
<!-- 💡 Indicate the type of change your pull request is. -->
<!-- 🤷♀️ If you're not sure, don't select anything -->
<!-- ✂️ Feel free to delete unselected options -->
<!-- To select one, put an x in the box: [x] -->
- [ ] `patch` — Bug Fix
- [ ] `minor` — New Feature
- [x] `major` — Breaking Change
- [ ] `dependencies` — Dependency Update (publishes a `patch` release,
for devDependencies use `internal`)
- [ ] `documentation` — Changes to the documentation only (will not
publish a new version)
- [ ] `tests` — Changes to any testing-related code only (will not
publish a new version)
- [ ] `internal` — Any other changes that don't affect the published
package (will not publish a new version)
### Release Notes
- Remove unused userId and instanceId props from AppOptions
This PR adds a `check-box` geo shape.
![Kapture 2023-05-08 at 15 31
49](https://user-images.githubusercontent.com/23072548/236853749-99ba786f-73a4-4b65-86ca-f2cdac61a903.gif)
It also improves some logic around the `onClick` shape util handler and
some surprisingly related fixes to point hit testing.
### Test Plan
1. Create a geo shape
2. Set it as a checkbox style
3. *easter egg* double click while holding alt to toggle between
check-box and rectangle
- [x] Unit Tests
### Release Note
- Adds checkbox geo shape.
This PR has been hijacked! 🗑️🦝🦝🦝
The <Canvas> component was previously split into an <SVGLayer> and an
<HTMLLayer>, mainly due to the complexity around translating SVGs.
However, this was done before we learned that SVGs can have overflow:
visible, so it turns out that we don't really need the SVGLayer at all.
This PR now refactors away SVG Layer.
It also updates the class name prefix in editor from `rs-` to `tl-` and
does a few other small changes.
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>