tldraw 5.2.0 → 5.3.0-canary.263f9dbe88bb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +2 -1
- package/RELEASE_NOTES.md +66 -2
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +1 -1
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +1 -1
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js +6 -2
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +1 -1
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +1 -1
- package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/crop.js +61 -15
- package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +1 -1
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +70 -16
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
- package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js +33 -4
- package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +2 -7
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +1 -2
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -2
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +1 -2
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +1 -2
- package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/crop.mjs +61 -15
- package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +1 -2
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +75 -17
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
- package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs +34 -5
- package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/package.json +4 -4
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +3 -8
- package/src/lib/shapes/geo/toolStates/Pointing.ts +2 -2
- package/src/lib/shapes/line/LineShapeUtil.test.tsx +121 -0
- package/src/lib/shapes/line/LineShapeUtil.tsx +10 -2
- package/src/lib/shapes/line/toolStates/Pointing.ts +2 -2
- package/src/lib/shapes/note/toolStates/Pointing.ts +2 -2
- package/src/lib/shapes/shared/crop.ts +75 -16
- package/src/lib/shapes/text/toolStates/Pointing.ts +2 -2
- package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +103 -18
- package/src/lib/ui/components/HelperButtons/BackToContent.tsx +49 -5
- package/src/lib/ui/version.ts +3 -3
- package/src/test/crop.test.ts +141 -0
- package/src/test/cropping.test.ts +102 -0
- package/src/test/modifiers.test.ts +16 -0
- package/src/test/ui/BackToContent.test.tsx +98 -19
package/DOCS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# tldraw Documentation
|
|
2
2
|
|
|
3
|
-
Version: `5.
|
|
3
|
+
Version: `5.3.0-canary.263f9dbe88bb`
|
|
4
4
|
|
|
5
5
|
This file is generated during package publishing from the tldraw docs content for this exact package version.
|
|
6
6
|
|
|
@@ -383,6 +383,7 @@ We ship an experimental `tldraw-migrate` agent skill that helps a coding agent u
|
|
|
383
383
|
|
|
384
384
|
#### v5.x
|
|
385
385
|
|
|
386
|
+
- [v5.2](https://tldraw.dev/releases/v5.2.0) - Faster freehand ink, a frame selection action, SDK-wide performance improvements, and breaking changes to the collaborator user-id types and Node support
|
|
386
387
|
- [v5.1](https://tldraw.dev/releases/v5.1.0) - Page menu redesign, copy-styles shortcut, selectable locked shapes, public translation APIs, and performance improvements
|
|
387
388
|
- [v5.0](https://tldraw.dev/releases/v5.0.0) - Custom themes, overlays, performance, extensiblity, and attribution
|
|
388
389
|
|
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
-
Version: `5.
|
|
3
|
+
Version: `5.3.0-canary.263f9dbe88bb`
|
|
4
4
|
|
|
5
5
|
This file is generated during package publishing from the tldraw release notes content for this exact package version.
|
|
6
6
|
|
|
7
7
|
## v5.2.0
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
[View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v5.2.0)
|
|
10
|
+
|
|
11
|
+
This release brings in performance improvements across tldraw. The freehand ink algorithm now computes strokes 2–3x faster, shape resizing is quicker, and editor load time is reduced. Multi-click handling was simplified to double-click only to support improved mobile gestures. Plus it's easier to add shapes to frames, and dozens of bugs were fixed.
|
|
12
|
+
|
|
13
|
+
### What's new
|
|
14
|
+
|
|
15
|
+
#### Faster freehand ink ([#9154](https://github.com/tldraw/tldraw/pull/9154))
|
|
16
|
+
|
|
17
|
+
We rewrote the freehand ink algorithm. Draw and highlighter strokes now compute about 2x faster (up to 3x for long strokes) and produce 57% smaller SVG path data, with no visible change to how strokes look. The rewrite removes two rarely-used stroke APIs; see the breaking changes in [API changes](#api-changes).
|
|
18
|
+
|
|
19
|
+
#### Frame selection ([#8151](https://github.com/tldraw/tldraw/pull/8151))
|
|
20
|
+
|
|
21
|
+
A new "Frame selection" action wraps the selected shapes in a frame with `cmd+shift+f`. When a frame is selected, the same shortcut removes it.
|
|
10
22
|
|
|
11
23
|
### API changes
|
|
12
24
|
|
|
13
25
|
- 💥 Simplify multi-click handling to double-click only. `ClickManager` no longer tracks triple or quadruple clicks: the `triple_click` and `quadruple_click` events and the `onTripleClick` / `onQuadrupleClick` handlers have been removed, and `TLClickEventName` is now just `'double_click'`. ([#8897](https://github.com/tldraw/tldraw/pull/8897))
|
|
14
26
|
- 💥 Move `ShapeIndicatorOverlayUtil` and `TLShapeIndicatorOverlay` from `@tldraw/editor` to `tldraw`. Both are still exported from `tldraw`; update any imports of these symbols that came directly from `@tldraw/editor`. ([#9018](https://github.com/tldraw/tldraw/pull/9018))
|
|
27
|
+
- 💥 Drop support for the EOL Node 20. The minimum supported Node is now `>=22.12.0`, the first version with native `require()` of ES modules, so tldraw can depend on ESM-only packages. ([#9098](https://github.com/tldraw/tldraw/pull/9098))
|
|
28
|
+
- 💥 Type the collaborator user-id APIs as `TLUserId` instead of `string`. `TLInstancePresence.userId` / `followingUserId`, `TLInstance.followingUserId` / `highlightedUserIds`, `Editor.startFollowingUser()`, `Editor.zoomToUser()`, `usePresence()`, `usePeerIds()`, and the people-menu prop types now use `TLUserId`. Runtime behavior is unchanged: `TLUserId` is a branded string, so cast plain strings at the call site, for example `editor.startFollowingUser(userId as TLUserId)`. ([#9002](https://github.com/tldraw/tldraw/pull/9002))
|
|
29
|
+
- 💥 Remove `StrokePoint.vector` and `setStrokePointRadii` from the freehand stroke pipeline. The vector is derivable from consecutive points and radius/taper computation now happens inside `getStroke` and `svgInk`; nothing in the SDK consumed these outside the pipeline itself. ([#9154](https://github.com/tldraw/tldraw/pull/9154))
|
|
30
|
+
- 💥 Remove the obsolete selection-background slot from `@tldraw/editor`: `DefaultSelectionBackground`, `TLSelectionBackgroundProps`, `TLEditorComponents.SelectionBackground`, and the `useTransform` helper. These were unused and have no replacement; remove any references to them. ([#9362](https://github.com/tldraw/tldraw/pull/9362))
|
|
15
31
|
- Add an `embedConfig` option to `EmbedShapeUtil` for passing per-embed configuration such as API keys. The default Google Maps embed no longer reads `process.env.NEXT_PUBLIC_GC_API_KEY` — pass the key explicitly instead. ([#9068](https://github.com/tldraw/tldraw/pull/9068))
|
|
16
32
|
|
|
17
33
|
```ts
|
|
@@ -20,11 +36,31 @@ This release simplifies multi-click handling down to a single double-click event
|
|
|
20
36
|
})
|
|
21
37
|
```
|
|
22
38
|
|
|
39
|
+
- Add an `allowVideoAutoplay` option to `TldrawOptions`. When set to `false`, no video shape autoplays regardless of its per-shape `autoplay` prop — including pasted and restored shapes. Defaults to `true`. ([#8943](https://github.com/tldraw/tldraw/pull/8943))
|
|
40
|
+
- Add `ShapeUtil.getContentElement` and `ShapeUtil.onReleaseContentElement`, an app-owned content element lifecycle that lets stateful shape content (such as cross-origin iframes) survive unmounting the editor. ([#9167](https://github.com/tldraw/tldraw/pull/9167))
|
|
41
|
+
|
|
23
42
|
### Improvements
|
|
24
43
|
|
|
44
|
+
- Open the context menu with a right-click from any tool, not just the select tool, and with a touch long-press while using the select tool. Long-pressing on a shape-creation tool no longer leaves a stray shape behind. ([#8948](https://github.com/tldraw/tldraw/pull/8948))
|
|
25
45
|
- Add a `shift+q` shortcut that copies the styles of the hovered shape and applies them to the next shapes you create. ([#9028](https://github.com/tldraw/tldraw/pull/9028))
|
|
46
|
+
- Add a double-tap-and-drag zoom gesture for touch devices. ([#7858](https://github.com/tldraw/tldraw/pull/7858))
|
|
47
|
+
- As you drag out a frame, the frame tool now highlights the shapes it will enclose. ([#9102](https://github.com/tldraw/tldraw/pull/9102))
|
|
48
|
+
- Pasted bookmarks now show an immediate loading placeholder with a spinner at the paste location, instead of waiting for metadata before appearing. ([#8663](https://github.com/tldraw/tldraw/pull/8663))
|
|
49
|
+
- Add the missing keyboard shortcuts (copy as PNG, print, insert embed, highlight tool, frame selection, flatten, toggle locked, distribute horizontally/vertically) to the keyboard shortcuts dialog. ([#9285](https://github.com/tldraw/tldraw/pull/9285))
|
|
50
|
+
- Make the selection corner rotate handles easier to grab. ([#9374](https://github.com/tldraw/tldraw/pull/9374))
|
|
51
|
+
- Reduce the default indentation on rich-text lists so nested lists take up less horizontal space. ([#9287](https://github.com/tldraw/tldraw/pull/9287))
|
|
52
|
+
- Hide the "back to content" button during the animation that pans back to the canvas when focusing it. ([#9278](https://github.com/tldraw/tldraw/pull/9278))
|
|
53
|
+
- Remove the extraneous `title` tooltips on menu items. ([#9315](https://github.com/tldraw/tldraw/pull/9315))
|
|
54
|
+
- `@tldraw/mermaid` now loads its ESM-only `mermaid` dependency lazily, so the package is requirable from CommonJS and mermaid only loads when a diagram is created. ([#9100](https://github.com/tldraw/tldraw/pull/9100))
|
|
26
55
|
- Keep sync at full speed when the same multiplayer room is open in multiple tabs, windows, or devices — previously a room with no other users throttled network sync to once per second. ([#8988](https://github.com/tldraw/tldraw/pull/8988))
|
|
27
56
|
- Include `DOCS.md` documentation in published npm packages, and a generated docs and release notes rollup in the `tldraw` package, so documentation is available when browsing package artifacts. ([#8503](https://github.com/tldraw/tldraw/pull/8503))
|
|
57
|
+
- Shrink stored draw shape data for mouse, trackpad, and finger input by ~33% by omitting the redundant constant-pressure value from the encoded path. ([#8963](https://github.com/tldraw/tldraw/pull/8963))
|
|
58
|
+
- Improve performance when resizing many shapes at once. ([#9153](https://github.com/tldraw/tldraw/pull/9153))
|
|
59
|
+
- Improve change tracking and sync performance when many shapes change at once. ([#9151](https://github.com/tldraw/tldraw/pull/9151), [#9152](https://github.com/tldraw/tldraw/pull/9152))
|
|
60
|
+
- Improve validation performance during high-frequency updates. ([#9150](https://github.com/tldraw/tldraw/pull/9150))
|
|
61
|
+
- Speed up editor load by caching generated pattern fill defs and deduplicating icon preloads, so neither is rebuilt on every editor mount. ([#9345](https://github.com/tldraw/tldraw/pull/9345), [#9351](https://github.com/tldraw/tldraw/pull/9351))
|
|
62
|
+
- Remove the `jittered-fractional-indexing` dependency and speed up index key generation and validation; newly generated index keys are slightly shorter. ([#9352](https://github.com/tldraw/tldraw/pull/9352))
|
|
63
|
+
- Improve minimap rendering performance on large documents. ([#9355](https://github.com/tldraw/tldraw/pull/9355))
|
|
28
64
|
|
|
29
65
|
### Bug fixes
|
|
30
66
|
|
|
@@ -35,6 +71,34 @@ This release simplifies multi-click handling down to a single double-click event
|
|
|
35
71
|
- Fix the viewport shifting slightly when zooming past the minimum or maximum zoom level. ([#8957](https://github.com/tldraw/tldraw/pull/8957))
|
|
36
72
|
- Improve the contrast of disabled buttons and menu items in dark mode. ([#8931](https://github.com/tldraw/tldraw/pull/8931))
|
|
37
73
|
- Fix `debounce(...).cancel()` leaving an awaited call hanging forever; it now rejects the pending promise. ([#8683](https://github.com/tldraw/tldraw/pull/8683))
|
|
74
|
+
- Fix arrows jumping to incorrect positions after undoing or redoing shape deletions involving bindings. ([#8283](https://github.com/tldraw/tldraw/pull/8283))
|
|
75
|
+
- Fix touch long-press on shape-creation tools so the context menu opens without leaving a stray shape behind. ([#8946](https://github.com/tldraw/tldraw/pull/8946))
|
|
76
|
+
- Fix text labels drifting vertically between browsers (e.g. Chrome vs Safari) in multiplayer by snapping line-height to whole pixels. ([#8981](https://github.com/tldraw/tldraw/pull/8981))
|
|
77
|
+
- Fix collaborators not appearing until they interact with the board, idle following peers not being hidden, the "following you" indicator not showing in the people menu, and a phantom cursor for your own other browser sessions. ([#9088](https://github.com/tldraw/tldraw/pull/9088), [#9002](https://github.com/tldraw/tldraw/pull/9002))
|
|
78
|
+
- Fix releasing a modifier while still holding a shortcut key triggering the adjacent non-modifier shortcut. ([#9099](https://github.com/tldraw/tldraw/pull/9099))
|
|
79
|
+
- Fix redo (`cmd+shift+z`) not firing after an undo (`cmd+z`) on macOS when cmd is kept held. ([#9139](https://github.com/tldraw/tldraw/pull/9139))
|
|
80
|
+
- Fix releasing a fast right-click pan zooming the camera to the maximum zoom level. ([#9140](https://github.com/tldraw/tldraw/pull/9140))
|
|
81
|
+
- Fix selection handles disappearing when pressing (but not yet dragging) a resize edge, resize corner, or rotate handle, and keep selection chrome consistent while pointing. ([#9179](https://github.com/tldraw/tldraw/pull/9179), [#9184](https://github.com/tldraw/tldraw/pull/9184))
|
|
82
|
+
- Fix double-clicking an arrow handle no longer toggling the arrowhead on that end. ([#9180](https://github.com/tldraw/tldraw/pull/9180))
|
|
83
|
+
- Fix the camera jumping when a one-finger hand-tool pan transitions into a two-finger pinch zoom. ([#9182](https://github.com/tldraw/tldraw/pull/9182))
|
|
84
|
+
- Fix arrows becoming partially un-hoverable and un-clickable when bindings were created or updated without a shape change (e.g. `createBindings` after `createShapes`). ([#9183](https://github.com/tldraw/tldraw/pull/9183))
|
|
85
|
+
- Fix camera state getting stuck at `moving` when the editor is disposed during camera movement (e.g. React strict mode with a shared store). ([#9201](https://github.com/tldraw/tldraw/pull/9201))
|
|
86
|
+
- Fix the following indicator border being hidden beneath UI panels. ([#9210](https://github.com/tldraw/tldraw/pull/9210))
|
|
87
|
+
- Fix the sync version-mismatch handshake reporting `CLIENT_TOO_OLD` when the server is the one running an older version; it now correctly reports `SERVER_TOO_OLD`. ([#9212](https://github.com/tldraw/tldraw/pull/9212))
|
|
88
|
+
- Fix ctrl+click on macOS not selecting locked shapes or opening the context menu; it now behaves like a right-click. ([#9234](https://github.com/tldraw/tldraw/pull/9234))
|
|
89
|
+
- Fix a crash that could occur when undo or redo restored an editing state for a shape that no longer exists. ([#9260](https://github.com/tldraw/tldraw/pull/9260))
|
|
90
|
+
- Fix the line tool's minimum bend distance so it's measured in screen pixels. Shift-click now behaves the same at every zoom level. ([#9275](https://github.com/tldraw/tldraw/pull/9275))
|
|
91
|
+
- Fix style scrubbing selecting the wrong option when you release the pointer over a different style section. ([#9280](https://github.com/tldraw/tldraw/pull/9280))
|
|
92
|
+
- Fix empty rich text (an empty array) not being treated as an empty label. ([#9295](https://github.com/tldraw/tldraw/pull/9295))
|
|
93
|
+
- Fix desktop graphics tablets (e.g. Wacom) incorrectly switching the editor into pen mode. Pen mode now auto-enables only for direct-display stylus input such as Apple Pencil on iPad or Surface Pen on a touchscreen. ([#9316](https://github.com/tldraw/tldraw/pull/9316))
|
|
94
|
+
- Fix inconsistent easing when clicking the minimap to move the camera. ([#9355](https://github.com/tldraw/tldraw/pull/9355))
|
|
95
|
+
- Fix sync clients crashing when a malformed WebSocket message is received. ([#9356](https://github.com/tldraw/tldraw/pull/9356))
|
|
96
|
+
- Fix a crash when measuring viewport bounds after the editor document body is unavailable. ([#9357](https://github.com/tldraw/tldraw/pull/9357))
|
|
97
|
+
- Fix highlighted rich text showing an outline in dark mode. ([#9358](https://github.com/tldraw/tldraw/pull/9358))
|
|
98
|
+
- Fix text in exported images sometimes being sized with a fallback font when the export ran before the document's fonts had finished loading. ([#9372](https://github.com/tldraw/tldraw/pull/9372))
|
|
99
|
+
- Fix a crash when a shape is deleted mid-click (e.g. by a remote user or an undo) while clicking on it. ([#9376](https://github.com/tldraw/tldraw/pull/9376))
|
|
100
|
+
- Fix the license manager treating loopback hosts other than `localhost` (such as `127.0.0.1` and `::1`) as production environments. ([#9384](https://github.com/tldraw/tldraw/pull/9384))
|
|
101
|
+
- Fix the crop of a grouped, cropped image shifting when the group is flipped by dragging a resize handle. ([#9395](https://github.com/tldraw/tldraw/pull/9395))
|
|
38
102
|
|
|
39
103
|
## v5.1.0
|
|
40
104
|
|
package/dist-cjs/index.js
CHANGED
|
@@ -648,7 +648,7 @@ var import_buildFromV1Document = require("./lib/utils/tldr/buildFromV1Document")
|
|
|
648
648
|
var import_file = require("./lib/utils/tldr/file");
|
|
649
649
|
(0, import_editor.registerTldrawLibraryVersion)(
|
|
650
650
|
"tldraw",
|
|
651
|
-
"5.
|
|
651
|
+
"5.3.0-canary.263f9dbe88bb",
|
|
652
652
|
"cjs"
|
|
653
653
|
);
|
|
654
654
|
//# sourceMappingURL=index.js.map
|
|
@@ -77,7 +77,7 @@ class Pointing extends import_editor.StateNode {
|
|
|
77
77
|
this.cancel();
|
|
78
78
|
}
|
|
79
79
|
onLongPress() {
|
|
80
|
-
|
|
80
|
+
if (this.editor.getInstanceState().isCoarsePointer) this.cancel();
|
|
81
81
|
}
|
|
82
82
|
onCancel() {
|
|
83
83
|
this.cancel();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/arrow/toolStates/Pointing.tsx"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import { StateNode, TLArrowShape, createShapeId, maybeSnapToGrid } from '@tldraw/editor'\nimport { ArrowShapeUtil } from '../ArrowShapeUtil'\nimport { clearArrowTargetState, updateArrowTargetState } from '../arrowTargetState'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\tshape?: TLArrowShape\n\n\tisPrecise = false\n\tisPreciseTimerId: number | null = null\n\n\tmarkId = ''\n\n\toverride onEnter(info: { isPrecise?: boolean }) {\n\t\tthis.markId = ''\n\t\tthis.isPrecise = !!info.isPrecise\n\n\t\tconst targetState = updateArrowTargetState({\n\t\t\teditor: this.editor,\n\t\t\tpointInPageSpace: this.editor.inputs.getCurrentPagePoint(),\n\t\t\tarrow: undefined,\n\t\t\tisPrecise: this.isPrecise,\n\t\t\tcurrentBinding: undefined,\n\t\t\toppositeBinding: undefined,\n\t\t})\n\n\t\tif (!targetState) {\n\t\t\tthis.createArrowShape()\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.startPreciseTimeout()\n\t}\n\n\toverride onExit() {\n\t\tthis.shape = undefined\n\t\tclearArrowTargetState(this.editor)\n\t\tthis.clearPreciseTimeout()\n\t}\n\n\toverride onPointerMove() {\n\t\tif (this.editor.inputs.getIsDragging()) {\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.createArrowShape()\n\t\t\t}\n\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.updateArrowShapeEndHandle()\n\n\t\t\tthis.editor.setCurrentTool('select.dragging_handle', {\n\t\t\t\tshape: this.shape,\n\t\t\t\thandle: { id: 'end', type: 'vertex', index: 'a3', x: 0, y: 0 },\n\t\t\t\tisCreating: true,\n\t\t\t\tcreatingMarkId: this.markId || undefined,\n\t\t\t\tonInteractionEnd: 'arrow',\n\t\t\t})\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.cancel()\n\t}\n\n\toverride onLongPress() {\n\t\t// On a touch (coarse pointer) long-press, cancel the pending shape so it leaves nothing behind.\n\t\tif (this.editor.getInstanceState().isCoarsePointer) this.cancel()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tcancel() {\n\t\tif (this.shape) {\n\t\t\t// the arrow might not have been created yet!\n\t\t\tthis.editor.bailToMark(this.markId)\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcreateArrowShape() {\n\t\tconst originPagePoint = this.editor.inputs.getOriginPagePoint()\n\n\t\tconst id = createShapeId()\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_arrow:${id}`)\n\t\tconst newPoint = maybeSnapToGrid(originPagePoint, this.editor)\n\t\tthis.editor.createShape({\n\t\t\tid,\n\t\t\ttype: 'arrow',\n\t\t\tx: newPoint.x,\n\t\t\ty: newPoint.y,\n\t\t\tprops: {\n\t\t\t\tscale: this.editor.getResizeScaleFactor(),\n\t\t\t},\n\t\t})\n\n\t\tconst shape = this.editor.getShape<TLArrowShape>(id)\n\t\tif (!shape) return\n\n\t\tconst handles = this.editor.getShapeHandles(shape)\n\t\tif (!handles) throw Error(`expected handles for arrow`)\n\n\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\tconst initial = this.shape\n\t\tconst startHandle = handles.find((h) => h.id === 'start')!\n\t\tconst change = util.onHandleDrag?.(shape, {\n\t\t\thandle: { ...startHandle, x: 0, y: 0 },\n\t\t\tisPrecise: true,\n\t\t\tisCreatingShape: true,\n\t\t\tinitial: initial,\n\t\t})\n\n\t\tif (change) {\n\t\t\tthis.editor.updateShapes([change])\n\t\t}\n\n\t\t// Cache the current shape after those changes\n\t\tthis.shape = this.editor.getShape(id)\n\t\tthis.editor.select(id)\n\t}\n\n\tupdateArrowShapeEndHandle() {\n\t\tconst shape = this.shape\n\t\tif (!shape) throw Error(`expected shape`)\n\n\t\tconst handles = this.editor.getShapeHandles(shape)\n\t\tif (!handles) throw Error(`expected handles for arrow`)\n\n\t\t// start update\n\t\t{\n\t\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\t\tconst initial = this.shape\n\t\t\tconst startHandle = handles.find((h) => h.id === 'start')!\n\t\t\tconst change = util.onHandleDrag?.(shape, {\n\t\t\t\thandle: { ...startHandle, x: 0, y: 0 },\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: true,\n\t\t\t\tinitial: initial,\n\t\t\t})\n\n\t\t\tif (change) {\n\t\t\t\tthis.editor.updateShapes([change])\n\t\t\t}\n\t\t}\n\n\t\t// end update\n\t\t{\n\t\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\t\tconst initial = this.shape\n\t\t\tconst point = this.editor.getPointInShapeSpace(\n\t\t\t\tshape,\n\t\t\t\tthis.editor.inputs.getCurrentPagePoint()\n\t\t\t)\n\t\t\tconst endHandle = handles.find((h) => h.id === 'end')!\n\t\t\tconst change = util.onHandleDrag?.(this.editor.getShape(shape)!, {\n\t\t\t\thandle: { ...endHandle, x: point.x, y: point.y },\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: true,\n\t\t\t\tinitial: initial,\n\t\t\t})\n\n\t\t\tif (change) {\n\t\t\t\tthis.editor.updateShapes([change])\n\t\t\t}\n\t\t}\n\n\t\t// Cache the current shape after those changes\n\t\tthis.shape = this.editor.getShape(shape.id)\n\t}\n\n\tprivate startPreciseTimeout() {\n\t\tconst arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')\n\n\t\tthis.isPreciseTimerId = this.editor.timers.setTimeout(() => {\n\t\t\tif (!this.getIsActive()) return\n\t\t\tthis.isPrecise = true\n\t\t}, arrowUtil.options.pointingPreciseTimeout)\n\t}\n\n\tprivate clearPreciseTimeout() {\n\t\tif (this.isPreciseTimerId !== null) {\n\t\t\tclearTimeout(this.isPreciseTimerId)\n\t\t}\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAwE;AAExE,8BAA8D;AAEvD,MAAM,iBAAiB,wBAAU;AAAA,EACvC,OAAgB,KAAK;AAAA,EAErB;AAAA,EAEA,YAAY;AAAA,EACZ,mBAAkC;AAAA,EAElC,SAAS;AAAA,EAEA,QAAQ,MAA+B;AAC/C,SAAK,SAAS;AACd,SAAK,YAAY,CAAC,CAAC,KAAK;AAExB,UAAM,kBAAc,gDAAuB;AAAA,MAC1C,QAAQ,KAAK;AAAA,MACb,kBAAkB,KAAK,OAAO,OAAO,oBAAoB;AAAA,MACzD,OAAO;AAAA,MACP,WAAW,KAAK;AAAA,MAChB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,IAClB,CAAC;AAED,QAAI,CAAC,aAAa;AACjB,WAAK,iBAAiB;AACtB,UAAI,CAAC,KAAK,OAAO;AAChB,aAAK,OAAO;AACZ;AAAA,MACD;AAAA,IACD;AAEA,SAAK,oBAAoB;AAAA,EAC1B;AAAA,EAES,SAAS;AACjB,SAAK,QAAQ;AACb,uDAAsB,KAAK,MAAM;AACjC,SAAK,oBAAoB;AAAA,EAC1B;AAAA,EAES,gBAAgB;AACxB,QAAI,KAAK,OAAO,OAAO,cAAc,GAAG;AACvC,UAAI,CAAC,KAAK,OAAO;AAChB,aAAK,iBAAiB;AAAA,MACvB;AAEA,UAAI,CAAC,KAAK,OAAO;AAChB,aAAK,OAAO;AACZ;AAAA,MACD;AAEA,WAAK,0BAA0B;AAE/B,WAAK,OAAO,eAAe,0BAA0B;AAAA,QACpD,OAAO,KAAK;AAAA,QACZ,QAAQ,EAAE,IAAI,OAAO,MAAM,UAAU,OAAO,MAAM,GAAG,GAAG,GAAG,EAAE;AAAA,QAC7D,YAAY;AAAA,QACZ,gBAAgB,KAAK,UAAU;AAAA,QAC/B,kBAAkB;AAAA,MACnB,CAAC;AAAA,IACF;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,cAAc;AAEtB,QAAI,KAAK,OAAO,iBAAiB,EAAE,gBAAiB,MAAK,OAAO;AAAA,EACjE;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAEA,SAAS;AACR,QAAI,KAAK,OAAO;AAEf,WAAK,OAAO,WAAW,KAAK,MAAM;AAAA,IACnC;AACA,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEA,mBAAmB;AAClB,UAAM,kBAAkB,KAAK,OAAO,OAAO,mBAAmB;AAE9D,UAAM,SAAK,6BAAc;AAEzB,SAAK,SAAS,KAAK,OAAO,yBAAyB,kBAAkB,EAAE,EAAE;AACzE,UAAM,eAAW,+BAAgB,iBAAiB,KAAK,MAAM;AAC7D,SAAK,OAAO,YAAY;AAAA,MACvB;AAAA,MACA,MAAM;AAAA,MACN,GAAG,SAAS;AAAA,MACZ,GAAG,SAAS;AAAA,MACZ,OAAO;AAAA,QACN,OAAO,KAAK,OAAO,qBAAqB;AAAA,MACzC;AAAA,IACD,CAAC;AAED,UAAM,QAAQ,KAAK,OAAO,SAAuB,EAAE;AACnD,QAAI,CAAC,MAAO;AAEZ,UAAM,UAAU,KAAK,OAAO,gBAAgB,KAAK;AACjD,QAAI,CAAC,QAAS,OAAM,MAAM,4BAA4B;AAEtD,UAAM,OAAO,KAAK,OAAO,aAA2B,OAAO;AAC3D,UAAM,UAAU,KAAK;AACrB,UAAM,cAAc,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACxD,UAAM,SAAS,KAAK,eAAe,OAAO;AAAA,MACzC,QAAQ,EAAE,GAAG,aAAa,GAAG,GAAG,GAAG,EAAE;AAAA,MACrC,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB;AAAA,IACD,CAAC;AAED,QAAI,QAAQ;AACX,WAAK,OAAO,aAAa,CAAC,MAAM,CAAC;AAAA,IAClC;AAGA,SAAK,QAAQ,KAAK,OAAO,SAAS,EAAE;AACpC,SAAK,OAAO,OAAO,EAAE;AAAA,EACtB;AAAA,EAEA,4BAA4B;AAC3B,UAAM,QAAQ,KAAK;AACnB,QAAI,CAAC,MAAO,OAAM,MAAM,gBAAgB;AAExC,UAAM,UAAU,KAAK,OAAO,gBAAgB,KAAK;AACjD,QAAI,CAAC,QAAS,OAAM,MAAM,4BAA4B;AAGtD;AACC,YAAM,OAAO,KAAK,OAAO,aAA2B,OAAO;AAC3D,YAAM,UAAU,KAAK;AACrB,YAAM,cAAc,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACxD,YAAM,SAAS,KAAK,eAAe,OAAO;AAAA,QACzC,QAAQ,EAAE,GAAG,aAAa,GAAG,GAAG,GAAG,EAAE;AAAA,QACrC,WAAW,KAAK;AAAA,QAChB,iBAAiB;AAAA,QACjB;AAAA,MACD,CAAC;AAED,UAAI,QAAQ;AACX,aAAK,OAAO,aAAa,CAAC,MAAM,CAAC;AAAA,MAClC;AAAA,IACD;AAGA;AACC,YAAM,OAAO,KAAK,OAAO,aAA2B,OAAO;AAC3D,YAAM,UAAU,KAAK;AACrB,YAAM,QAAQ,KAAK,OAAO;AAAA,QACzB;AAAA,QACA,KAAK,OAAO,OAAO,oBAAoB;AAAA,MACxC;AACA,YAAM,YAAY,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK;AACpD,YAAM,SAAS,KAAK,eAAe,KAAK,OAAO,SAAS,KAAK,GAAI;AAAA,QAChE,QAAQ,EAAE,GAAG,WAAW,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,QAC/C,WAAW,KAAK;AAAA,QAChB,iBAAiB;AAAA,QACjB;AAAA,MACD,CAAC;AAED,UAAI,QAAQ;AACX,aAAK,OAAO,aAAa,CAAC,MAAM,CAAC;AAAA,MAClC;AAAA,IACD;AAGA,SAAK,QAAQ,KAAK,OAAO,SAAS,MAAM,EAAE;AAAA,EAC3C;AAAA,EAEQ,sBAAsB;AAC7B,UAAM,YAAY,KAAK,OAAO,aAA6B,OAAO;AAElE,SAAK,mBAAmB,KAAK,OAAO,OAAO,WAAW,MAAM;AAC3D,UAAI,CAAC,KAAK,YAAY,EAAG;AACzB,WAAK,YAAY;AAAA,IAClB,GAAG,UAAU,QAAQ,sBAAsB;AAAA,EAC5C;AAAA,EAEQ,sBAAsB;AAC7B,QAAI,KAAK,qBAAqB,MAAM;AACnC,mBAAa,KAAK,gBAAgB;AAAA,IACnC;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -29,7 +29,7 @@ class Pointing extends import_editor.StateNode {
|
|
|
29
29
|
this.complete();
|
|
30
30
|
}
|
|
31
31
|
onLongPress() {
|
|
32
|
-
|
|
32
|
+
if (this.editor.getInstanceState().isCoarsePointer) this.cancel();
|
|
33
33
|
}
|
|
34
34
|
onPointerMove(info) {
|
|
35
35
|
if (this.editor.inputs.getIsDragging()) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/geo/toolStates/Pointing.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tGeoShapeGeoStyle,\n\tStateNode,\n\tTLGeoShape,\n\tTLPointerEventInfo,\n\tVec,\n\tcreateShapeId,\n\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import {\n\tGeoShapeGeoStyle,\n\tStateNode,\n\tTLGeoShape,\n\tTLPointerEventInfo,\n\tVec,\n\tcreateShapeId,\n\tmaybeSnapToGrid,\n} from '@tldraw/editor'\nimport { GeoShapeUtil } from '../GeoShapeUtil'\nimport { getGeoTypeDefinition } from '../getGeoShapePath'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onLongPress() {\n\t\t// On a touch (coarse pointer) long-press, cancel the pending shape so it leaves nothing behind.\n\t\tif (this.editor.getInstanceState().isCoarsePointer) this.cancel()\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tif (this.editor.inputs.getIsDragging()) {\n\t\t\tconst originPagePoint = this.editor.inputs.getOriginPagePoint()\n\n\t\t\tconst id = createShapeId()\n\n\t\t\tconst creatingMarkId = this.editor.markHistoryStoppingPoint(`creating_geo:${id}`)\n\t\t\tconst newPoint = maybeSnapToGrid(originPagePoint, this.editor)\n\t\t\tthis.editor\n\t\t\t\t.createShapes([\n\t\t\t\t\t{\n\t\t\t\t\t\tid,\n\t\t\t\t\t\ttype: 'geo',\n\t\t\t\t\t\tx: newPoint.x,\n\t\t\t\t\t\ty: newPoint.y,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tw: 1,\n\t\t\t\t\t\t\th: 1,\n\t\t\t\t\t\t\tgeo: this.editor.getStyleForNextShape(GeoShapeGeoStyle),\n\t\t\t\t\t\t\tscale: this.editor.getResizeScaleFactor(),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t])\n\t\t\t\t.select(id)\n\n\t\t\tconst shape = this.editor.getShape(id)\n\t\t\tif (!shape) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.editor.setCurrentTool('select.resizing', {\n\t\t\t\t...info,\n\t\t\t\ttarget: 'selection',\n\t\t\t\thandle: 'bottom_right',\n\t\t\t\tisCreating: true,\n\t\t\t\tcreatingMarkId,\n\t\t\t\tcreationCursorOffset: { x: 1, y: 1 },\n\t\t\t\tonInteractionEnd: 'geo',\n\t\t\t})\n\t\t}\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tconst originPagePoint = this.editor.inputs.getOriginPagePoint()\n\n\t\tconst id = createShapeId()\n\n\t\tthis.editor.markHistoryStoppingPoint(`creating_geo:${id}`)\n\n\t\tconst scale = this.editor.getResizeScaleFactor()\n\n\t\tconst geo = this.editor.getStyleForNextShape(GeoShapeGeoStyle)\n\t\tconst geoShapeUtil = this.editor.getShapeUtil<GeoShapeUtil>('geo')\n\n\t\tconst def = getGeoTypeDefinition(geo, geoShapeUtil.options.customGeoTypes)\n\t\tconst size = def?.defaultSize ?? { w: 200, h: 200 }\n\n\t\tthis.editor.createShapes([\n\t\t\t{\n\t\t\t\tid,\n\t\t\t\ttype: 'geo',\n\t\t\t\tx: originPagePoint.x,\n\t\t\t\ty: originPagePoint.y,\n\t\t\t\tprops: {\n\t\t\t\t\tgeo: this.editor.getStyleForNextShape(GeoShapeGeoStyle),\n\t\t\t\t\tscale,\n\t\t\t\t\t...size,\n\t\t\t\t},\n\t\t\t},\n\t\t])\n\n\t\tconst shape = this.editor.getShape<TLGeoShape>(id)!\n\t\tif (!shape) {\n\t\t\tthis.cancel()\n\t\t\treturn\n\t\t}\n\n\t\tconst { w, h } = shape.props\n\n\t\tconst delta = new Vec(w / 2, h / 2).mul(scale)\n\t\tconst parentTransform = this.editor.getShapeParentTransform(shape)\n\t\tif (parentTransform) delta.rot(-parentTransform.rotation())\n\t\tconst newPoint = maybeSnapToGrid(new Vec(shape.x - delta.x, shape.y - delta.y), this.editor)\n\t\tthis.editor.select(id)\n\t\tthis.editor.updateShape({\n\t\t\tid: shape.id,\n\t\t\ttype: 'geo',\n\t\t\tx: newPoint.x,\n\t\t\ty: newPoint.y,\n\t\t\tprops: {\n\t\t\t\tgeo: this.editor.getStyleForNextShape(GeoShapeGeoStyle),\n\t\t\t\tw: w * scale,\n\t\t\t\th: h * scale,\n\t\t\t},\n\t\t})\n\n\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\tthis.parent.transition('idle')\n\t\t} else {\n\t\t\tthis.editor.setCurrentTool('select', {})\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\t// we should not have created any shapes yet, so no need to bail\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -83,7 +83,10 @@ class LineShapeUtil extends import_editor.ShapeUtil {
|
|
|
83
83
|
const points = linePointsToArray(shape);
|
|
84
84
|
const results = points.map((point) => ({
|
|
85
85
|
...point,
|
|
86
|
-
id
|
|
86
|
+
// A vertex handle's id is the point's stable id (its map key), not its
|
|
87
|
+
// index. The index is only ever used for ordering (sortByIndex) and for
|
|
88
|
+
// computing the create-handle positions below.
|
|
89
|
+
id: point.id,
|
|
87
90
|
type: "vertex",
|
|
88
91
|
canSnap: true
|
|
89
92
|
}));
|
|
@@ -270,7 +273,8 @@ class LineShapeUtil extends import_editor.ShapeUtil {
|
|
|
270
273
|
}
|
|
271
274
|
}
|
|
272
275
|
function linePointsToArray(shape) {
|
|
273
|
-
|
|
276
|
+
const sorted = Object.values(shape.props.points).sort(import_editor.sortByIndex);
|
|
277
|
+
return sorted.filter((point, i) => i === 0 || point.index !== sorted[i - 1].index);
|
|
274
278
|
}
|
|
275
279
|
const pathCache = new import_editor.WeakCache();
|
|
276
280
|
function getPathForLineShape(shape) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/line/LineShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["// oxlint-disable typescript/no-empty-object-type\nimport {\n\tGroup2d,\n\tHandleSnapGeometry,\n\tSVGContainer,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLHandle,\n\tTLHandleDragInfo,\n\tTLLineShape,\n\tTLLineShapePoint,\n\tTLResizeInfo,\n\tVec,\n\tWeakCache,\n\tZERO_INDEX_KEY,\n\tassert,\n\tgetColorValue,\n\tgetIndexAbove,\n\tgetIndexBetween,\n\tgetIndices,\n\tlerp,\n\tlineShapeMigrations,\n\tlineShapeProps,\n\tmapObjectMapValues,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n\tuseColorMode,\n} from '@tldraw/editor'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { PathBuilder, PathBuilderGeometry2d } from '../shared/PathBuilder'\n\nconst handlesCache = new WeakCache<TLLineShape['props'], TLHandle[]>()\n\n/** @public */\nexport interface LineShapeUtilDisplayValues {\n\tstrokeColor: string\n\tstrokeWidth: number\n}\n\n/** @public */\nexport interface LineShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLLineShape,\n\tLineShapeUtilDisplayValues\n> {}\n\n/** @public */\nexport class LineShapeUtil extends ShapeUtil<TLLineShape> {\n\tstatic override type = 'line' as const\n\tstatic override props = lineShapeProps\n\tstatic override migrations = lineShapeMigrations\n\n\toverride options: LineShapeOptions = {\n\t\tgetDefaultDisplayValues(_editor, shape, theme, colorMode): LineShapeUtilDisplayValues {\n\t\t\tconst { color, size } = shape.props\n\t\t\treturn {\n\t\t\t\tstrokeColor: getColorValue(theme.colors[colorMode], color, 'solid'),\n\t\t\t\tstrokeWidth: theme.strokeWidth * STROKE_SIZES[size],\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<LineShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride hideResizeHandles(shape: TLLineShape) {\n\t\treturn true\n\t}\n\toverride hideRotateHandle(shape: TLLineShape) {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsFg(shape: TLLineShape) {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsBg(shape: TLLineShape) {\n\t\treturn true\n\t}\n\toverride hideInMinimap() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLLineShape['props'] {\n\t\tconst [start, end] = getIndices(2)\n\t\treturn {\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tcolor: 'black',\n\t\t\tspline: 'line',\n\t\t\tpoints: {\n\t\t\t\t[start]: { id: start, index: start, x: 0, y: 0 },\n\t\t\t\t[end]: { id: end, index: end, x: 0.1, y: 0.1 },\n\t\t\t},\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLLineShape) {\n\t\t// todo: should we have min size?\n\t\tconst geometry = getPathForLineShape(shape).toGeometry()\n\t\tassert(geometry instanceof PathBuilderGeometry2d)\n\t\treturn geometry\n\t}\n\n\toverride getHandles(shape: TLLineShape) {\n\t\treturn handlesCache.get(shape.props, () => {\n\t\t\tconst spline = this.getGeometry(shape)\n\n\t\t\tconst points = linePointsToArray(shape)\n\t\t\tconst results: TLHandle[] = points.map((point) => ({\n\t\t\t\t...point,\n\t\t\t\tid: point.index,\n\t\t\t\ttype: 'vertex',\n\t\t\t\tcanSnap: true,\n\t\t\t}))\n\n\t\t\tfor (let i = 0; i < points.length - 1; i++) {\n\t\t\t\tconst index = getIndexBetween(points[i].index, points[i + 1].index)\n\t\t\t\tconst segment = spline.getSegments()[i]\n\t\t\t\tconst point = segment.interpolateAlongEdge(0.5)\n\t\t\t\tresults.push({\n\t\t\t\t\tid: index,\n\t\t\t\t\ttype: 'create',\n\t\t\t\t\tindex,\n\t\t\t\t\tx: point.x,\n\t\t\t\t\ty: point.y,\n\t\t\t\t\tcanSnap: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn results.sort(sortByIndex)\n\t\t})\n\t}\n\n\t// Events\n\n\toverride onResize(shape: TLLineShape, info: TLResizeInfo<TLLineShape>) {\n\t\tconst { scaleX, scaleY } = info\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tpoints: mapObjectMapValues(shape.props.points, (_, { id, index, x, y }) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tindex,\n\t\t\t\t\tx: x * scaleX,\n\t\t\t\t\ty: y * scaleY,\n\t\t\t\t})),\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onBeforeCreate(next: TLLineShape): void | TLLineShape {\n\t\tconst {\n\t\t\tprops: { points },\n\t\t} = next\n\t\tconst pointKeys = Object.keys(points)\n\n\t\tif (pointKeys.length < 2) {\n\t\t\treturn\n\t\t}\n\n\t\tconst firstPoint = points[pointKeys[0]]\n\t\tconst allSame = pointKeys.every((key) => {\n\t\t\tconst point = points[key]\n\t\t\treturn point.x === firstPoint.x && point.y === firstPoint.y\n\t\t})\n\t\tif (allSame) {\n\t\t\tconst lastKey = pointKeys[pointKeys.length - 1]\n\t\t\tpoints[lastKey] = {\n\t\t\t\t...points[lastKey],\n\t\t\t\tx: points[lastKey].x + 0.1,\n\t\t\t\ty: points[lastKey].y + 0.1,\n\t\t\t}\n\t\t\treturn next\n\t\t}\n\t\treturn\n\t}\n\n\toverride onHandleDrag(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\tconst newPoint = maybeSnapToGrid(new Vec(handle.x, handle.y), this.editor)\n\t\treturn {\n\t\t\t...shape,\n\t\t\tprops: {\n\t\t\t\t...shape.props,\n\t\t\t\tpoints: {\n\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t[handle.id]: { id: handle.id, index: handle.index, x: newPoint.x, y: newPoint.y },\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onHandleDragStart(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\t// For line shapes, if we're dragging a \"create\" handle, then\n\t\t// create a new vertex handle at that point; and make this handle\n\t\t// the handle that we're dragging.\n\t\tif (handle.type === 'create') {\n\t\t\treturn {\n\t\t\t\t...shape,\n\t\t\t\tprops: {\n\t\t\t\t\t...shape.props,\n\t\t\t\t\tpoints: {\n\t\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t\t[handle.index]: { id: handle.index, index: handle.index, x: handle.x, y: handle.y },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n\n\tcomponent(shape: TLLineShape) {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst colorMode = useColorMode()\n\t\tconst dv = getDisplayValues(this, shape, colorMode)\n\t\treturn (\n\t\t\t<SVGContainer style={{ minWidth: 50, minHeight: 50 }}>\n\t\t\t\t<LineShapeSvg shape={shape} strokeColor={dv.strokeColor} strokeWidth={dv.strokeWidth} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLLineShape): Path2D {\n\t\tconst strokeWidth = getDisplayValues(this, shape).strokeWidth * shape.props.scale\n\t\tconst path = getPathForLineShape(shape)\n\t\tconst { dash } = shape.props\n\n\t\treturn path.toPath2D({\n\t\t\tstyle: dash === 'draw' ? 'draw' : 'solid',\n\t\t\tstrokeWidth: 1,\n\t\t\tpasses: 1,\n\t\t\trandomSeed: shape.id,\n\t\t\toffset: 0,\n\t\t\troundness: strokeWidth * 2,\n\t\t})\n\t}\n\n\toverride toSvg(shape: TLLineShape, ctx: SvgExportContext) {\n\t\tconst dv = getDisplayValues(this, shape, ctx.colorMode)\n\t\treturn (\n\t\t\t<LineShapeSvg\n\t\t\t\tshouldScale\n\t\t\t\tshape={shape}\n\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride getHandleSnapGeometry(shape: TLLineShape): HandleSnapGeometry {\n\t\tconst points = linePointsToArray(shape)\n\t\treturn {\n\t\t\tpoints,\n\t\t\tgetSelfSnapPoints: (handle) => {\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// We want to skip the current and adjacent handles\n\t\t\t\treturn points.filter((_, i) => Math.abs(i - index) > 1).map(Vec.From)\n\t\t\t},\n\t\t\tgetSelfSnapOutline: (handle) => {\n\t\t\t\t// We want to skip the segments that include the handle, so\n\t\t\t\t// find the index of the handle that shares the same index property\n\t\t\t\t// as the initial dragging handle; this catches a quirk of create handles\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// Get all the outline segments from the shape that don't include the handle\n\t\t\t\tconst segments = this.getGeometry(shape)\n\t\t\t\t\t.getSegments()\n\t\t\t\t\t.filter((_, i) => i !== index - 1 && i !== index)\n\n\t\t\t\tif (!segments.length) return null\n\t\t\t\treturn new Group2d({ children: segments })\n\t\t\t},\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLLineShape,\n\t\tendShape: TLLineShape,\n\t\tt: number\n\t): TLLineShape['props'] {\n\t\tconst startPoints = linePointsToArray(startShape)\n\t\tconst endPoints = linePointsToArray(endShape)\n\n\t\tconst pointsToUseStart: TLLineShapePoint[] = []\n\t\tconst pointsToUseEnd: TLLineShapePoint[] = []\n\n\t\tlet index = ZERO_INDEX_KEY\n\n\t\tif (startPoints.length > endPoints.length) {\n\t\t\t// we'll need to expand points\n\t\t\tfor (let i = 0; i < startPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = { ...startPoints[i] }\n\t\t\t\tif (endPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[endPoints.length - 1], id: index }\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else if (endPoints.length > startPoints.length) {\n\t\t\t// we'll need to converge points\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i] }\n\t\t\t\tif (startPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseStart[i] = {\n\t\t\t\t\t\t...startPoints[startPoints.length - 1],\n\t\t\t\t\t\tid: index,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseStart[i] = { ...startPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else {\n\t\t\t// noop, easy\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = startPoints[i]\n\t\t\t\tpointsToUseEnd[i] = endPoints[i]\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tpoints: Object.fromEntries(\n\t\t\t\tpointsToUseStart.map((point, i) => {\n\t\t\t\t\tconst endPoint = pointsToUseEnd[i]\n\t\t\t\t\treturn [\n\t\t\t\t\t\tpoint.id,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...point,\n\t\t\t\t\t\t\tx: lerp(point.x, endPoint.x, t),\n\t\t\t\t\t\t\ty: lerp(point.y, endPoint.y, t),\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t\t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction linePointsToArray(shape: TLLineShape) {\n\treturn Object.values(shape.props.points).sort(sortByIndex)\n}\n\nconst pathCache = new WeakCache<TLLineShape, PathBuilder>()\nfunction getPathForLineShape(shape: TLLineShape): PathBuilder {\n\treturn pathCache.get(shape, () => {\n\t\tconst points = linePointsToArray(shape).map(Vec.From)\n\n\t\tswitch (shape.props.spline) {\n\t\t\tcase 'cubic': {\n\t\t\t\treturn PathBuilder.cubicSplineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t\tcase 'line': {\n\t\t\t\treturn PathBuilder.lineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction LineShapeSvg({\n\tshape,\n\tshouldScale = false,\n\tforceSolid = false,\n\tstrokeColor,\n\tstrokeWidth: baseStrokeWidth,\n}: {\n\tshape: TLLineShape\n\tshouldScale?: boolean\n\tforceSolid?: boolean\n\tstrokeColor: string\n\tstrokeWidth: number\n}) {\n\tconst path = getPathForLineShape(shape)\n\tconst { dash } = shape.props\n\n\tconst scaleFactor = 1 / shape.props.scale\n\n\tconst scale = shouldScale ? scaleFactor : 1\n\n\tconst strokeWidth = baseStrokeWidth * shape.props.scale\n\n\treturn path.toSvg({\n\t\tstyle: dash,\n\t\tstrokeWidth,\n\t\tforceSolid,\n\t\trandomSeed: shape.id,\n\t\tprops: {\n\t\t\ttransform: `scale(${scale})`,\n\t\t\tstroke: strokeColor,\n\t\t\tfill: 'none',\n\t\t},\n\t})\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["// oxlint-disable typescript/no-empty-object-type\nimport {\n\tGroup2d,\n\tHandleSnapGeometry,\n\tSVGContainer,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLHandle,\n\tTLHandleDragInfo,\n\tTLLineShape,\n\tTLLineShapePoint,\n\tTLResizeInfo,\n\tVec,\n\tWeakCache,\n\tZERO_INDEX_KEY,\n\tassert,\n\tgetColorValue,\n\tgetIndexAbove,\n\tgetIndexBetween,\n\tgetIndices,\n\tlerp,\n\tlineShapeMigrations,\n\tlineShapeProps,\n\tmapObjectMapValues,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n\tuseColorMode,\n} from '@tldraw/editor'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { PathBuilder, PathBuilderGeometry2d } from '../shared/PathBuilder'\n\nconst handlesCache = new WeakCache<TLLineShape['props'], TLHandle[]>()\n\n/** @public */\nexport interface LineShapeUtilDisplayValues {\n\tstrokeColor: string\n\tstrokeWidth: number\n}\n\n/** @public */\nexport interface LineShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLLineShape,\n\tLineShapeUtilDisplayValues\n> {}\n\n/** @public */\nexport class LineShapeUtil extends ShapeUtil<TLLineShape> {\n\tstatic override type = 'line' as const\n\tstatic override props = lineShapeProps\n\tstatic override migrations = lineShapeMigrations\n\n\toverride options: LineShapeOptions = {\n\t\tgetDefaultDisplayValues(_editor, shape, theme, colorMode): LineShapeUtilDisplayValues {\n\t\t\tconst { color, size } = shape.props\n\t\t\treturn {\n\t\t\t\tstrokeColor: getColorValue(theme.colors[colorMode], color, 'solid'),\n\t\t\t\tstrokeWidth: theme.strokeWidth * STROKE_SIZES[size],\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<LineShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride hideResizeHandles(shape: TLLineShape) {\n\t\treturn true\n\t}\n\toverride hideRotateHandle(shape: TLLineShape) {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsFg(shape: TLLineShape) {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsBg(shape: TLLineShape) {\n\t\treturn true\n\t}\n\toverride hideInMinimap() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLLineShape['props'] {\n\t\tconst [start, end] = getIndices(2)\n\t\treturn {\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tcolor: 'black',\n\t\t\tspline: 'line',\n\t\t\tpoints: {\n\t\t\t\t[start]: { id: start, index: start, x: 0, y: 0 },\n\t\t\t\t[end]: { id: end, index: end, x: 0.1, y: 0.1 },\n\t\t\t},\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLLineShape) {\n\t\t// todo: should we have min size?\n\t\tconst geometry = getPathForLineShape(shape).toGeometry()\n\t\tassert(geometry instanceof PathBuilderGeometry2d)\n\t\treturn geometry\n\t}\n\n\toverride getHandles(shape: TLLineShape) {\n\t\treturn handlesCache.get(shape.props, () => {\n\t\t\tconst spline = this.getGeometry(shape)\n\n\t\t\tconst points = linePointsToArray(shape)\n\t\t\tconst results: TLHandle[] = points.map((point) => ({\n\t\t\t\t...point,\n\t\t\t\t// A vertex handle's id is the point's stable id (its map key), not its\n\t\t\t\t// index. The index is only ever used for ordering (sortByIndex) and for\n\t\t\t\t// computing the create-handle positions below.\n\t\t\t\tid: point.id,\n\t\t\t\ttype: 'vertex',\n\t\t\t\tcanSnap: true,\n\t\t\t}))\n\n\t\t\tfor (let i = 0; i < points.length - 1; i++) {\n\t\t\t\tconst index = getIndexBetween(points[i].index, points[i + 1].index)\n\t\t\t\tconst segment = spline.getSegments()[i]\n\t\t\t\tconst point = segment.interpolateAlongEdge(0.5)\n\t\t\t\tresults.push({\n\t\t\t\t\tid: index,\n\t\t\t\t\ttype: 'create',\n\t\t\t\t\tindex,\n\t\t\t\t\tx: point.x,\n\t\t\t\t\ty: point.y,\n\t\t\t\t\tcanSnap: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn results.sort(sortByIndex)\n\t\t})\n\t}\n\n\t// Events\n\n\toverride onResize(shape: TLLineShape, info: TLResizeInfo<TLLineShape>) {\n\t\tconst { scaleX, scaleY } = info\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tpoints: mapObjectMapValues(shape.props.points, (_, { id, index, x, y }) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tindex,\n\t\t\t\t\tx: x * scaleX,\n\t\t\t\t\ty: y * scaleY,\n\t\t\t\t})),\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onBeforeCreate(next: TLLineShape): void | TLLineShape {\n\t\tconst {\n\t\t\tprops: { points },\n\t\t} = next\n\t\tconst pointKeys = Object.keys(points)\n\n\t\tif (pointKeys.length < 2) {\n\t\t\treturn\n\t\t}\n\n\t\tconst firstPoint = points[pointKeys[0]]\n\t\tconst allSame = pointKeys.every((key) => {\n\t\t\tconst point = points[key]\n\t\t\treturn point.x === firstPoint.x && point.y === firstPoint.y\n\t\t})\n\t\tif (allSame) {\n\t\t\tconst lastKey = pointKeys[pointKeys.length - 1]\n\t\t\tpoints[lastKey] = {\n\t\t\t\t...points[lastKey],\n\t\t\t\tx: points[lastKey].x + 0.1,\n\t\t\t\ty: points[lastKey].y + 0.1,\n\t\t\t}\n\t\t\treturn next\n\t\t}\n\t\treturn\n\t}\n\n\toverride onHandleDrag(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\tconst newPoint = maybeSnapToGrid(new Vec(handle.x, handle.y), this.editor)\n\t\t// handle.id is the point's key (== its id), so we update the point in place.\n\t\treturn {\n\t\t\t...shape,\n\t\t\tprops: {\n\t\t\t\t...shape.props,\n\t\t\t\tpoints: {\n\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t[handle.id]: { id: handle.id, index: handle.index, x: newPoint.x, y: newPoint.y },\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onHandleDragStart(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\t// For line shapes, if we're dragging a \"create\" handle, then\n\t\t// create a new vertex handle at that point; and make this handle\n\t\t// the handle that we're dragging.\n\t\tif (handle.type === 'create') {\n\t\t\treturn {\n\t\t\t\t...shape,\n\t\t\t\tprops: {\n\t\t\t\t\t...shape.props,\n\t\t\t\t\tpoints: {\n\t\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t\t[handle.index]: { id: handle.index, index: handle.index, x: handle.x, y: handle.y },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n\n\tcomponent(shape: TLLineShape) {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst colorMode = useColorMode()\n\t\tconst dv = getDisplayValues(this, shape, colorMode)\n\t\treturn (\n\t\t\t<SVGContainer style={{ minWidth: 50, minHeight: 50 }}>\n\t\t\t\t<LineShapeSvg shape={shape} strokeColor={dv.strokeColor} strokeWidth={dv.strokeWidth} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLLineShape): Path2D {\n\t\tconst strokeWidth = getDisplayValues(this, shape).strokeWidth * shape.props.scale\n\t\tconst path = getPathForLineShape(shape)\n\t\tconst { dash } = shape.props\n\n\t\treturn path.toPath2D({\n\t\t\tstyle: dash === 'draw' ? 'draw' : 'solid',\n\t\t\tstrokeWidth: 1,\n\t\t\tpasses: 1,\n\t\t\trandomSeed: shape.id,\n\t\t\toffset: 0,\n\t\t\troundness: strokeWidth * 2,\n\t\t})\n\t}\n\n\toverride toSvg(shape: TLLineShape, ctx: SvgExportContext) {\n\t\tconst dv = getDisplayValues(this, shape, ctx.colorMode)\n\t\treturn (\n\t\t\t<LineShapeSvg\n\t\t\t\tshouldScale\n\t\t\t\tshape={shape}\n\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride getHandleSnapGeometry(shape: TLLineShape): HandleSnapGeometry {\n\t\tconst points = linePointsToArray(shape)\n\t\treturn {\n\t\t\tpoints,\n\t\t\tgetSelfSnapPoints: (handle) => {\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// We want to skip the current and adjacent handles\n\t\t\t\treturn points.filter((_, i) => Math.abs(i - index) > 1).map(Vec.From)\n\t\t\t},\n\t\t\tgetSelfSnapOutline: (handle) => {\n\t\t\t\t// We want to skip the segments that include the handle, so\n\t\t\t\t// find the index of the handle that shares the same index property\n\t\t\t\t// as the initial dragging handle; this catches a quirk of create handles\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// Get all the outline segments from the shape that don't include the handle\n\t\t\t\tconst segments = this.getGeometry(shape)\n\t\t\t\t\t.getSegments()\n\t\t\t\t\t.filter((_, i) => i !== index - 1 && i !== index)\n\n\t\t\t\tif (!segments.length) return null\n\t\t\t\treturn new Group2d({ children: segments })\n\t\t\t},\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLLineShape,\n\t\tendShape: TLLineShape,\n\t\tt: number\n\t): TLLineShape['props'] {\n\t\tconst startPoints = linePointsToArray(startShape)\n\t\tconst endPoints = linePointsToArray(endShape)\n\n\t\tconst pointsToUseStart: TLLineShapePoint[] = []\n\t\tconst pointsToUseEnd: TLLineShapePoint[] = []\n\n\t\tlet index = ZERO_INDEX_KEY\n\n\t\tif (startPoints.length > endPoints.length) {\n\t\t\t// we'll need to expand points\n\t\t\tfor (let i = 0; i < startPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = { ...startPoints[i] }\n\t\t\t\tif (endPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[endPoints.length - 1], id: index }\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else if (endPoints.length > startPoints.length) {\n\t\t\t// we'll need to converge points\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i] }\n\t\t\t\tif (startPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseStart[i] = {\n\t\t\t\t\t\t...startPoints[startPoints.length - 1],\n\t\t\t\t\t\tid: index,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseStart[i] = { ...startPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else {\n\t\t\t// noop, easy\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = startPoints[i]\n\t\t\t\tpointsToUseEnd[i] = endPoints[i]\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tpoints: Object.fromEntries(\n\t\t\t\tpointsToUseStart.map((point, i) => {\n\t\t\t\t\tconst endPoint = pointsToUseEnd[i]\n\t\t\t\t\treturn [\n\t\t\t\t\t\tpoint.id,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...point,\n\t\t\t\t\t\t\tx: lerp(point.x, endPoint.x, t),\n\t\t\t\t\t\t\ty: lerp(point.y, endPoint.y, t),\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t\t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction linePointsToArray(shape: TLLineShape) {\n\tconst sorted = Object.values(shape.props.points).sort(sortByIndex)\n\t// Tolerate malformed data where two points share an index: keep only the first\n\t// point at each index, so getHandles' getIndexBetween never sees equal adjacent\n\t// indices (which would throw \"a2 >= a2\"). A no-op for well-formed lines.\n\treturn sorted.filter((point, i) => i === 0 || point.index !== sorted[i - 1].index)\n}\n\nconst pathCache = new WeakCache<TLLineShape, PathBuilder>()\nfunction getPathForLineShape(shape: TLLineShape): PathBuilder {\n\treturn pathCache.get(shape, () => {\n\t\tconst points = linePointsToArray(shape).map(Vec.From)\n\n\t\tswitch (shape.props.spline) {\n\t\t\tcase 'cubic': {\n\t\t\t\treturn PathBuilder.cubicSplineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t\tcase 'line': {\n\t\t\t\treturn PathBuilder.lineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction LineShapeSvg({\n\tshape,\n\tshouldScale = false,\n\tforceSolid = false,\n\tstrokeColor,\n\tstrokeWidth: baseStrokeWidth,\n}: {\n\tshape: TLLineShape\n\tshouldScale?: boolean\n\tforceSolid?: boolean\n\tstrokeColor: string\n\tstrokeWidth: number\n}) {\n\tconst path = getPathForLineShape(shape)\n\tconst { dash } = shape.props\n\n\tconst scaleFactor = 1 / shape.props.scale\n\n\tconst scale = shouldScale ? scaleFactor : 1\n\n\tconst strokeWidth = baseStrokeWidth * shape.props.scale\n\n\treturn path.toSvg({\n\t\tstyle: dash,\n\t\tstrokeWidth,\n\t\tforceSolid,\n\t\trandomSeed: shape.id,\n\t\tprops: {\n\t\t\ttransform: `scale(${scale})`,\n\t\t\tstroke: strokeColor,\n\t\t\tfill: 'none',\n\t\t},\n\t})\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -119,7 +119,7 @@ class Pointing extends import_editor.StateNode {
|
|
|
119
119
|
this.complete();
|
|
120
120
|
}
|
|
121
121
|
onLongPress() {
|
|
122
|
-
|
|
122
|
+
if (this.editor.getInstanceState().isCoarsePointer) this.cancel();
|
|
123
123
|
}
|
|
124
124
|
onCancel() {
|
|
125
125
|
this.cancel();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/line/toolStates/Pointing.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLLineShape,\n\tTLShapeId,\n\tVec,\n\tcreateShapeId,\n\tgetIndexAbove,\n\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLLineShape,\n\tTLShapeId,\n\tVec,\n\tcreateShapeId,\n\tgetIndexAbove,\n\tlast,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n\tstructuredClone,\n} from '@tldraw/editor'\n\n// Minimum distance, in screen pixels, between two shift-clicked handles before we merge them\nconst MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES = 2\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\tshape = {} as TLLineShape\n\n\tmarkId: string | undefined\n\n\toverride onEnter(info: { shapeId?: TLShapeId }) {\n\t\tconst { inputs } = this.editor\n\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\n\t\tthis.markId = undefined\n\n\t\t// Previously created line shape that we might be extending\n\t\tconst shape = info.shapeId && this.editor.getShape<TLLineShape>(info.shapeId)\n\n\t\tif (shape && inputs.getShiftKey()) {\n\t\t\t// Extending a previous shape\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_line:${shape.id}`)\n\t\t\tthis.shape = shape\n\n\t\t\tconst handles = this.editor.getShapeHandles(this.shape)\n\t\t\tif (!handles) return\n\n\t\t\tconst vertexHandles = handles.filter((h) => h.type === 'vertex').sort(sortByIndex)\n\t\t\tconst endHandle = vertexHandles[vertexHandles.length - 1]\n\t\t\tconst prevEndHandle = vertexHandles[vertexHandles.length - 2]\n\n\t\t\tconst shapePagePoint = Mat.applyToPoint(\n\t\t\t\tthis.editor.getShapeParentTransform(this.shape)!,\n\t\t\t\tnew Vec(this.shape.x, this.shape.y)\n\t\t\t)\n\t\t\t// nudge the point slightly to avoid zero-length lines\n\t\t\tconst nudgedPoint = Vec.Sub(currentPagePoint, shapePagePoint).addXY(0.1, 0.1)\n\t\t\tconst nextPoint = maybeSnapToGrid(nudgedPoint, this.editor)\n\t\t\tconst points = structuredClone(this.shape.props.points)\n\n\t\t\t// compare in screen space\n\t\t\tconst minDistance =\n\t\t\t\tMINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES / this.editor.getZoomLevel()\n\n\t\t\tif (\n\t\t\t\tVec.DistMin(endHandle, prevEndHandle, minDistance) ||\n\t\t\t\tVec.DistMin(nextPoint, endHandle, minDistance)\n\t\t\t) {\n\t\t\t\t// Don't add a new point if the distance between the last two points is too small\n\t\t\t\tpoints[endHandle.id] = {\n\t\t\t\t\tid: endHandle.id,\n\t\t\t\t\tindex: endHandle.index,\n\t\t\t\t\tx: nextPoint.x,\n\t\t\t\t\ty: nextPoint.y,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Add a new point\n\t\t\t\tconst nextIndex = getIndexAbove(endHandle.index)\n\t\t\t\tpoints[nextIndex] = {\n\t\t\t\t\tid: nextIndex,\n\t\t\t\t\tindex: nextIndex,\n\t\t\t\t\tx: nextPoint.x,\n\t\t\t\t\ty: nextPoint.y,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.editor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid: this.shape.id,\n\t\t\t\t\ttype: this.shape.type,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tpoints,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t])\n\t\t} else {\n\t\t\tconst id = createShapeId()\n\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_line:${id}`)\n\n\t\t\tconst newPoint = maybeSnapToGrid(currentPagePoint, this.editor)\n\n\t\t\tthis.editor.createShapes([\n\t\t\t\t{\n\t\t\t\t\tid,\n\t\t\t\t\ttype: 'line',\n\t\t\t\t\tx: newPoint.x,\n\t\t\t\t\ty: newPoint.y,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tscale: this.editor.getResizeScaleFactor(),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t])\n\n\t\t\tif (!this.editor.getShape(id)) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.editor.select(id)\n\t\t\tthis.shape = this.editor.getShape(id)!\n\t\t}\n\t}\n\n\toverride onPointerMove() {\n\t\tif (!this.shape) return\n\n\t\tif (this.editor.inputs.getIsDragging()) {\n\t\t\tconst handles = this.editor.getShapeHandles(this.shape)\n\t\t\tif (!handles) {\n\t\t\t\tif (this.markId) this.editor.bailToMark(this.markId)\n\t\t\t\tthrow Error('No handles found')\n\t\t\t}\n\t\t\tconst lastHandle = last(handles)!\n\t\t\tthis.editor.setCurrentTool('select.dragging_handle', {\n\t\t\t\tshape: this.shape,\n\t\t\t\tisCreating: true,\n\t\t\t\tcreatingMarkId: this.markId,\n\t\t\t\t// remove the offset that we added to the handle when we created it\n\t\t\t\thandle: { ...lastHandle, x: lastHandle.x - 0.1, y: lastHandle.y - 0.1 },\n\t\t\t\tonInteractionEnd: 'line',\n\t\t\t})\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onLongPress() {\n\t\t// On a touch (coarse pointer) long-press, cancel the pending shape so it leaves nothing behind.\n\t\tif (this.editor.getInstanceState().isCoarsePointer) this.cancel()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.parent.transition('idle')\n\t\tif (this.markId) this.editor.bailToMark(this.markId)\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n\n\tcomplete() {\n\t\tthis.parent.transition('idle', { shapeId: this.shape.id })\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n\n\tcancel() {\n\t\tif (this.markId) this.editor.bailToMark(this.markId)\n\t\tthis.parent.transition('idle', { shapeId: this.shape.id })\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -93,7 +93,7 @@ class Pointing extends import_editor.StateNode {
|
|
|
93
93
|
this.complete();
|
|
94
94
|
}
|
|
95
95
|
onLongPress() {
|
|
96
|
-
|
|
96
|
+
if (this.editor.getInstanceState().isCoarsePointer) this.cancel();
|
|
97
97
|
}
|
|
98
98
|
onInterrupt() {
|
|
99
99
|
this.cancel();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/note/toolStates/Pointing.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tEditor,\n\tStateNode,\n\tTLNoteShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tVec,\n\tcreateShapeId,\n\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import {\n\tEditor,\n\tStateNode,\n\tTLNoteShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tVec,\n\tcreateShapeId,\n\tmaybeSnapToGrid,\n} from '@tldraw/editor'\nimport { startEditingShapeWithRichText } from '../../../tools/SelectTool/selectHelpers'\nimport { getDisplayValues } from '../../shared/getDisplayValues'\nimport {\n\tNOTE_ADJACENT_POSITION_SNAP_RADIUS,\n\tgetAvailableNoteAdjacentPositions,\n} from '../noteHelpers'\nimport type { NoteShapeUtil } from '../NoteShapeUtil'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\tdragged = false\n\n\tinfo = {} as TLPointerEventInfo\n\n\tmarkId = ''\n\n\tshape = {} as TLNoteShape\n\n\tprivate shapeId!: TLShapeId\n\n\tprivate shapeCenter = new Vec()\n\n\tprivate hasCreatedShape = false\n\n\toverride onEnter() {\n\t\tconst { editor } = this\n\n\t\tthis.hasCreatedShape = false\n\t\tthis.shapeId = createShapeId()\n\t\tthis.markId = editor.markHistoryStoppingPoint(`creating_note:${this.shapeId}`)\n\n\t\t// Resolve note dimensions from the util's defaults\n\t\tconst noteUtil = editor.getShapeUtil('note') as NoteShapeUtil\n\t\tconst dv = getDisplayValues(noteUtil, { props: noteUtil.getDefaultProps() } as TLNoteShape)\n\n\t\t// Check for note pits; if the pointer is close to one, place the note centered on the pit\n\t\tconst center = editor.inputs.getOriginPagePoint().clone()\n\t\tconst offset = getNoteShapeAdjacentPositionOffset(\n\t\t\teditor,\n\t\t\tcenter,\n\t\t\teditor.getResizeScaleFactor(),\n\t\t\tdv.noteWidth,\n\t\t\tdv.noteHeight\n\t\t)\n\t\tif (offset) {\n\t\t\tcenter.sub(offset)\n\t\t}\n\t\tthis.shapeCenter = center\n\n\t\t// On a coarse pointer, defer creating the note until the gesture commits (a\n\t\t// drag or a release). The note is created on press, and a long-press cancels\n\t\t// the pending creation, so without deferral the note appears on press and\n\t\t// vanishes at the long-press mark \u2014 a visible flash. On a fine pointer there\n\t\t// is no long-press cancel, so create immediately to keep the press-and-drag feel.\n\t\tif (!editor.getInstanceState().isCoarsePointer) {\n\t\t\tthis.ensureShapeCreated()\n\t\t}\n\t}\n\n\t// Create the note now if it hasn't been created yet (idempotent). The deferred\n\t// drag and release paths route through here; a max-shapes failure cancels the\n\t// gesture, matching the original onEnter behaviour.\n\tprivate ensureShapeCreated() {\n\t\tif (this.hasCreatedShape) return\n\n\t\tconst shape = createNoteShape(this.editor, this.shapeId, this.shapeCenter)\n\t\tif (shape) {\n\t\t\tthis.shape = shape\n\t\t\tthis.hasCreatedShape = true\n\t\t} else {\n\t\t\tthis.cancel()\n\t\t}\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tif (this.editor.inputs.getIsDragging()) {\n\t\t\tthis.ensureShapeCreated()\n\t\t\tif (!this.hasCreatedShape) return\n\t\t\tthis.editor.setCurrentTool('select.translating', {\n\t\t\t\t...info,\n\t\t\t\ttarget: 'shape',\n\t\t\t\tshape: this.shape,\n\t\t\t\tonInteractionEnd: 'note',\n\t\t\t\tisCreating: true,\n\t\t\t\tcreatingMarkId: this.markId,\n\t\t\t\tonCreate: () => {\n\t\t\t\t\tstartEditingShapeWithRichText(this.editor, this.shape.id)\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onLongPress() {\n\t\t// On a touch (coarse pointer) long-press, cancel the pending shape so it leaves nothing behind.\n\t\tif (this.editor.getInstanceState().isCoarsePointer) this.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tthis.ensureShapeCreated()\n\t\tif (!this.hasCreatedShape) return\n\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\tthis.parent.transition('idle')\n\t\t} else {\n\t\t\tstartEditingShapeWithRichText(this.editor, this.shape.id, { info: this.info })\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\tthis.editor.bailToMark(this.markId)\n\t\tthis.parent.transition('idle', this.info)\n\t}\n}\n\nexport function getNoteShapeAdjacentPositionOffset(\n\teditor: Editor,\n\tcenter: Vec,\n\tscale: number,\n\tnoteWidth: number,\n\tnoteHeight: number\n) {\n\tlet min = NOTE_ADJACENT_POSITION_SNAP_RADIUS / editor.getZoomLevel() // in screen space\n\tlet offset: Vec | undefined\n\tfor (const pit of getAvailableNoteAdjacentPositions(editor, {\n\t\trotation: 0,\n\t\tscale,\n\t\textraHeight: 0,\n\t\tnoteWidth,\n\t\tnoteHeight,\n\t})) {\n\t\t// only check page rotations of zero\n\t\tconst deltaToPit = Vec.Sub(center, pit)\n\t\tconst dist = deltaToPit.len()\n\t\tif (dist < min) {\n\t\t\tmin = dist\n\t\t\toffset = deltaToPit\n\t\t}\n\t}\n\treturn offset\n}\n\nexport function createNoteShape(editor: Editor, id: TLShapeId, center: Vec) {\n\teditor.createShape({\n\t\tid,\n\t\ttype: 'note',\n\t\tx: center.x,\n\t\ty: center.y,\n\t\tprops: {\n\t\t\tscale: editor.getResizeScaleFactor(),\n\t\t},\n\t})\n\n\tconst shape = editor.getShape<TLNoteShape>(id)\n\t// Should never happen since we just checked, but just in case\n\tif (!shape) return\n\n\teditor.select(id)\n\tconst bounds = editor.getShapeGeometry(shape).bounds\n\tconst newPoint = maybeSnapToGrid(\n\t\tnew Vec(shape.x - bounds.width / 2, shape.y - bounds.height / 2),\n\t\teditor\n\t)\n\n\t// Center the text around the created point\n\teditor.updateShapes([\n\t\t{\n\t\t\tid,\n\t\t\ttype: 'note',\n\t\t\tx: newPoint.x,\n\t\t\ty: newPoint.y,\n\t\t},\n\t])\n\n\treturn editor.getShape<TLNoteShape>(id)\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBASO;AACP,2BAA8C;AAC9C,8BAAiC;AACjC,yBAGO;AAGA,MAAM,iBAAiB,wBAAU;AAAA,EACvC,OAAgB,KAAK;AAAA,EAErB,UAAU;AAAA,EAEV,OAAO,CAAC;AAAA,EAER,SAAS;AAAA,EAET,QAAQ,CAAC;AAAA,EAED;AAAA,EAEA,cAAc,IAAI,kBAAI;AAAA,EAEtB,kBAAkB;AAAA,EAEjB,UAAU;AAClB,UAAM,EAAE,OAAO,IAAI;AAEnB,SAAK,kBAAkB;AACvB,SAAK,cAAU,6BAAc;AAC7B,SAAK,SAAS,OAAO,yBAAyB,iBAAiB,KAAK,OAAO,EAAE;AAG7E,UAAM,WAAW,OAAO,aAAa,MAAM;AAC3C,UAAM,SAAK,0CAAiB,UAAU,EAAE,OAAO,SAAS,gBAAgB,EAAE,CAAgB;AAG1F,UAAM,SAAS,OAAO,OAAO,mBAAmB,EAAE,MAAM;AACxD,UAAM,SAAS;AAAA,MACd;AAAA,MACA;AAAA,MACA,OAAO,qBAAqB;AAAA,MAC5B,GAAG;AAAA,MACH,GAAG;AAAA,IACJ;AACA,QAAI,QAAQ;AACX,aAAO,IAAI,MAAM;AAAA,IAClB;AACA,SAAK,cAAc;AAOnB,QAAI,CAAC,OAAO,iBAAiB,EAAE,iBAAiB;AAC/C,WAAK,mBAAmB;AAAA,IACzB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB;AAC5B,QAAI,KAAK,gBAAiB;AAE1B,UAAM,QAAQ,gBAAgB,KAAK,QAAQ,KAAK,SAAS,KAAK,WAAW;AACzE,QAAI,OAAO;AACV,WAAK,QAAQ;AACb,WAAK,kBAAkB;AAAA,IACxB,OAAO;AACN,WAAK,OAAO;AAAA,IACb;AAAA,EACD;AAAA,EAES,cAAc,MAA0B;AAChD,QAAI,KAAK,OAAO,OAAO,cAAc,GAAG;AACvC,WAAK,mBAAmB;AACxB,UAAI,CAAC,KAAK,gBAAiB;AAC3B,WAAK,OAAO,eAAe,sBAAsB;AAAA,QAChD,GAAG;AAAA,QACH,QAAQ;AAAA,QACR,OAAO,KAAK;AAAA,QACZ,kBAAkB;AAAA,QAClB,YAAY;AAAA,QACZ,gBAAgB,KAAK;AAAA,QACrB,UAAU,MAAM;AACf,kEAA8B,KAAK,QAAQ,KAAK,MAAM,EAAE;AAAA,QACzD;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,cAAc;AAEtB,QAAI,KAAK,OAAO,iBAAiB,EAAE,gBAAiB,MAAK,OAAO;AAAA,EACjE;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAEQ,WAAW;AAClB,SAAK,mBAAmB;AACxB,QAAI,CAAC,KAAK,gBAAiB;AAC3B,QAAI,KAAK,OAAO,iBAAiB,EAAE,cAAc;AAChD,WAAK,OAAO,WAAW,MAAM;AAAA,IAC9B,OAAO;AACN,8DAA8B,KAAK,QAAQ,KAAK,MAAM,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;AAAA,IAC9E;AAAA,EACD;AAAA,EAEQ,SAAS;AAChB,SAAK,OAAO,WAAW,KAAK,MAAM;AAClC,SAAK,OAAO,WAAW,QAAQ,KAAK,IAAI;AAAA,EACzC;AACD;AAEO,SAAS,mCACf,QACA,QACA,OACA,WACA,YACC;AACD,MAAI,MAAM,wDAAqC,OAAO,aAAa;AACnE,MAAI;AACJ,aAAW,WAAO,sDAAkC,QAAQ;AAAA,IAC3D,UAAU;AAAA,IACV;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,EACD,CAAC,GAAG;AAEH,UAAM,aAAa,kBAAI,IAAI,QAAQ,GAAG;AACtC,UAAM,OAAO,WAAW,IAAI;AAC5B,QAAI,OAAO,KAAK;AACf,YAAM;AACN,eAAS;AAAA,IACV;AAAA,EACD;AACA,SAAO;AACR;AAEO,SAAS,gBAAgB,QAAgB,IAAe,QAAa;AAC3E,SAAO,YAAY;AAAA,IAClB;AAAA,IACA,MAAM;AAAA,IACN,GAAG,OAAO;AAAA,IACV,GAAG,OAAO;AAAA,IACV,OAAO;AAAA,MACN,OAAO,OAAO,qBAAqB;AAAA,IACpC;AAAA,EACD,CAAC;AAED,QAAM,QAAQ,OAAO,SAAsB,EAAE;AAE7C,MAAI,CAAC,MAAO;AAEZ,SAAO,OAAO,EAAE;AAChB,QAAM,SAAS,OAAO,iBAAiB,KAAK,EAAE;AAC9C,QAAM,eAAW;AAAA,IAChB,IAAI,kBAAI,MAAM,IAAI,OAAO,QAAQ,GAAG,MAAM,IAAI,OAAO,SAAS,CAAC;AAAA,IAC/D;AAAA,EACD;AAGA,SAAO,aAAa;AAAA,IACnB;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN,GAAG,SAAS;AAAA,MACZ,GAAG,SAAS;AAAA,IACb;AAAA,EACD,CAAC;AAED,SAAO,OAAO,SAAsB,EAAE;AACvC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -83,7 +83,7 @@ function createCropAroundCenter(centerX, centerY, width, height, isCircle) {
|
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
function getCropBox(shape, info, opts = {}) {
|
|
86
|
-
const { handle, change, crop, aspectRatioLocked } = info;
|
|
86
|
+
const { handle, change, crop, aspectRatioLocked, isResizingFromCenter } = info;
|
|
87
87
|
const { w, h } = info.uncroppedSize;
|
|
88
88
|
const { minWidth = MIN_CROP_SIZE, minHeight = MIN_CROP_SIZE } = opts;
|
|
89
89
|
if (w < minWidth || h < minHeight || change.x === 0 && change.y === 0) {
|
|
@@ -97,21 +97,67 @@ function getCropBox(shape, info, opts = {}) {
|
|
|
97
97
|
);
|
|
98
98
|
const targetRatio = prevCropBox.aspectRatio;
|
|
99
99
|
const tempBox = prevCropBox.clone();
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
100
|
+
const movesLeft = handle === "top_left" || handle === "bottom_left" || handle === "left";
|
|
101
|
+
const movesRight = handle === "top_right" || handle === "bottom_right" || handle === "right";
|
|
102
|
+
const movesTop = handle === "top_left" || handle === "top_right" || handle === "top";
|
|
103
|
+
const movesBottom = handle === "bottom_left" || handle === "bottom_right" || handle === "bottom";
|
|
104
|
+
if (isResizingFromCenter) {
|
|
105
|
+
const cx = prevCropBox.midX;
|
|
106
|
+
const cy = prevCropBox.midY;
|
|
107
|
+
let halfW = prevCropBox.w / 2;
|
|
108
|
+
let halfH = prevCropBox.h / 2;
|
|
109
|
+
if (movesLeft) halfW = cx - (prevCropBox.x + change.x);
|
|
110
|
+
else if (movesRight) halfW = prevCropBox.maxX + change.x - cx;
|
|
111
|
+
if (movesTop) halfH = cy - (prevCropBox.y + change.y);
|
|
112
|
+
else if (movesBottom) halfH = prevCropBox.maxY + change.y - cy;
|
|
113
|
+
if (aspectRatioLocked) {
|
|
114
|
+
const isCorner = (movesLeft || movesRight) && (movesTop || movesBottom);
|
|
115
|
+
let drivingHalfW;
|
|
116
|
+
if (isCorner) {
|
|
117
|
+
drivingHalfW = halfW / halfH > targetRatio ? halfW : halfH * targetRatio;
|
|
118
|
+
} else if (movesLeft || movesRight) {
|
|
119
|
+
drivingHalfW = halfW;
|
|
120
|
+
} else {
|
|
121
|
+
drivingHalfW = halfH * targetRatio;
|
|
122
|
+
}
|
|
123
|
+
const minHalfW = Math.max(minWidth / 2, minHeight / 2 * targetRatio);
|
|
124
|
+
const maxHalfW = Math.min(cx, w - cx, cy * targetRatio, (h - cy) * targetRatio);
|
|
125
|
+
if (maxHalfW < minHalfW) return;
|
|
126
|
+
halfW = (0, import_editor.clamp)(drivingHalfW, minHalfW, maxHalfW);
|
|
127
|
+
halfH = halfW / targetRatio;
|
|
128
|
+
} else {
|
|
129
|
+
if (movesLeft || movesRight) {
|
|
130
|
+
const maxHalfW = Math.min(cx, w - cx);
|
|
131
|
+
if (maxHalfW < minWidth / 2) return;
|
|
132
|
+
halfW = (0, import_editor.clamp)(halfW, minWidth / 2, maxHalfW);
|
|
133
|
+
}
|
|
134
|
+
if (movesTop || movesBottom) {
|
|
135
|
+
const maxHalfH = Math.min(cy, h - cy);
|
|
136
|
+
if (maxHalfH < minHeight / 2) return;
|
|
137
|
+
halfH = (0, import_editor.clamp)(halfH, minHeight / 2, maxHalfH);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
tempBox.x = cx - halfW;
|
|
141
|
+
tempBox.y = cy - halfH;
|
|
142
|
+
tempBox.w = halfW * 2;
|
|
143
|
+
tempBox.h = halfH * 2;
|
|
144
|
+
} else {
|
|
145
|
+
if (movesLeft) {
|
|
146
|
+
tempBox.x = (0, import_editor.clamp)(tempBox.x + change.x, 0, prevCropBox.maxX - minWidth);
|
|
147
|
+
tempBox.w = prevCropBox.maxX - tempBox.x;
|
|
148
|
+
} else if (movesRight) {
|
|
149
|
+
const tempRight = (0, import_editor.clamp)(tempBox.maxX + change.x, prevCropBox.x + minWidth, w);
|
|
150
|
+
tempBox.w = tempRight - tempBox.x;
|
|
151
|
+
}
|
|
152
|
+
if (movesTop) {
|
|
153
|
+
tempBox.y = (0, import_editor.clamp)(tempBox.y + change.y, 0, prevCropBox.maxY - minHeight);
|
|
154
|
+
tempBox.h = prevCropBox.maxY - tempBox.y;
|
|
155
|
+
} else if (movesBottom) {
|
|
156
|
+
const tempBottom = (0, import_editor.clamp)(tempBox.maxY + change.y, prevCropBox.y + minHeight, h);
|
|
157
|
+
tempBox.h = tempBottom - tempBox.y;
|
|
158
|
+
}
|
|
113
159
|
}
|
|
114
|
-
if (aspectRatioLocked) {
|
|
160
|
+
if (aspectRatioLocked && !isResizingFromCenter) {
|
|
115
161
|
const isXLimiting = tempBox.aspectRatio > targetRatio;
|
|
116
162
|
if (isXLimiting) {
|
|
117
163
|
tempBox.h = tempBox.w / targetRatio;
|