Commit graph

427 commits

Author SHA1 Message Date
alex
ce782dc70b
Wrap local/session storage calls in try/catch (take 2) (#3066)
Steve tried this in #3043, but we reverted it in #3063. Steve's version
added `JSON.parse`/`JSON.stringify` to the helpers without checking for
where we were already `JSON.parse`ing (or not). In some places we just
store strings directly rather than wanting them jsonified, so in this
version we leave the jsonification to the callers - the helpers just do
the reading/writing and return the string values.

### Change Type

- [x] `patch` — Bug fix
2024-03-04 16:15:20 +00:00
alex
8adaaf8e22
Revert "Protect local storage calls (#3043)" (#3063)
This reverts commit 2f28d7c6f8.

### Change Type

- [x] `patch` — Bug fix
2024-03-04 15:48:31 +00:00
alex
15c760f7ea
children: any -> children: ReactNode (#3061)
We use `children: any` in a bunch of places, but the proper type for
these is `ReactNode`. This diff fixes those.

### Change Type

- [x] `patch` — Bug fix
2024-03-04 14:48:40 +00:00
Steve Ruiz
2f28d7c6f8
Protect local storage calls (#3043)
This PR provides some safe wrappers for local storage calls. Local
storage is not available in all environments (for example, a React
Native web view). The PR also adds an eslint rule preventing direct
calls to local / session storage.

### Change Type

- [x] `patch` — Bug fix

### Release Notes

- Fixes a bug that could cause crashes in React Native webviews.
2024-03-04 13:37:09 +00:00
Steve Ruiz
f819a57a05
Expose getStyleForNextShape (#3039)
This PR exposes a method for getting the style for the next shape.

### Change Type

- [x] `patch` — Bug fix

### Release Notes

- Expose the API for `Editor.getStyleForNextShape`, previously marked as
internal.
2024-03-02 20:16:55 +00:00
Steve Ruiz
52df06b014
A few more async routes (#3023)
This PR makes a few more of our routes async.

### Change Type

- [x] `internal` — Any other changes that don't affect the published
package[^2]
2024-03-02 17:17:09 +00:00
Steve Ruiz
338501d656
[fix] Routes check on e2e tests (#3022)
This PR updates our end to end tests so that they check every route in
our examples to ensure that it loads (skipping any routes that don't
features a canvas).

### Change Type

- [x] `tests` — Changes to any test code only[^2]

### Test Plan

- [x] End to end tests
2024-03-02 16:42:07 +00:00
Steve Ruiz
4cc823e22e
Show a broken image for files without assets (#2990)
This PR shows a broken state for images or video shapes without assets.
It deletes assets when pasted content fails to generate a new asset for
the shape. It includes some mild refactoring to the image shape.
Previously, shapes that had no corresponding assets would be
transparent. This PR preserves the transparent state for shapes with
assets but without source data (ie loading assets).

After:
<img width="1062" alt="image"
src="https://github.com/tldraw/tldraw/assets/23072548/81ad6953-a45f-4cc2-9f39-559009621a82">
<img width="1158" alt="image"
src="https://github.com/tldraw/tldraw/assets/23072548/40d15158-d201-458f-b555-6f3d8708a283">

Before:
<img width="1178" alt="image"
src="https://github.com/tldraw/tldraw/assets/23072548/2bed5b3c-cf1f-48be-9c68-d15fdccb9c99">


### Change Type

- [x] `patch` — Bug fix

### Test Plan

1. Create an image / video
2. Delete its asset

### Release Notes

- Better handling of broken images / videos.
2024-03-01 18:16:27 +00:00
Steve Ruiz
4bd1a31721
Selection UI example (plus fixes to pageToScreen) (#3015)
This PR adds a custom selection UI example.

![Kapture 2024-03-01 at 14 02
25](https://github.com/tldraw/tldraw/assets/23072548/039cc6ab-17b9-4bc3-8c05-ad3ce788a5d3)

It also fixes a bug with pageToScreen and adds a
`getSelectionRotatedScreenBounds` method.

### Change Type

- [ ] `patch` — Bug fix
- [x] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [ ] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version


### Release Notes

- Adds selection UI example.
- Adds `Editor.getSelectionRotatedScreenBounds` method
- Fixes a bug with `pageToScreen`.
2024-03-01 17:42:35 +00:00
David Sheldrick
1d5a9efa17
[bugfix] Avoid randomness at init time to allow running on cloudflare. (#3016)
Describe what your pull request does. If appropriate, add GIFs or images
showing the before and after.

Follow up to #2987 

### Change Type

- [x] `patch` — Bug fix


### Release Notes

- Prevent using randomness API at init time, to allow importing the
tldraw package in a cloudflare worker.
2024-03-01 15:34:16 +00:00
huppy-bot[bot]
ba6cba64c6 Update CHANGELOG.md [skip ci] 2024-02-29 18:28:45 +00:00
huppy-bot[bot]
ed1a031a69 Update CHANGELOG.md [skip ci] 2024-02-29 18:12:00 +00:00
David Sheldrick
a25d58e9b6 fix refresh-assets cache inputs 2024-02-29 18:03:10 +00:00
huppy-bot[bot]
752c30ac62 Update CHANGELOG.md [skip ci] 2024-02-29 17:59:47 +00:00
David Sheldrick
7fdaa3b7ed use glob to pick up version files? 2024-02-29 17:55:36 +00:00
huppy-bot[bot]
76949b62bd Update CHANGELOG.md [skip ci] 2024-02-29 17:45:47 +00:00
David Sheldrick
ba26324058
Fix publish script one more time (#3010)
follow up to #3009 

the versions.ts files were not being updated since things had been added
and moved around

### Change Type

- [ ] `patch` — Bug fix
- [ ] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [x] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: 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
- [ ] End to end tests

### Release Notes

- Add a brief release note for your PR here.
2024-02-29 17:38:19 +00:00
huppy-bot[bot]
21cc1c1345 Update CHANGELOG.md [skip ci] 2024-02-29 17:18:43 +00:00
David Sheldrick
9d237eec73
Fix publishing scripts (#3008)
Follow up to #3006 

### Change Type

- [ ] `patch` — Bug fix
- [ ] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [x] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: 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
- [ ] End to end tests

### Release Notes

- Add a brief release note for your PR here.
2024-02-29 16:59:05 +00:00
huppy-bot[bot]
a429a44e69 Update CHANGELOG.md [skip ci] 2024-02-29 16:41:45 +00:00
alex
a0628f9cb2
tldraw_final_v6_final(old version).docx.pdf (#2998)
Rename `@tldraw/tldraw` to just `tldraw`! `@tldraw/tldraw` still exists
as an alias to `tldraw` for folks who are still using that.

### Test Plan

- [x] Unit Tests
- [ ] End to end tests

### Release Notes

- The `@tldraw/tldraw` package has been renamed to `tldraw`. You can
keep using the old version if you want though!
2024-02-29 16:06:19 +00:00
Steve Ruiz
ae531da193
Don't add editor / app to window. (#2995)
This PR removes code that would add a reference to the editor to the
window. This is a feature that we added very early on during testing,
but which we should have moved out of the library earlier. Adding it
here as one of our last PRs before release.

If you've relied on this, you'll need to update your use of the library
to do it manually:

```ts
<Tldraw onMount={(editor) => {
  ;(window as any).app = editor
  ;(window as any).editor = editor
}}/>
```

### Change Type

- [x] `major` — Breaking change

### Release Notes

- Remove `window.editor` and `window.app` references to editor.
2024-02-29 15:42:36 +00:00
Steve Ruiz
4f07e696e8
[feature] wrap mode (#2938)
By default, tldraw's brushing mode will select when the box intersects
an shape's geometry. A user can hold Command / Ctrl to require that the
selection box fully contain a shape's bounds instead.

Some people really prefer the opposite. Three years! Three years I've
been saying "no no no".

This PR adds a user preference to flip the logic. When `isWrapMode` is
true, selection requires that the box completely contain a shape before
it's added to the list of selecting shapes; and ctrl flips back to
intersection instead.

### Change Type

- [x] `minor` — New feature

### Test Plan

1. Turn on wrap mode in the user preferences menu.
2. Select stuff.
3. Use the ctrl key to except the behavior back to intersection.

- [x] Unit Tests

### Release Notes

- Added `isWrapMode` to user preferences.
- Added Wrap Mode toggle to user preferences menu.
2024-02-29 11:45:02 +00:00
Mitja Bezenšek
adc53afbe3
Don't allow edge scrolling when camera is frozen. (#2992)
Don't allow edge scrolling when camera is frozen.

### Change Type

- [x] `patch` — Bug fix
- [ ] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [ ] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Testing
It's a bit hard to test this, you actually need to change the code a
bit.
1. Add an `onMount` handler to the `Tldraw` component in `develop.tsx`
2. In the `onMount` handler add:
`editor.updateInstanceState({canMoveCamera: false})` to freeze the
camera.
3. Make sure edge scrolling is turned on in the preferences.
4. Use brush selections / resizing / translating close to the edges.
5. The camera should not move.

### Release Notes

- Don't allow edge scrolling when camera is frozen.
2024-02-29 11:27:16 +00:00
David Sheldrick
a4033f7a61
Setup papercuts (#2987)
I'm bringing the sockets example up to date and ran into some issues
that were tricky to resolve in userland but trivial to resolve in
packageland.

Gonna collect them here.  

### Change Type

- [x] `patch` — Bug fix
- [ ] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [ ] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: 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
- [ ] End to end tests

### Release Notes

- Add a brief release note for your PR here.
2024-02-29 10:40:28 +00:00
Steve Ruiz
1a68857174
migrate shapes / assets as a store on putContent (#2971)
This PR updates the `putContentOntoCurrentPage` so that it migrates
shapes / records as a complete store.

### Change Type

- [x] `patch` — Bug fix

### Test Plan

1. Copy and paste, ideally between versions.
2024-02-27 16:35:01 +00:00
Steve Ruiz
d88ce929eb
[fix] double spinner (#2963)
Fixes a double spinner in the loading component.

### Change Type

- [x] `patch` — Bug fix
2024-02-27 09:30:02 +00:00
Steve Ruiz
6d417577be
Prevent iframe embedding for dotcom (except on tldraw.com) (#2947)
This PR fixes a check on whether the dot com multiplayer editor has been
loaded in an iframe.

It tries to keep it working on tldraw.com itself.

### Change Type

- [x] `patch` — Bug fix

### Test Plan

1. Load me in an iframe
2024-02-26 18:30:55 +00:00
Steve Ruiz
2211ca0063
bump typescript / api-extractor (#2949)
This PR bumps TypeScript to 5.3.3 and API extractor. We started getting
some weird behavior in CI due to different versions of the two
libraries, ie where the CI api.jsons would differ from those built
locally.

### Change Type

- [x] `dependencies` — Changes to package dependencies[^1]
2024-02-25 11:43:17 +00:00
Steve Ruiz
ad902be5e6
Expand props (#2948)
This PR expands the tldraw / tldraweditor component props.

### Change Type

- [x] `patch` — Bug fix
2024-02-25 11:16:10 +00:00
Steve Ruiz
0f1599d5b3
[fix] Corejs imports (#2940)
This PR fixes a bug with corejs imports. See
https://github.com/tldraw/tldraw/issues/1947

### Change Type

- [x] `patch` — Bug fix

### Release Notes

- Fixes a bug effecting some users related to corejs imports.
2024-02-23 17:36:27 +00:00
David Sheldrick
046ebc4ac0
Fix undo/redo for Opacity Slider + Style dropdowns. (#2933)
Closes #2664 and #2929 

### Change Type

- [x] `patch` — Bug fix

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: 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
- [ ] End to end tests

### Release Notes

- Fixed issues where undo/redo entries were not being set up correctly
for the opacity slider or the style dropdown menus.
2024-02-23 14:25:36 +00:00
huppy-bot[bot]
82527884ad Update CHANGELOG.md [skip ci] 2024-02-21 15:28:00 +00:00
David Sheldrick
987a576423
Check tsconfig "references" arrays (#2891)
Closes #2800

This PR makes it so that `check-scripts` will error out if you forget to
add a "references" entry to a tsconfig file when adding an internal
dependency in our monorepo.

If these project references are missed it can prevent TS from
building/rebuilding things when they need to be built/rebuilt.

### Change Type

- [x] `internal` — Any other changes that don't affect the published
package[^2]
2024-02-21 13:07:53 +00:00
Mime Čuvalo
f5f9da4f64
[experiment] paste: show little puff when pasting to denote something happened (#2787)
@steveruizok go ahead and take a look at the animation css and tweak as
you like.
@SomeHats and @steveruizok this is an experiment in that this is prbly
the wrong way to approach it? But I'd be curious to learn if there was a
more proper route here


https://github.com/tldraw/tldraw/assets/469604/40a7029c-f4e8-4f2a-914e-8e6f264be4c7

### Change Type

- [x] `patch` — Bug fix

### Release Notes

- UI: add a little 'puff' when something is pasted to tell that
something has happened.

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2024-02-21 10:46:57 +00:00
David Sheldrick
3e12b27728
Fix 'style panel doesn't always disappear if you switch to the hand/laser tools' (#2886)
We had some bad logic in `useRelevantStyles` explicitly allowing an
opacity-slider to be rendered at all times when there is at least one
shape selected.

This shouldn't be the case when the editor is in non-shape-focused tools
like the move tool and the laser pointer tool. I refactored the hook
slightly to make it easier to express the correct logic. See the comment
for a more detailed description.

### Change Type

- [x] `patch` — Bug fix


[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version


### Release Notes

- Fixes an bug causing the opacity slider to show up in the move tool
and laser pointer tool.
2024-02-20 15:09:45 +00:00
David Sheldrick
4a2040f92c
Faster validations + record reference stability at the same time (#2848)
This PR adds a validation mode whereby previous known-to-be-valid values
can be used to speed up the validation process itself. At the same time
it enables us to do fine-grained equality checking on records much more
quickly than by using something like lodash isEqual, and using that we
can prevent triggering effects for record updates that don't actually
alter any values in the store.

Here's some preliminary perf testing of average time spent in
`store.put()` during some common interactions

| task | before (ms) | after (ms) |
| ---- | ---- | ---- |
| drawing lines | 0.0403 | 0.0214 |
| drawing boxes | 0.0408 | 0.0348 |
| translating lines | 0.0352 | 0.0042 |
| translating boxes | 0.0051 | 0.0032 |
| rotating lines | 0.0312 | 0.0065 |
| rotating boxes | 0.0053 | 0.0035 |
| brush selecting boxes | 0.0200 | 0.0232 |
| traversal with shapes | 0.0130 | 0.0108 |
| traversal without shapes | 0.0201 | 0.0173 |

**traversal** means moving the camera and pointer around the canvas

#### Discussion

At the scale of hundredths of a millisecond these .put operations are so
fast that even if they became literally instantaneous the change would
not be human perceptible. That said, there is an overall marked
improvement here. Especially for dealing with draw shapes.

These figures are also mostly in line with expectations, aside from a
couple of things:

- I don't understand why the `brush selecting boxes` task got slower
after the change.
- I don't understand why the `traversal` tasks are slower than the
`translating boxes` task, both before and after. I would expect that
.putting shape records would be much slower than .putting pointer/camera
records (since the latter have fewer and simpler properties)

### Change Type

- [x] `patch` — Bug fix

### Test Plan

1. Add a step-by-step description of how to test your PR here.
2.

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- Add a brief release note for your PR here.
2024-02-20 12:35:25 +00:00
alex
50f77fe75c
[Snapping 6/6] Self-snapping API (#2869)
This diff adds a self-snapping API for handles. Self-snapping is used
when a shape's handles want to snap to the shape itself. By default,
this isn't allowed because moving the handle might move the snap point,
which creates a janky user experience.

Now, shapes can return customised versions of their normal handle
snapping geometry in these cases. As a bonus, line shapes now snap to
other handles on their own line!

### Change Type

- [x] `minor` — New feature

### Test Plan

1. Line handles should snap to other handles on the same line when
holding command

- [x] Unit Tests

### Release Notes

- Line handles now snap to other handles on the same line when holding
command

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2024-02-19 17:27:29 +00:00
Steve Ruiz
9fc5f4459f
Roundup fixes (#2862)
This one is a roundup of superficial changes, apologies for having them
in a single PR.

This PR:
- does some chair re-arranging for one of our hotter paths related to
updating shapes
- changes our type exports for editor components
- adds shape indicator to editor components
- moves canvas to be an editor component
- fixes a CSS bug with hinted buttons
- fixes CSS bugs with the menus
- fixes bad imports in examples

### Change Type

- [x] `major`
2024-02-19 14:52:43 +00:00
Mitja Bezenšek
b3d6af4454
Allow users to set document name and use it for exporting / saving (#2685)
Adds the ability to change document names in the top center part of the
UI. This mostly brings back the functionality we already had in the
past.

This is basically a port of what @SomeHats did a while back. I changed
the dropdown options and removed some of the things (we are not dealing
with network requests directly so some of that logic did not apply any
longer). We did have autosave back then, not sure if we want to bring
that back?

Changes the `exportAs` api, thus braking.

### Change Type

- [ ] `patch` — Bug fix
- [ ] `minor` — New feature
- [x] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [ ] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

1. Top center should now show a new UI element. It has a dropdown with a
few actions.
2. Double clicking the name should also start editing it.
3. The name should also be respected when exporting things. Not if you
select some shapes or a frame. In that case we still use the old names.
But if you don't have anything selected and then export / save a project
it should have the document name.

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- Allow users to name their documents.
2024-02-19 12:30:26 +00:00
Steve Ruiz
3e41c3acd7
[fix] grid, other insets (#2858)
Fix the grid and other insets, a few CSS cleanups.

### Change Type

- [x] `patch` — Bug fix

### Test Plan

1. Turn on the grid.

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- Fixes a bug with the grid not appearing.
2024-02-18 23:01:00 +00:00
Lu Wilson
212eb88480
Add component for viewing an image of a snapshot (#2804)
This PR adds the `TldrawImage` component that displays a tldraw snapshot
as an SVG image.

![2024-02-15 at 12 29 52 - Coral
Cod](https://github.com/tldraw/tldraw/assets/15892272/14140e9e-7d6d-4dd3-88a3-86a6786325c5)

## Why

We've seen requests for this kind of thing from users. eg: GitBook, and
on discord:

<img width="710" alt="image"
src="https://github.com/tldraw/tldraw/assets/15892272/3d3a3e9d-66b9-42e7-81de-a70aa7165bdc">

The component provides a way to do that.
This PR also untangles various bits of editor state from image
exporting, which makes it easier for library users to export images more
agnostically. (ie: they can now export any shapes on any page in any
theme. previously, they had to change the user's state to do that).

## What else

- This PR also adds an **Image snapshot** example to demonstrate the new
component.
- We now pass an `isDarkMode` property to the `toSvg` method (inside the
`ctx` argument). This means that `toSvg` doesn't have to rely on editor
state anymore. I updated all our `toSvg` methods to use it.
- See code comments for more info.

## Any issues?

When you toggle to editing mode in the new example, text measurements
are initially wrong (until you edit the size of a text shape). Click on
the text shape to see how its indicator is wrong. Not sure why this is,
or if it's even related. Does it ring a bell with anyone? If not, I'll
take a closer look. (fixed, see comments --steve)

## Future work

Now that we've untangled image exporting from editor state, we could
expose some more helpful helpers for making this easier.

Fixes tld-2122

### Change Type

- [x] `minor` — New feature

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

1. Open the **Image snapshot** example.
2. Try editing the image, saving the image, and making sure the image
updates.

- [ ] Unit Tests
- [ ] End to end tests

### Release Notes

- Dev: Added the `TldrawImage` component.

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2024-02-16 13:54:48 +00:00
Steve Ruiz
dd67577fea
[fix] pointer capture logging when debug flag is off (#2850)
This PR fixes a bug where pointer capture would log when the debug flag
was off.

### Change Type

- [x] `patch` — Bug fix
2024-02-16 10:41:27 +00:00
alex
89881397b5
[Snapping 4/5] Add handle-point snapping (#2841)
Currently, when dragging line handles they'll snap to the outlines of
other shapes, but not to their vertices. This can make it hard to snap
precisely to certain key places, like the handles of other lines, or the
corners of `geo` shapes.

This diff adds a new snap type for handles - snapping to points:

![Kapture 2024-02-14 at 16 30
41](https://github.com/tldraw/tldraw/assets/1489520/046109d3-2961-463f-bf71-9350ea1204bc)

This adds to the new snapping API so the snapping points can very easily
be customised on a shape-by-shape basis. Closes TLD-2198

This PR is part of a series - please don't merge it until the things
before it have landed!
1. #2827 
2. #2831
3. #2793 
4. #2841 (you are here)
5. #2845

### Change Type

- [x] `minor` — New feature

### Test Plan

1. create a line shape
2. drag its handles whilst holding command
3. it should snap to the outlines of other shapes, vertices of other
line shapes, and the bounding box corners/center of most 'boxy' shapes
(geo, embed, etc)

- [x] Unit Tests

### Release Notes

- Line handles
2024-02-15 15:22:48 +00:00
alex
77865d9f5e
[Snapping 3/5] Custom snapping API (#2793)
This diff adds an API for customising our existing snap types. These
are:
1. Bound snapping. When translating or resizing a shape, it'll snap to
certain key points on the bounds of particular shapes. Previously, these
were hard-coded to the corners and center of the bounding box of the
shape. Now, a shape can bring its own (e.g. a triangle may add snapping
for its 3 corners, and it's centroid rather than bounding box center.
2. Handle outline snapping. When dragging a handle, it'll snap to the
outline of other shapes geometry. Now, shapes can return different
geometry for this sort of snapping if they like.

Each of these is customised through a method on `ShapeUtil`:
`getBoundsSnapGeometry` and `getHandleSnapGeometry`. These return
interfaces describing the different geometry that can be snapped to in
both these cases. Currently, each returns an object with a single
property, but there are more types of snapping coming in follow-up PRs.
When reviewing this PR, start with the definitions of
`BoundsSnapGeometry` in `BoundsSnaps.ts` and `HandleSnapGeometry` in
`HandleSnaps.ts`

This doesn't add point snapping - i'll add that in a follow-up! It'll be
customisable with the `getHandleSnapGeometry` API.

Fixes TLD-2197

This PR is part of a series - please don't merge it until the things
before it have landed!
1. #2827 
4. #2831
5. #2793 (you are here)
6. #2841
7. #2845

### Change Type

- [x] `minor` — New feature

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

- [x] Unit Tests

### Release Notes

- Add `ShapeUtil.getSnapInfo` for customising shape snaps.
2024-02-15 15:10:04 +00:00
Steve Ruiz
ac0259a6af
Composable custom UI (#2796)
This PR refactors our menu systems and provides an interface to hide or
replace individual user interface elements.

# Background

Previously, we've had two types of overrides:
- "schema" overrides that would allow insertion or replacement of items
in the different menus
- "component" overrides that would replace components in the editor's
user interface

This PR is an attempt to unify the two and to provide for additional
cases where the "schema-based" user interface had begun to break down.

# Approach

This PR makes no attempt to change the `actions` or `tools`
overrides—the current system seems to be correct for those because they
are not reactive. The challenge with the other ui schemas is that they
_are_ reactive, and thus the overrides both need to a) be fed in from
outside of the editor as props, and b) react to changes from the editor,
which is an impossible situation.

The new approach is to use React to declare menu items. (Surprise!) 

```tsx
function CustomHelpMenuContent() {
	return (
		<>
			<DefaultHelpMenuContent />
			<TldrawUiMenuGroup id="custom stuff">
				<TldrawUiMenuItem
					id="about"
					label="Like my posts"
					icon="external-link"
					readonlyOk
					onSelect={() => {
						window.open('https://x.com/tldraw', '_blank')
					}}
				/>
			</TldrawUiMenuGroup>
		</>
	)
}

const components: TLComponents = {
	HelpMenuContent: CustomHelpMenuContent,
}

export default function CustomHelpMenuContentExample() {
	return (
		<div className="tldraw__editor">
			<Tldraw components={components} />
		</div>
	)
}
```

We use a `components` prop with the combined editor and ui components.

- [ ] Create a "layout" component?
- [ ] Make UI components more isolated? If possible, they shouldn't
depend on styles outside of themselves, so that they can be used in
other layouts. Maybe we wait on this because I'm feeling a slippery
slope toward presumptions about configurability.
- [ ] OTOH maybe we go hard and consider these things as separate
components, even packages, with their own interfaces for customizability
/ configurability, just go all the way with it, and see what that looks
like.

# Pros

Top line: you can customize tldraw's user interface in a MUCH more
granular / powerful way than before.

It solves a case where menu items could not be made stateful from
outside of the editor context, and provides the option to do things in
the menus that we couldn't allow previously with the "schema-based"
approach.

It also may (who knows) be more performant because we can locate the
state inside of the components for individual buttons and groups,
instead of all at the top level above the "schema". Because items /
groups decide their own state, we don't have to have big checks on how
many items are selected, or whether we have a flippable state. Items and
groups themselves are allowed to re-build as part of the regular React
lifecycle. Menus aren't constantly being rebuilt, if that were ever an
issue.

Menu items can be shared between different menu types. We'll are
sometimes able to re-use items between, for example, the menu and the
context menu and the actions menu.

Our overrides no longer mutate anything, so there's less weird searching
and finding.

# Cons

This approach can make customization menu contents significantly more
complex, as an end user would need to re-declare most of a menu in order
to make any change to it. Luckily a user can add things to the top or
bottom of the context menu fairly easily. (And who knows, folks may
actually want to do deep customization, and this allows for it.)

It's more code. We are shipping more react components, basically one for
each menu item / group.

Currently this PR does not export the subcomponents, i.e. menu items. If
we do want to export these, then heaven help us, it's going to be a
_lot_ of exports.

# Progress 

- [x] Context menu
- [x] Main menu
- [x] Zoom menu
- [x] Help menu
- [x] Actions menu
- [x] Keyboard shortcuts menu
- [x] Quick actions in main menu? (new)
- [x] Helper buttons? (new)
- [x] Debug Menu

And potentially
- [x] Toolbar
- [x] Style menu
- [ ] Share zone
- [x] Navigation zone
- [ ] Other zones

### Change Type

- [x] `major` — Breaking change

### Test Plan

1. use the context menu
2. use the custom context menu example
3. use cursor chat in the context menu

- [x] Unit Tests
- [ ] End to end tests

### Release Notes

- Add a brief release note for your PR here.
2024-02-15 12:10:09 +00:00
Mime Čuvalo
5faac660bc
errors: improve msg in dialog when error happens (#2844)
Right now it's hard to parse the stack trace to see what the problem is.
This just raises the msg up to a first-class position to get the gist of
the problem.

<img width="631" alt="Screenshot 2024-02-14 at 17 09 55"
src="https://github.com/tldraw/tldraw/assets/469604/d40b8bb4-e752-48d3-946d-6377c08e66fc">


### Change Type

- [x] `patch` — Bug fix

### Release Notes

- Improves error dialog messaging.
2024-02-15 11:35:42 +00:00
Mime Čuvalo
5bb60858b9
seo: take 2 (#2817)
(pending landing on: "Going to wait to land this one until the Google
SEO 'soft 404' validation finishes. I want to make sure we're testing
separate things.")

- removes Loading text
- adds sitemap to try to get Google to play nice

### Change Type

- [x] `patch` — Bug fix

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2024-02-15 11:28:43 +00:00
alex
4bfea7649d
[Snapping 2/5] Fix line-handle mid-point snapping (#2831)
Currently, only the end handles of the line tool snap. It should be all
of them.

Line handles work kind of weirdly at the moment: instead of just storing
the positions, we store full `TLHandle` objects complete with IDs,
`canSnap`/`canBind` properties, etc. Currently, all the handles get
written to the store with `canSnap: false`, when really it should be up
to the shape util to decide which handles are snappable.

This diff replaces the current handles map (from arbitrary ID to
`TLHandle`) with just the data we need: a map from index to x/y. The
extra information that the `Editor` needs for `TLHandle` is hydrated at
runtime (with `canSnap` set to `true` this time!)

Fixes TLD-2200

This PR is part of a series - please don't merge it until the things
before it have landed!
1. #2827 
2. #2831 (you are here)
3. #2793
4. #2841
5. #2845

### Change Type

- [x] `major` — Breaking change


[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version

### Test Plan

1. Create a funky line shape on tldraw.com
2. Paste it into staging and make sure it comes across ok
3. Make some funky line shape in staging - make sure you use dragging,
mid-point creation, and shift-clicking

- [x] Unit Tests

### Release Notes

- Simplify the contents of `TLLineShape.props.handles`
2024-02-15 10:27:55 +00:00
alex
93c2ed615c
[Snapping 1/5] Validation & strict types for fractional indexes (#2827)
Currently, we type our fractional index keys as `string` and don't have
any validation for them. I'm touching some of this code for my work on
line handles and wanted to change that:
- fractional indexes are now `IndexKey`s, not `string`s. `IndexKey`s
have a brand property so can't be used interchangeably with strings
(like our IDs)
- There's a new `T.indexKey` validator which we can use in our
validations to make sure we don't end up with nonsense keys.

This PR is part of a series - please don't merge it until the things
before it have landed!
1. #2827 (you are here)
2. #2831
3. #2793
4. #2841
5. #2845

### Change Type

- [x] `patch` — Bug fix

### Test Plan

1. Mostly relying on unit & end to end tests here - no user facing
changes.

- [x] Unit Tests
2024-02-14 17:53:30 +00:00