This PR fixes a bug that causes menus not to close correctly when open.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. On mobile, open the menu.
2. Tap the canvas—it should close the panel.
3. Open the mobile style panel.
4. Tap the canvas—it should close the panel.
5. Open the mobile style panel.
6. Tap the mobile style panel button—it should close the panel.
7. On mobile, long press to open the context menu
### Release Notes
- [fix] bug with menus
This PR removes some calls to `findLast`, as this is not in all browsers
yet.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Drag and drop.
2. Create a shape inside of a frame
- [x] Unit Tests
Bumps nanoid to bring in line with brivate to make sure our nanoid mock
in our fuzz test works. Supersedes
https://github.com/tldraw/brivate/pull/3027#pullrequestreview-1676280991
### Change Type
- [ ] `patch` — Bug fix
- [ ] `minor` — New feature
- [ ] `major` — Breaking change
- [x] `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
This PR fixes a bug where the indicator on a locked group (or any
shape!) would not appear when the shape was unlocked. This happens
because the `memo` equality checker filtered out changes to the shape's
locked property if they did not effect any other properties.
![Kapture 2023-10-13 at 14 44
31](https://github.com/tldraw/tldraw/assets/23072548/c40442e0-8d18-4ed0-863c-c2b73da81f28)
### Change Type
- [x] `patch` — Bug fix
### Release Notes
- Fix case where indicator was not shown when unlocking groups
This PR fixes (or rather buries) a bug that could occur when the parents
to children array includes shapes that no longer exist.
### Change Type
- [x] `patch` — Bug fix
This PR allows locked shapes to be reparented. This fixes a bug where
grouped and locked shapes would disappear when their parent group would
be ungrouped.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Create two shapes.
2. Group the shapes.
3. Lock one shape.
4. Ungroup the group
- [x] Unit Tests
### Release Notes
- Fix a bug where grouped locked shapes would be deleted when ungrouped.
Closes#2051
This was another bug related to the usage of parent-scope `let`
assignments to avoid stack allocations in a hot code path, so I switched
to `const`s and local `let`s which we really should have done last week.
I think the compiler should be able to optimize this well enough.
### 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
- Fixes opacity of shapes while erasing in a group or frame.
This PR fixes a bug where certain hit tests would always miss straight
lines.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Create a straight line.
2. Try to bind an arrow to it.
- [x] Unit Tests
### Release Notes
- [fix] Bug where arrows would not bind to straight lines
Previously, entering a geo shape and adding a bunch of newlines wouldn't
correctly update the shape's height. This fixes that.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Create a geo shape
2. Enter text editing mode
3. Spam the enter key
4. See that the shape grows appropriately
5. Exit editing and check that the trailing newlines have been deleted.
- [ ] Unit Tests
- [x] End to end tests
---------
Co-authored-by: huppy-bot[bot] <128400622+huppy-bot[bot]@users.noreply.github.com>
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This PR:
1. Adds a `renderingOnly` option to the `Editor.getShapeAtPoint` method.
When true, the method will only hit test against rendering shapes
(shapes that are inside of the current `renderingBounds`) rather than
all shapes on the canvas.
2. Includes some low level improvements to the way that edges find their
nearest point.
3. Includes a fix to circle geometry that could produce NaN values
### Change Type
- [x] `minor` — New feature
### Test Plan
1. Check whether hovering shapes still works as you would expect.
- [x] Unit Tests
### Release Notes
- Improve perf for hovering shapes / shape hit tests
Before the geometry change, we'd rely on the browser to tell us which
element was hovered, which meant that when the pointer left the canvas
we'd automatically clear the hovered shape.
Currently, we don't know whether the pointer is over the canvas or not -
so we keep showing the hover indicator for the last shape you had your
pointer over.
This diff adds an `isHoveringCanvas` prop to the instance state (true,
false, or null if the current pointer doesn't support hovering) that we
can use to track this and disable the hover indicator appropriately.
![Kapture 2023-10-05 at 12 00
00](https://github.com/tldraw/tldraw/assets/1489520/236b9459-878b-47e2-bcaa-10d245581347)
### Change Type
- [x] `minor` — New feature
### Test Plan
1. Create some shapes that go below the UI
2. Move the mouse from the shape to the UI
3. Hover indicator should disappear
This PR:
- removes feature flags for people menu, highlighter shape
- removes debugging for cursors
- adds a debug flag for hiding shapes
- changes Canvas to use `useValue` rather than `track`
- removes the default background color on `tl-background`
- in the editor components, makes `Background` null by default
### Change Type
- [x] `minor` — New feature
There are a lot of cases (eg when interacting with the ui) where the
editor loses focus. This check was preventing us from updating the
viewport screen bounds when appropriate. This function is throttled and
pretty cheap anyway (if the viewport is equal its a no-op) so let's just
remove the condition
### Change Type
- [x] `patch` — Bug fix
Frame labels lost their editing outline at some point. 🤷🏼 any idea how
this happened?
## Before
![Kapture 2023-10-04 at 13 47
28](https://github.com/tldraw/tldraw/assets/1242537/5da612e3-6456-493d-a4d7-4a5b953284bb)
## After
![Kapture 2023-10-04 at 13 49
55](https://github.com/tldraw/tldraw/assets/1242537/1608af3b-aac8-4f1c-8a9b-09aab19b07fb)
### 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.
This PR restores the controlled nature of focus. Focus allows keyboard
shortcuts and other interactions to occur. The editor's focus should
always / entirely be controlled via the autoFocus prop or by manually
setting `editor.instanceState.isFocused`.
Design note: I'm starting to think that focus is the wrong abstraction,
and that we should instead use a kind of "disabled" state for editors
that the user isn't interacting with directly. In a page where multiple
editors exit (e.g. a notion page), a developer could switch from
disabled to enabled using a first interaction.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
- [x] End to end tests
We got things sliggghhhtly wrong in #1980. That diff was attempting to
fix a bug where the text measurement element would refuse to go above
the viewport size in safari. This was most obvious in the case where
there was no fixed width on a text shape, and that diff fixed that case,
but it was also happening when a fixed width text shape was wider than
viewport - which wasn't covered by that fix. It turned out that that fix
also introduced a bug where shapes would no longer grow along the y-axis
- in part because the relationship between `width`, `maxWidth`, and
`minWidth` is very confusing.
The one-liner fix is to just use `max-content` instead of `fit-content`
- that way, the div ignores the size of its container. But I also
cleared up the API for text measurement to remove the `width` property
entirely in favour of `maxWidth`. I think this makes things much clearer
and as far as I can tell doesn't affect anything.
Closes#1998
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Create an arrow & geo shape with labels, plus a note and text shape
2. Try to break text measurement - overflow the bounds, make very wide
text, experiment with fixed/auto-size text, etc.
Fixes an issue with creating arrows. Currently we create an arrow that
has both `start` and `end` handles set to the same point. This causes
`NaN` issues in some of our functions / svg rendering. After this change
we only create the arrow after we start dragging, which ensures the
start and the end handle won't have the same coordinates. This probably
feels the best way to approach it: arrow of length 0 doesn't really make
sense.
Resolves [#2005](https://github.com/tldraw/tldraw/issues/2005)
Before
https://github.com/tldraw/tldraw/assets/2523721/6e83c17e-21bd-4e0a-826b-02fad9c21ec6
After
https://github.com/tldraw/tldraw/assets/2523721/29359936-b673-4583-89c8-6d1728ab338c
### 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. Create an arrow.
2. You should not see any errors in the console.
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This PR prevents certain shapes from being edited while in readonly
mode. It adds `ShapeUtil.canEditInReadOnly` to allow developers to opt
in to editing shapes. It's currently applied only to embed shapes.
### Change Type
- [x] `major`
### Test Plan
1. In a readonly mode, try to edit text / sticky notes / arrow labels
via double click / enter. You should not be able to edit them.
2. Try to edit an embed. You should be able to edit it.
### Release Notes
- Prevent editing text shapes in readonly mode.
@SomeHats I'll leave this assigned to you in case you want to compare
the perf of using consts/lets scoped to the visitor function. Or just do
that anyway regardless of microperf. Either is fine with me.
This PR prevents the escape key from exiting full screen when a shape is
being edited or when shapes are selected. Basically, if the select tool
is going to use the escape key, then don't let it be used for its normal
purpose.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Open a firefox full screen tab.
2. Start editing a text shape.
3. Press escape. It should stop editing.
4. Press escape again. It should deselect the shape.
5. Press escape again. It should exit full screen mode.
This PR hides hovered indicators when using a coarse pointer.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. On an iPad or touch device, use the draw tool.
2. Select the select tool.
3. You should not see the hovered indicator on the drawn shape.
### Release Notes
- Hide hovered indicators on mobile / coarse pointer devices.
This PR improves pinch events on touch screens.
It tries to avoid zooming unless we're sure that the user is zooming (or
at least, that they've started zooming). It removes behavior that snaps
the pinch to a certain zoom (e.g. 100%, 50%).
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. On iPad, try to two-finger pan without zooming.
2. Perform a zoom.
3. Perform a two-finger pan, then a zoom.
### Release Notes
- Improve pinch gesture events.
Co-authored-by: Alex Alex@dytry.ch
closes [#1978](https://github.com/tldraw/tldraw/issues/1978)
Text was wrapping on Safari because the measure text div was rendered
differently on different browsers. Interestingly, when forcing the
text-measure div to be visible and on-screen in Chrome, the same
text-wrapping behaviour was apparent. By setting white-space to 'pre'
when width hasn't been set by the user, we can ensure that only line
breaks the user has inputted are rendered by default on all browsers.
### 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. On Safari
2. Make a new text shape and start typing
3. At a certain point the text starts to wrap without the width having
been set
### Release Notes
- Fix text wrapping differently on Safari and Chrome/Firefox
Before/After
<image width="350"
src="https://github.com/tldraw/tldraw/assets/98838967/320171b4-61e0-4a41-b8d3-830bd90bea65">
<image width="350"
src="https://github.com/tldraw/tldraw/assets/98838967/b42d7156-0ce9-4894-9692-9338dc931b79">
This PR removes the automatic focus events from the editor.
The `autoFocus` prop is now true by default. When true, the editor will
begin in a focused state (`editor.instanceState.isFocused` will be
`true`) and the component will respond to keyboard shortcuts and other
interactions. When false, the editor will begin in an unfocused state
and not respond to keyboard interactions.
**It's now up to the developer** using the component to update
`isFocused` themselves. There's no predictable way to do that on our
side, so we leave it to the developer to decide when to turn on or off
focus for a container (for example, using an intersection observer to
"unfocus" components that are off screen).
### Change Type
- [x] `major` — Breaking change
### Test Plan
1. Open the multiple editors example.
2. Click to focus each editor.
3. Use the keyboard shortcuts to check that the correct editor is
focused.
4. Start editing a shape, then select the other editor. The first
editing shape should complete.
- [x] Unit Tests
- [x] End to end tests
### Release Notes
- [editor] Make autofocus default, remove automatic blur / focus events.
---------
Co-authored-by: David Sheldrick <d.j.sheldrick@gmail.com>
This PR fixes some cases where, if a member function (like `onEnter`)
was not an arrow function, it would not run.
### Change Type
- [x] `patch` — Bug fix
This PR makes it so that user preferences can be in a 'null' state,
where we use the default values and/or infer from the system
preferences.
Before this PR it was impossible to allow a user to change their locale
via their system config rather than selecting an explicit value in the
tldraw editor menu. Similarly, it was impossible to adapt to changes in
the user's system preferences for dark/light mode.
That's because we saved the full user preference values the first time
the user loaded tldraw, and the only way for them to change after that
is by saving new values.
After this PR, if a value is `null` we will use the 'default' version of
it, which can be inferred based on the user's system preferences in the
case of dark mode, locale, and animation speed. Then if the user changes
their system config and refreshes the page their changes should be
picked up by tldraw where they previously wouldn't have been.
Dark mode inference is opt-in by setting a prop `inferDarkMode: true` on
the `Editor` instance (and the `<Tldraw />` components), because we
don't want it to be a surprise for existing library users.
### Change Type
- [ ] `patch` — Bug fix
- [ ] `minor` — New feature
- [x] `major` — Breaking change
[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version
This PR fixes not being able to right-click the selection background of
shapes.
* It still lets you right-click outside of a selection to deselect.
* It still lets you right-click a different shape inside the selection
bounds.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Draw a squiggle.
2. Select it.
3. Right-click somewhere inside the selection bounds (but NOT on the
squiggle itself).
4. The context menu should open.
- [ ] Unit Tests
- [ ] End to end tests
### Release Notes
- Improved right click behaviour.
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This PR fixes the text label placement for geo shapes. (It also fixes
the way an ellipse renders when set to dash or dotted).
There's still the slightest offset of the text label's outline when you
begin editing. Maybe we should keep the indicator instead?
### Change Type
- [x] `patch` — Bug fix
### Test Plan
Create a hexagon shape
hit enter to type
indicator is offset, text label is no longer offset
---------
Co-authored-by: David Sheldrick <d.j.sheldrick@gmail.com>
Previously, if a shape had two frame parents and those frames didn't
intersect, we'd render the shape without any clipping. This is because
in the case that we don't find an intersection we were returning
undefined (meaning nothing is masked out) instead of an empty array
(meaning everything is masked out)
![Kapture 2023-09-19 at 16 34
08](https://github.com/tldraw/tldraw/assets/1489520/3192c3df-5a71-4dea-a720-6319a803cd1c)
Fixes#1933
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. create a frame (A)
2. create a shape (B) to the left of frame A
3. create a frame (C) with another shape (D) inside to the left of shape
B
4. select shape B and frame C
5. drag shape B into frame A
6. make sure both frame C and shape D are completely clipped
Currently, the highlighter shape uses a single 0-width line for its
geometry, same as the draw tool. For the draw tool this works ok - the
visual line is thin enough that unless you zoom right in, it's hard to
find areas where the hover should trigger but isn't. As the highlighter
tool is much thicker though, it's relatively easy to find those areas.
The fix is for the geometry to represent the line including its thick
stroke, instead of at 0-width. There are two possible approaches here:
1. Update the polyline geometry to allow passing a stroke width.
2. Instead of a polyline, make the highlighter shape be a polygon that
traces _around_ the stroke
1 is the more accurate approach, but is hard to fit into our geometry
system. Our geometry is based around two primitives: `getVertices` which
returns an array of points around the shape, and `nearestPoint` which
returns the nearest point on the geometry to a vector we pass in. We can
account for a stroke in `nearestPoint` pretty easily, including it in
`getVertices` is hard - we'd have to expand the vertices and handle line
join/caps etc. Just making the change in `nearestPoint` does fix the
issue here, but i'm not sure about the knock-on effect elsewhere and
don't really want to introduce 1-off hacks into the core geometry
system.
2 actually means addressing the same hard problem around outlining
strokes as 1, but it lets us do it in a more tightly-scoped one-off
change just to the highlighter shape, instead of trying to come up with
a generic solution for the whole geometry system. This is the approach
I've taken in this diff. We outline the stroke using perfect-freehand,
which works pretty well but produces inaccurate results at edge-cases,
particularly when a line rapidly changes direction:
![Kapture 2023-09-19 at 13 45
01](https://github.com/tldraw/tldraw/assets/1489520/1593ac5c-e7db-4360-b97d-ba66cdfb5498)
I think that given this is scoped to just the highlighter shape and is
imo an improvement over the stroke issue from before, it's a reasonable
solution for now. If we want to in the future we could implement real
non-freehand-based outlining.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Create a highlight shape
2. Zoom in
3. Make sure you can interact with the shape at its edges instead of
right in the center
This PR adds the source items from a paste event to the data shared with
external content handlers. This allows developers to customize the way
certain content is handled.
For example, pasting text sometimes incudes additional clipboard items,
such as the HTML representation of that text. We wouldn't want to create
two shapes—one for the text and one for the HTML—so we still treat this
as a single text paste. The `registerExternalContentHandler` API allows
a developer to change how that text is handled, and the new `sources`
API will now allow the developer to take into consideration all of the
items that were on the clipboard.
![Kapture 2023-09-19 at 12 25
52](https://github.com/tldraw/tldraw/assets/23072548/fa976320-cfec-4921-b481-10cae0d4043e)
### Change Type
- [x] `minor` — New feature
### Test Plan
1. Try the external content source example.
2. Paste text that includes HTML (e.g. from VS Code)
### Release Notes
- [editor / tldraw] add `sources` to `TLExternalContent`
This prevents geometry from being recalculated when dragging shapes
around. It uses an equality check on the shape props to opt out of
recalculations. This still allows bounds to be calculated based on other
reactive values, so if folks really want to use x,y values or opacity or
whatever, they can call editor.getShape(id) when making their
calculation.
### 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
### Release Notes
- Fixes a perf regression for dragging shapes around
This is a follow up to #1915 which caused the shape container div
dimensions to be wildly inaccurate. We thought it wouldn't matter but we
had a note on discord from someone who was relying on the div container
being accurate.
This rounds the shape dimensions to the nearest integer that is
compatible with the user's device pixel ratio, using the method
pioneered in #1858 (thanks @BrianHung)
### 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
### Release Notes
- Improves the precision of the shape dimensions rounding logic
closes: #1884
Fix bug: ungroup when moving a shape in a group in a frame.
### before
https://github.com/tldraw/tldraw/assets/24749358/994a871a-5da2-4d8b-b80e-a4db43e66142
### after
https://github.com/tldraw/tldraw/assets/24749358/4395d416-b7f6-4af0-a4c2-0bf77c29d7e2
### 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
- Fix bug: ungroup when moving a shape in a group in a frame.
---------
Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
Co-authored-by: David Sheldrick <d.j.sheldrick@gmail.com>
Closes#1911
### 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
- Fixes an issue where lines would wobble as you dragged the handles
around
This PR fixes right clicks.
### Change Type
- [x] `patch` — Bug fix
### Test Plan
1. Right click a shape. The context menu should show information
relevant to the shape.
2. Lock a shape.
3. Right click to get to the unlock from the context menu.
This PR:
- adds `canSnap` as a property to handle and ignores snapping when
dragging a handle that does not have `canSnap` set to true. Arrows no
longer snap.
- adds `isLabel` to Geometry2d
- fixes selection on empty text labels
- fixes vertices / snapping for empty text labels
### Change Type
- [x] `minor` — New feature
### Test Plan
- [x] Unit Tests