Wykres commitów

25 Commity (be93cc0eb6d8554d04273d67dbb2a08dfb8e469c)

Autor SHA1 Wiadomość Data
David Sheldrick be93cc0eb6
Revert "zoom to affected shapes after undo/redo" (#2310)
Reverts tldraw/tldraw#2293
2023-12-12 11:36:52 +00:00
David Sheldrick f7ae99dd1f
zoom to affected shapes after undo/redo (#2293)
This PR makes it so that any shapes affected by an undo/redo action,
along with any shapes that are selected after an undo/redo action, are
visible in the viewport.

### Change Type

- [x] `patch` — Bug fix


### Release Notes

- Make sure affected shapes are visible after undo/redo
2023-12-08 10:35:35 +00:00
David Sheldrick 34cfb85169
no impure getters pt 11 (#2236)
follow up to #2189 

adds runtime warnings for deprecated fields. cleans up remaining fields
and usages. Adds a lint rule to prevent access to deprecated fields.
Adds a lint rule to prevent using getters.

### Change Type

- [x] `patch` — Bug fix
2023-11-16 15:34:56 +00:00
David Sheldrick d683cc0943
No impure getters pt9 (#2222)
follow up to #2189 

### Change Type

- [x] `patch` — Bug fix
2023-11-14 17:07:35 +00:00
David Sheldrick dc0f6ae0f2
No impure getters pt8 (#2221)
follow up to #2189 
### Change Type

- [x] `patch` — Bug fix
2023-11-14 16:32:27 +00:00
Steve Ruiz 7186368f0d
StateNode atoms (#2213)
This PR extracts some improvements from #2198 into a separate PR.

### Release Notes
- adds computed `StateNode.getPath`
- adds computed StateNode.getCurrent`
- adds computed StateNode.getIsActive`
- adds computed `Editor.getPath()`
- makes transition's second property optional

### Change Type

- [x] `minor` — New feature

### Test Plan

- [x] Unit Tests
- [x] End to end tests
2023-11-14 13:02:50 +00:00
David Sheldrick 9d783f65cb
No impure getters pt5 (#2208)
Follow up to #2189 

### Change Type

- [x] `patch` — Bug fix
2023-11-14 10:23:03 +00:00
David Sheldrick daf729d45c
No impure getters pt4 (#2206)
follow up to #2189 and #2203 

### Change Type

- [x] `patch` — Bug fix
2023-11-13 16:02:50 +00:00
David Sheldrick 2ca2f81f2a
No impure getters pt2 (#2202)
follow up to #2189
2023-11-13 12:42:07 +00:00
Steve Ruiz 5db3c1553e
Replace Atom.value with Atom.get() (#2189)
This PR replaces the `.value` getter for the atom with `.get()`

### Change Type

- [x] `major` — Breaking change

---------

Co-authored-by: David Sheldrick <d.j.sheldrick@gmail.com>
2023-11-13 11:51:22 +00:00
Steve Ruiz da33179a31
Remove focus management (#1953)
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>
2023-10-02 11:29:54 +00:00
David Sheldrick 3d30f77ac1
Make user preferences optional (#1963)
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
2023-09-29 15:20:39 +00:00
Steve Ruiz 20704ea417
[fix] iframe losing focus on pointer down (#1848)
This PR fixes a bug that would cause an interactive iframe (e.g. a
youtube video) to lose its editing state once clicked.

### Change Type

- [x] `patch` — Bug fix

### Test Plan

1. Create an interactive iframe.
2. Begin editing.
3. Click inside of the iframe
2023-09-09 09:41:06 +00:00
Steve Ruiz 48a1bb4d88
Migrate snapshot (#1843)
Add `Store.migrateSnapshot`, another surface API alongside getSnapshot
and loadSnapshot.

### Change Type

- [x] `minor` — New feature

### Release Notes

- [editor] add `Store.migrateSnapshot`
2023-09-08 17:04:53 +00:00
Steve Ruiz 2c7c97af9c
[fix] style changes (#1814)
This PR updates the way that styles are changed. It splits `setStyle`
and `setOpacity` into `setStyleForNext Shape` and
`setOpacityForNextShape` and `setStyleForSelectedShapes` and
`setOpacityForSelectedShapes`. It fixes the issue with setting one style
re-setting other styles.

### Change Type

- [x] `major` — Breaking change

### Test Plan

1. Set styles when shapes are not selected.
2. Set styles when shapes are selected.
3. Set styles when shapes are selected and the selected tool is not
select.

- [x] Unit Tests
2023-08-23 10:14:49 +00:00
Steve Ruiz 22329c51fc
[improvement] More selection logic (#1806)
This PR includes further UX improvements to selection.

- clicking inside of a hollow shape will no longer select it on pointer
up
- clicking a shape's filled label will select it on pointer down
- clicking a shape's empty label will select it on pointer up
- clicking and dragging a selected arrow is now better limited to its
body, not its bounds
- arrows will no longer bind to labels

### Text labels

A big change here relates to text labels. Previously, we had listeners
set on the text label elements; I've removed these and we now check the
actual label bounds geometry for a hit. For geo shapes, this geometry is
now placed correctly based on the alignment / vertical alignment of the
label.

- Clicking on a label with text in it will select the shape on pointer
down.
- Clicking on an empty text label will select the shape on pointer up.

## Hollow shapes

Previously, shapes with `fill: none` were also being selected on pointer
up. I've removed that logic because it was producing wrong-feeling
selections too often. We now select these shapes only when clicking on
the label (as mentioned above) or when clicking on the edges of the
shape. This is in line with the original behavior (currently on
tldraw.com, prior to the earlier PR that updated selection logic).

## Arrows

Arrows still hit the inside of hollow shapes, using the "smallest
hovered" logic previously used for pointer-up selection on hollow
shapes. They also now correctly do so while ignoring text labels.

### Change Type

- [x] `minor` — New feature

### Test Plan

1. try selecting geo shapes, nested geo shapes, arrows and shapes with
labels or without labels

- [x] Unit Tests
2023-08-13 15:55:24 +00:00
Steve Ruiz 13ef8be58d
Cleanup page state commands (#1800)
This PR cleans up some APIs around the editor's current page state:

- `setEditingShapeId` -> `setEditingShape`
- `setHoveredShapeId` -> `setHoveredShape`
- `setCroppingShapeId` -> `setCroppingShape`
- `setFocusedGroupId` -> `setFocusedGroup`
- `setErasingShapeIds` -> `setErasingShapes`
- `setHintingShapeIds` -> `setHintingShapes`

It also adds some additional computed getters, e.g.
`Editor.croppingShape`.

It also adds some errors around `setCroppingShape`.

### Change Type

- [x] `major` — Breaking change

### Test Plan

- [x] Unit Tests
2023-08-06 12:05:35 +00:00
Steve Ruiz 8991468446
history options / markId / createPage (#1796)
This PR:

- adds history options to several commands in order to allow them to
support squashing and ephemeral data (previously, these commands had
boolean values for squashing / ephemeral)

It also:
- changes `markId` to return the editor instance rather than the mark id
passed into the command
- removes `focus` and `blur` commands
- changes `createPage` parameters
- unifies `animateShape` / `animateShapes` options

### Change Type

- [x] `major` — Breaking change

### Test Plan

- [x] Unit Tests
2023-08-05 11:21:07 +00:00
Steve Ruiz 2be738e0cc
Update setter names, `setXXShapeId` rather than `setXXId` (#1789)
This PR is a follower on #1787 that adds some changes to how setters are
named.

### Change Type

- [x] `major` — Breaking change
2023-08-03 14:10:41 +00:00
Steve Ruiz 79fae186e4
Revert "Editor commands API / effects" (#1783)
Reverts tldraw/tldraw#1778.

Fuzz testing picked up errors related to deleting pages and undo/redo
which may doom this PR.

### Change Type

- [x] `major` — Breaking change
2023-08-01 17:03:31 +00:00
Steve Ruiz e17074a8b3
Editor commands API / effects (#1778)
This PR shrinks the commands API surface and adds a manager
(`CleanupManager`) for side effects.

### Change Type

- [x] `major` — Breaking change

### Test Plan

Use the app! Especially undo and redo. Our tests are passing but I've
found more cases where our coverage fails to catch issues.

### Release Notes

- tbd
2023-08-01 13:21:14 +00:00
Steve Ruiz d750da8f40
`ShapeUtil.getGeometry`, selection rewrite (#1751)
This PR is a significant rewrite of our selection / hit testing logic.

It
- replaces our current geometric helpers (`getBounds`, `getOutline`,
`hitTestPoint`, and `hitTestLineSegment`) with a new geometry API
- moves our hit testing entirely to JS using geometry
- improves selection logic, especially around editing shapes, groups and
frames
- fixes many minor selection bugs (e.g. shapes behind frames)
- removes hit-testing DOM elements from ShapeFill etc.
- adds many new tests around selection
- adds new tests around selection
- makes several superficial changes to surface editor APIs

This PR is hard to evaluate. The `selection-omnibus` test suite is
intended to describe all of the selection behavior, however all existing
tests are also either here preserved and passing or (in a few cases
around editing shapes) are modified to reflect the new behavior.

## Geometry

All `ShapeUtils` implement `getGeometry`, which returns a single
geometry primitive (`Geometry2d`). For example:

```ts
class BoxyShapeUtil {
  getGeometry(shape: BoxyShape) {
    return new Rectangle2d({
        width: shape.props.width, 
        height: shape.props.height, 
        isFilled: true,
        margin: shape.props.strokeWidth
      })
    }
}
```

This geometric primitive is used for all bounds calculation, hit
testing, intersection with arrows, etc.

There are several geometric primitives that extend `Geometry2d`:
- `Arc2d`
- `Circle2d`
- `CubicBezier2d`
- `CubicSpline2d`
- `Edge2d`
- `Ellipse2d`
- `Group2d`
- `Polygon2d`
- `Rectangle2d`
- `Stadium2d`

For shapes that have more complicated geometric representations, such as
an arrow with a label, the `Group2d` can accept other primitives as its
children.

## Hit testing

Previously, we did all hit testing via events set on shapes and other
elements. In this PR, I've replaced those hit tests with our own
calculation for hit tests in JavaScript. This removed the need for many
DOM elements, such as hit test area borders and fills which only existed
to trigger pointer events.

## Selection

We now support selecting "hollow" shapes by clicking inside of them.
This involves a lot of new logic but it should work intuitively. See
`Editor.getShapeAtPoint` for the (thoroughly commented) implementation.

![Kapture 2023-07-23 at 23 27
27](https://github.com/tldraw/tldraw/assets/23072548/a743275c-acdb-42d9-a3fe-b3e20dce86b6)

every sunset is actually the sun hiding in fear and respect of tldraw's
quality of interactions

This PR also fixes several bugs with scribble selection, in particular
around the shift key modifier.

![Kapture 2023-07-24 at 23 34
07](https://github.com/tldraw/tldraw/assets/23072548/871d67d0-8d06-42ae-a2b2-021effba37c5)

...as well as issues with labels and editing.

There are **over 100 new tests** for selection covering groups, frames,
brushing, scribbling, hovering, and editing. I'll add a few more before
I feel comfortable merging this PR.

## Arrow binding

Using the same "hollow shape" logic as selection, arrow binding is
significantly improved.

![Kapture 2023-07-22 at 07 46
25](https://github.com/tldraw/tldraw/assets/23072548/5aa724b3-b57d-4fb7-92d0-80e34246753c)

a thousand wise men could not improve on this

## Moving focus between editing shapes

Previously, this was handled in the `editing_shapes` state. This is
moved to `useEditableText`, and should generally be considered an
advanced implementation detail on a shape-by-shape basis. This addresses
a bug that I'd never noticed before, but which can be reproduced by
selecting an shape—but not focusing its input—while editing a different
shape. Previously, the new shape became the editing shape but its input
did not focus.

![Kapture 2023-07-23 at 23 19
09](https://github.com/tldraw/tldraw/assets/23072548/a5e157fb-24a8-42bd-a692-04ce769b1a9c)

In this PR, you can select a shape by clicking on its edge or body, or
select its input to transfer editing / focus.

![Kapture 2023-07-23 at 23 22
21](https://github.com/tldraw/tldraw/assets/23072548/7384e7ea-9777-4e1a-8f63-15de2166a53a)

tldraw, glorious tldraw

### Change Type

- [x] `major` — Breaking change

### Test Plan

1. Erase shapes
2. Select shapes
3. Calculate their bounding boxes

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

### Release Notes

- [editor] Remove `ShapeUtil.getBounds`, `ShapeUtil.getOutline`,
`ShapeUtil.hitTestPoint`, `ShapeUtil.hitTestLineSegment`
- [editor] Add `ShapeUtil.getGeometry`
- [editor] Add `Editor.getShapeGeometry`
2023-07-25 16:10:15 +00:00
Steve Ruiz b22ea7cd4e
More cleanup, focus bug fixes (#1749)
This PR is another grab bag:
- renames `readOnly` to `readonly` throughout editor
- fixes a regression related to focus and keyboard shortcuts
- adds a small outline for focused editors

### Change Type

- [x] `major`

### Test Plan

- [x] End to end tests
2023-07-19 10:52:21 +00:00
Steve Ruiz 3e31ef2a7d
Remove helpers / extraneous API methods. (#1745)
This PR removes several extraneous computed values from the editor. It
adds some silly instance state onto the instance state record and
unifies a few methods which were inconsistent. This is fit and finish
work 🧽

## Computed Values

In general, where once we had a getter and setter for `isBlahMode`,
which really masked either an `_isBlahMode` atom on the editor or
`instanceState.isBlahMode`, these are merged into `instanceState`; they
can be accessed / updated via `editor.instanceState` /
`editor.updateInstanceState`.

## tldraw select tool specific things

This PR also removes some tldraw specific state checks and creates new
component overrides to allow us to include them in tldraw/tldraw.

### Change Type

- [x] `major` — Breaking change

### Test Plan

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

### Release Notes

- [tldraw] rename `useReadonly` to `useReadOnly`
- [editor] remove `Editor.isDarkMode`
- [editor] remove `Editor.isChangingStyle`
- [editor] remove `Editor.isCoarsePointer`
- [editor] remove `Editor.isDarkMode`
- [editor] remove `Editor.isFocused`
- [editor] remove `Editor.isGridMode`
- [editor] remove `Editor.isPenMode`
- [editor] remove `Editor.isReadOnly`
- [editor] remove `Editor.isSnapMode`
- [editor] remove `Editor.isToolLocked`
- [editor] remove `Editor.locale`
- [editor] rename `Editor.pageState` to `Editor.currentPageState`
- [editor] add `Editor.pageStates`
- [editor] add `Editor.setErasingIds`
- [editor] add `Editor.setEditingId`
- [editor] add several new component overrides
2023-07-18 21:50:23 +00:00
Steve Ruiz b7d9c8684c
tldraw zero - package shuffle (#1710)
This PR moves code between our packages so that:
- @tldraw/editor is a “core” library with the engine and canvas but no
shapes, tools, or other things
- @tldraw/tldraw contains everything particular to the experience we’ve
built for tldraw

At first look, this might seem like a step away from customization and
configuration, however I believe it greatly increases the configuration
potential of the @tldraw/editor while also providing a more accurate
reflection of what configuration options actually exist for
@tldraw/tldraw.

## Library changes

@tldraw/editor re-exports its dependencies and @tldraw/tldraw re-exports
@tldraw/editor.

- users of @tldraw/editor WITHOUT @tldraw/tldraw should almost always
only import things from @tldraw/editor.
- users of @tldraw/tldraw should almost always only import things from
@tldraw/tldraw.

- @tldraw/polyfills is merged into @tldraw/editor
- @tldraw/indices is merged into @tldraw/editor
- @tldraw/primitives is merged mostly into @tldraw/editor, partially
into @tldraw/tldraw
- @tldraw/file-format is merged into @tldraw/tldraw
- @tldraw/ui is merged into @tldraw/tldraw

Many (many) utils and other code is moved from the editor to tldraw. For
example, embeds now are entirely an feature of @tldraw/tldraw. The only
big chunk of code left in core is related to arrow handling.

## API Changes

The editor can now be used without tldraw's assets. We load them in
@tldraw/tldraw instead, so feel free to use whatever fonts or images or
whatever that you like with the editor.

All tools and shapes (except for the `Group` shape) are moved to
@tldraw/tldraw. This includes the `select` tool.

You should use the editor with at least one tool, however, so you now
also need to send in an `initialState` prop to the Editor /
<TldrawEditor> component indicating which state the editor should begin
in.

The `components` prop now also accepts `SelectionForeground`.

The complex selection component that we use for tldraw is moved to
@tldraw/tldraw. The default component is quite basic but can easily be
replaced via the `components` prop. We pass down our tldraw-flavored
SelectionFg via `components`.

Likewise with the `Scribble` component: the `DefaultScribble` no longer
uses our freehand tech and is a simple path instead. We pass down the
tldraw-flavored scribble via `components`.

The `ExternalContentManager` (`Editor.externalContentManager`) is
removed and replaced with a mapping of types to handlers.

- Register new content handlers with
`Editor.registerExternalContentHandler`.
- Register new asset creation handlers (for files and URLs) with
`Editor.registerExternalAssetHandler`

### Change Type

- [x] `major` — Breaking change

### Test Plan

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

### Release Notes

- [@tldraw/editor] lots, wip
- [@tldraw/ui] gone, merged to tldraw/tldraw
- [@tldraw/polyfills] gone, merged to tldraw/editor
- [@tldraw/primitives] gone, merged to tldraw/editor / tldraw/tldraw
- [@tldraw/indices] gone, merged to tldraw/editor
- [@tldraw/file-format] gone, merged to tldraw/tldraw

---------

Co-authored-by: alex <alex@dytry.ch>
2023-07-17 21:22:34 +00:00