tldraw 5.4.0-next.ef99ab47e5ce → 5.4.0
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 +2826 -3226
- package/RELEASE_NOTES.md +190 -2
- package/dist-cjs/index.d.ts +264 -275
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/defaultExternalContentHandlers.js +32 -16
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/curved-arrow.js +2 -2
- package/dist-cjs/lib/shapes/arrow/curved-arrow.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/getArrowInfo.js +1 -1
- package/dist-cjs/lib/shapes/arrow/getArrowInfo.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/straight-arrow.js +2 -2
- package/dist-cjs/lib/shapes/arrow/straight-arrow.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js +2 -3
- package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +7 -5
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +8 -6
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/getGeoShapePath.js +3 -1
- package/dist-cjs/lib/shapes/geo/getGeoShapePath.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/toolStates/Idle.js +2 -3
- package/dist-cjs/lib/shapes/geo/toolStates/Idle.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/toolStates/Pointing.js +2 -6
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/note/noteHelpers.js +6 -5
- package/dist-cjs/lib/shapes/note/noteHelpers.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 +1 -1
- package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Idle.js +1 -1
- package/dist-cjs/lib/shapes/text/toolStates/Idle.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +1 -0
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +2 -0
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
- package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js +6 -0
- package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/SelectTool.js +3 -0
- package/dist-cjs/lib/tools/SelectTool/SelectTool.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js +1 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/Crop.js +1 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/Crop.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -3
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +6 -3
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js +3 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js +1 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +22 -30
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js +1 -3
- package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +4 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/selectHelpers.js +10 -0
- package/dist-cjs/lib/tools/SelectTool/selectHelpers.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +2 -3
- package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +1 -11
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +6 -1
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenuContent.js +1 -1
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenuContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Dialogs.js +8 -0
- package/dist-cjs/lib/ui/components/Dialogs.js.map +2 -2
- package/dist-cjs/lib/ui/components/EditLinkDialog.js +5 -5
- package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +4 -20
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuItem.js +1 -2
- package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js +2 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +1 -0
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +10 -8
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +20 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +8 -8
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +2 -0
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useCommentingEnabled.js +1 -1
- package/dist-cjs/lib/ui/hooks/useCommentingEnabled.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useFlatten.js +42 -23
- package/dist-cjs/lib/ui/hooks/useFlatten.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.d.mts +264 -275
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +32 -16
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/curved-arrow.mjs +2 -2
- package/dist-esm/lib/shapes/arrow/curved-arrow.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/getArrowInfo.mjs +1 -1
- package/dist-esm/lib/shapes/arrow/getArrowInfo.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/straight-arrow.mjs +2 -2
- package/dist-esm/lib/shapes/arrow/straight-arrow.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs +3 -4
- package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +7 -5
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +8 -6
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/getGeoShapePath.mjs +3 -1
- package/dist-esm/lib/shapes/geo/getGeoShapePath.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs +3 -4
- package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +1 -1
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +2 -7
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +4 -4
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/noteHelpers.mjs +6 -5
- package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +1 -1
- package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/crop.mjs +1 -1
- package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Idle.mjs +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +1 -0
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +2 -0
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
- package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs +6 -0
- package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/SelectTool.mjs +3 -0
- package/dist-esm/lib/tools/SelectTool/SelectTool.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs +1 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/Crop.mjs +1 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/Crop.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -3
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +6 -3
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs +3 -0
- package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +5 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +22 -31
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs +1 -3
- package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +4 -1
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs +10 -0
- package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs.map +2 -2
- package/dist-esm/lib/ui/TldrawUi.mjs +2 -3
- package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +2 -12
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +7 -2
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenuContent.mjs +1 -1
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenuContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Dialogs.mjs +9 -1
- package/dist-esm/lib/ui/components/Dialogs.mjs.map +2 -2
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs +5 -5
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +5 -22
- package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuItem.mjs +1 -2
- package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs +2 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +1 -0
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +10 -8
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +20 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +8 -8
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -0
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useCommentingEnabled.mjs +2 -2
- package/dist-esm/lib/ui/hooks/useCommentingEnabled.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useFlatten.mjs +42 -23
- package/dist-esm/lib/ui/hooks/useFlatten.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 +12 -6
- package/src/lib/defaultExternalContentHandlers.test.ts +43 -0
- package/src/lib/defaultExternalContentHandlers.ts +40 -18
- package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +17 -0
- package/src/lib/shapes/arrow/curved-arrow.ts +2 -2
- package/src/lib/shapes/arrow/elbow/getElbowArrowInfo.tsx +5 -3
- package/src/lib/shapes/arrow/getArrowInfo.ts +2 -1
- package/src/lib/shapes/arrow/straight-arrow.ts +2 -2
- package/src/lib/shapes/arrow/toolStates/Idle.tsx +3 -4
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +10 -6
- package/src/lib/shapes/draw/DrawShapeTool.test.ts +19 -0
- package/src/lib/shapes/draw/toolStates/Drawing.ts +12 -6
- package/src/lib/shapes/frame/FrameShapeTool.test.ts +17 -0
- package/src/lib/shapes/geo/GeoShapeTool.test.ts +28 -0
- package/src/lib/shapes/geo/getGeoShapePath.ts +3 -1
- package/src/lib/shapes/geo/toolStates/Idle.ts +3 -4
- package/src/lib/shapes/geo/toolStates/Pointing.ts +2 -1
- package/src/lib/shapes/line/LineShapeTool.test.ts +30 -1
- package/src/lib/shapes/line/toolStates/Pointing.ts +6 -7
- package/src/lib/shapes/note/NoteShapeTool.test.ts +45 -0
- package/src/lib/shapes/note/NoteShapeUtil.tsx +7 -4
- package/src/lib/shapes/note/noteHelpers.ts +18 -8
- package/src/lib/shapes/note/toolStates/Pointing.ts +2 -1
- package/src/lib/shapes/shared/crop.ts +7 -1
- package/src/lib/shapes/text/TextShapeTool.test.ts +33 -0
- package/src/lib/shapes/text/toolStates/Idle.ts +2 -2
- package/src/lib/shapes/text/toolStates/Pointing.ts +3 -0
- package/src/lib/shapes/video/VideoShapeUtil.tsx +4 -2
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +5 -0
- package/src/lib/tools/HandTool/childStates/OneFingerZooming.ts +10 -0
- package/src/lib/tools/SelectTool/SelectTool.ts +4 -0
- package/src/lib/tools/SelectTool/childStates/Brushing.ts +4 -0
- package/src/lib/tools/SelectTool/childStates/Crop/Crop.ts +4 -0
- package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +3 -4
- package/src/lib/tools/SelectTool/childStates/Idle.ts +10 -3
- package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +1 -1
- package/src/lib/tools/SelectTool/childStates/PointingCanvas.ts +4 -0
- package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +6 -1
- package/src/lib/tools/SelectTool/childStates/PointingShape.ts +4 -1
- package/src/lib/tools/SelectTool/childStates/Resizing.ts +30 -33
- package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +3 -3
- package/src/lib/tools/SelectTool/childStates/Translating.ts +6 -0
- package/src/lib/tools/SelectTool/selectHelpers.ts +21 -0
- package/src/lib/ui/TldrawUi.tsx +1 -2
- package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +4 -14
- package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +8 -2
- package/src/lib/ui/components/ContextMenu/DefaultContextMenuContent.tsx +5 -1
- package/src/lib/ui/components/Dialogs.tsx +17 -1
- package/src/lib/ui/components/EditLinkDialog.tsx +8 -7
- package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +5 -23
- package/src/lib/ui/components/SharePanel/DefaultPeopleMenuItem.tsx +2 -3
- package/src/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.tsx +2 -0
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +1 -0
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +13 -8
- package/src/lib/ui/components/primitives/TldrawUiSlider.test.tsx +92 -0
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +25 -1
- package/src/lib/ui/context/actions.tsx +25 -8
- package/src/lib/ui/hooks/useClipboardEvents.ts +2 -0
- package/src/lib/ui/hooks/useCommentingEnabled.ts +5 -3
- package/src/lib/ui/hooks/useFlatten.ts +56 -23
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +7 -16
- package/src/test/ClickManager.test.ts +18 -0
- package/src/test/Editor.test.tsx +3 -0
- package/src/test/EraserTool.test.ts +18 -2
- package/src/test/HandTool.test.ts +21 -0
- package/src/test/LaserTool.test.ts +46 -0
- package/src/test/ScribbleManager.test.ts +19 -0
- package/src/test/SelectTool.test.ts +110 -0
- package/src/test/TldrawEditor.test.tsx +18 -0
- package/src/test/VideoShapeUtil.test.tsx +126 -0
- package/src/test/actions-menu-readonly.test.tsx +37 -0
- package/src/test/bookmark-shapes.test.ts +110 -0
- package/src/test/commands/__snapshots__/packShapes.test.ts.snap +6 -6
- package/src/test/commands/clipboard.test.ts +36 -1
- package/src/test/commands/lockShapes.test.ts +11 -0
- package/src/test/commands/packShapes.test.ts +20 -0
- package/src/test/commands/putContent.test.ts +35 -1
- package/src/test/commands/setCamera.test.ts +69 -0
- package/src/test/commands/stackShapes.test.ts +12 -0
- package/src/test/commands/updateViewportPageBounds.test.ts +8 -0
- package/src/test/cropping.test.ts +162 -0
- package/src/test/customSnapping.test.tsx +32 -0
- package/src/test/defaultHandleExternalFileContent.test.ts +86 -0
- package/src/test/drawing.test.ts +60 -1
- package/src/test/duplicate.test.ts +22 -0
- package/src/test/flatten.test.ts +135 -0
- package/src/test/frames.test.ts +51 -0
- package/src/test/getShapeAtPoint.test.ts +44 -1
- package/src/test/handleDeepLink.test.tsx +15 -0
- package/src/test/minimap-wheel.test.tsx +48 -0
- package/src/test/resizing.test.ts +46 -0
- package/src/test/selection-omnibus.test.ts +50 -0
- package/src/test/spacebarPanning.test.ts +58 -0
- package/src/test/translating.test.ts +42 -0
- package/src/test/ui/AltTextEditor.test.tsx +51 -0
- package/src/test/ui/ContextMenu.test.tsx +61 -2
- package/src/test/ui/EditLinkDialog.test.tsx +77 -0
- package/src/test/ui/ImageToolbar.test.tsx +58 -0
- package/src/test/ui/StylePanel.test.tsx +33 -2
- package/src/test/ui/keyboardShortcuts.test.tsx +27 -0
- package/src/test/ui/presenceActivity.test.tsx +44 -0
- package/src/test/ui/unlockAll.test.tsx +55 -0
- package/src/test/ui-outside-editor.test.tsx +74 -0
- package/src/test/viewport-following.test.ts +29 -1
- package/tldraw.css +7 -16
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/arrow/elbow/getElbowArrowInfo.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tapproximately,\n\tassert,\n\tBox,\n\tEditor,\n\texhaustiveSwitchError,\n\tGeometry2dFilters,\n\tlerp,\n\tMat,\n\tTLArrowBinding,\n\tTLArrowBindingProps,\n\tTLArrowShape,\n\tTLShapeId,\n\tVec,\n\tVecLike,\n\tVecModel,\n} from '@tldraw/editor'\nimport { STROKE_SIZES } from '../../shared/default-shape-constants'\nimport { ArrowShapeUtil } from '../ArrowShapeUtil'\nimport { BOUND_ARROW_OFFSET, TLArrowBindings } from '../shared'\nimport {\n\tElbowArrowAxes,\n\tElbowArrowBox,\n\tElbowArrowBoxEdges,\n\tElbowArrowEdge,\n\tElbowArrowInfo,\n\tElbowArrowInfoWithoutRoute,\n\tElbowArrowOptions,\n\tElbowArrowRoute,\n\tElbowArrowSide,\n\tElbowArrowSideWithAxis,\n\tElbowArrowTargetBox,\n\tElbowArrowTerminal,\n} from './definitions'\nimport { createRange, expandRange, isWithinRange, rangeSize, subtractRange } from './range'\nimport { ElbowArrowWorkingInfo } from './routes/ElbowArrowWorkingInfo'\nimport {\n\trouteArrowWithAutoEdgePicking,\n\trouteArrowWithManualEdgePicking,\n\trouteArrowWithPartialEdgePicking,\n} from './routes/routeArrowWithAutoEdgePicking'\n\nexport function getElbowArrowInfo(\n\teditor: Editor,\n\tarrow: TLArrowShape,\n\tbindings: TLArrowBindings,\n\tarrowStrokeWidth?: number\n): ElbowArrowInfo {\n\tconst shapeOptions = editor.getShapeUtil<ArrowShapeUtil>(arrow.type).options\n\tconst options: ElbowArrowOptions = {\n\t\telbowMidpoint: arrow.props.elbowMidPoint,\n\t\texpandElbowLegLength: shapeOptions.expandElbowLegLength[arrow.props.size] * arrow.props.scale,\n\t\tminElbowLegLength: shapeOptions.minElbowLegLength[arrow.props.size] * arrow.props.scale,\n\t}\n\n\t// Before we can do anything else, we need to find the start and end terminals of the arrow.\n\t// These contain the binding info, geometry, bounds, etc.\n\tlet startTerminal = getElbowArrowTerminalInfo(\n\t\teditor,\n\t\tarrow,\n\t\tbindings.start,\n\t\tarrow.props.start,\n\t\tarrowStrokeWidth\n\t)\n\tlet endTerminal = getElbowArrowTerminalInfo(\n\t\teditor,\n\t\tarrow,\n\t\tbindings.end,\n\t\tarrow.props.end,\n\t\tarrowStrokeWidth\n\t)\n\t// unclosed paths are weird - we handle them outside of the initial terminal info.\n\tstartTerminal = adjustTerminalForUnclosedPathIfNeeded(startTerminal, endTerminal, options)\n\tendTerminal = adjustTerminalForUnclosedPathIfNeeded(endTerminal, startTerminal, options)\n\n\t// Ther terminal might include a \"side\" if the user has explicitly indicated what side the arrow\n\t// should come from. There are two terminals, and two cases for each terminal (explicit side or\n\t// not), for a total for 4 cases to handle. In order to keep things a bit simpler though, we\n\t// only handle 3 cases: if start no side and end has a side, we flip them around. From here on\n\t// out, we use A and B to refer to the terminals as they may be swapped.\n\tconst swapOrder = !!(!startTerminal.side && endTerminal.side)\n\n\tlet { aTerminal, bTerminal } = swapOrder\n\t\t? { aTerminal: endTerminal, bTerminal: startTerminal }\n\t\t: { aTerminal: startTerminal, bTerminal: endTerminal }\n\n\t// We model each edge that an arrow might enter/exit from separately. If an edge is blocked,\n\t// `getUsableEdge` might return null.\n\tlet edgesA = {\n\t\ttop: getUsableEdge(aTerminal, bTerminal, 'top', options),\n\t\tright: getUsableEdge(aTerminal, bTerminal, 'right', options),\n\t\tbottom: getUsableEdge(aTerminal, bTerminal, 'bottom', options),\n\t\tleft: getUsableEdge(aTerminal, bTerminal, 'left', options),\n\t}\n\n\tlet edgesB = {\n\t\ttop: getUsableEdge(bTerminal, aTerminal, 'top', options),\n\t\tright: getUsableEdge(bTerminal, aTerminal, 'right', options),\n\t\tbottom: getUsableEdge(bTerminal, aTerminal, 'bottom', options),\n\t\tleft: getUsableEdge(bTerminal, aTerminal, 'left', options),\n\t}\n\n\t// We we don't have a usable edge because it's blocked, we can convert some of the terminals to\n\t// points. Point terminals have less strict edge routing rules, but don't look as good\n\t// generally. For example, the arrow might go through the shape instead of around.\n\tconst aIsUsable = hasUsableEdge(edgesA, aTerminal.side)\n\tconst bIsUsable = hasUsableEdge(edgesB, bTerminal.side)\n\tlet needsNewEdges = false\n\tif (!aIsUsable || !bIsUsable) {\n\t\tneedsNewEdges = true\n\t\tif (!aIsUsable) {\n\t\t\tbTerminal = convertTerminalToPoint(bTerminal)\n\t\t}\n\n\t\tif (!bIsUsable) {\n\t\t\taTerminal = convertTerminalToPoint(aTerminal)\n\t\t}\n\n\t\tif (bTerminal.bounds.containsPoint(aTerminal.target, options.expandElbowLegLength)) {\n\t\t\tbTerminal = convertTerminalToPoint(bTerminal)\n\t\t}\n\n\t\tif (aTerminal.bounds.containsPoint(bTerminal.target, options.expandElbowLegLength)) {\n\t\t\taTerminal = convertTerminalToPoint(aTerminal)\n\t\t}\n\t}\n\n\tif (needsNewEdges) {\n\t\tedgesA = {\n\t\t\ttop: getUsableEdge(aTerminal, bTerminal, 'top', options),\n\t\t\tright: getUsableEdge(aTerminal, bTerminal, 'right', options),\n\t\t\tbottom: getUsableEdge(aTerminal, bTerminal, 'bottom', options),\n\t\t\tleft: getUsableEdge(aTerminal, bTerminal, 'left', options),\n\t\t}\n\n\t\tedgesB = {\n\t\t\ttop: getUsableEdge(bTerminal, aTerminal, 'top', options),\n\t\t\tright: getUsableEdge(bTerminal, aTerminal, 'right', options),\n\t\t\tbottom: getUsableEdge(bTerminal, aTerminal, 'bottom', options),\n\t\t\tleft: getUsableEdge(bTerminal, aTerminal, 'left', options),\n\t\t}\n\t}\n\n\t// We expand the bounds of the terminals so we can route arrows around them without the arrows\n\t// being too close to the shapes.\n\tconst expandedA = aTerminal.isPoint\n\t\t? aTerminal.bounds\n\t\t: aTerminal.bounds.clone().expandBy(options.expandElbowLegLength)\n\tconst expandedB = bTerminal.isPoint\n\t\t? bTerminal.bounds\n\t\t: bTerminal.bounds.clone().expandBy(options.expandElbowLegLength)\n\n\tconst common: ElbowArrowBox = {\n\t\toriginal: Box.Common([aTerminal.bounds, bTerminal.bounds]),\n\t\texpanded: Box.Common([expandedA, expandedB]),\n\t}\n\n\t// Calculate the gaps between the two terminals. If gap is positive, B is to the right of A. If\n\t// it's negative, the opposite is true. If it's 0, there's no gap between the shapes in that\n\t// dimension.\n\tlet gapX = bTerminal.bounds.minX - aTerminal.bounds.maxX\n\tif (gapX < 0) {\n\t\tgapX = aTerminal.bounds.minX - bTerminal.bounds.maxX\n\t\tif (gapX < 0) {\n\t\t\tgapX = 0\n\t\t}\n\t\tgapX = -gapX\n\t}\n\tlet gapY = bTerminal.bounds.minY - aTerminal.bounds.maxY\n\tif (gapY < 0) {\n\t\tgapY = aTerminal.bounds.minY - bTerminal.bounds.maxY\n\t\tif (gapY < 0) {\n\t\t\tgapY = 0\n\t\t}\n\t\tgapY = -gapY\n\t}\n\n\t// The midpoint of the gap is a useful point to route arrows through, but the user can also drag\n\t// it to choose a new midpoint. First, we calculate some constraints we'll need to keep in mind\n\t// when figuring out the midpoint...\n\tconst aMinLength = aTerminal.minEndSegmentLength * 3\n\tconst bMinLength = bTerminal.minEndSegmentLength * 3\n\tconst minLegDistanceNeeded =\n\t\t(aTerminal.isPoint ? aMinLength : options.minElbowLegLength) +\n\t\t(bTerminal.isPoint ? bMinLength : options.minElbowLegLength)\n\n\t// ...then, the possible range of the midpoint. This is also used when dragging the midpoint.\n\tlet mxRange: null | { a: number; b: number } = null\n\tif (gapX > minLegDistanceNeeded) {\n\t\tmxRange = {\n\t\t\ta: aTerminal.isPoint ? aTerminal.bounds.maxX + aMinLength : expandedA.maxX,\n\t\t\tb: bTerminal.isPoint ? bTerminal.bounds.minX - bMinLength : expandedB.minX,\n\t\t}\n\t} else if (gapX < -minLegDistanceNeeded) {\n\t\tmxRange = {\n\t\t\ta: aTerminal.isPoint ? aTerminal.bounds.minX - aMinLength : expandedA.minX,\n\t\t\tb: bTerminal.isPoint ? bTerminal.bounds.maxX + bMinLength : expandedB.maxX,\n\t\t}\n\t}\n\n\tlet myRange: null | { a: number; b: number } = null\n\tif (gapY > minLegDistanceNeeded) {\n\t\tmyRange = {\n\t\t\ta: aTerminal.isPoint ? aTerminal.bounds.maxY + aMinLength : expandedA.maxY,\n\t\t\tb: bTerminal.isPoint ? bTerminal.bounds.minY - bMinLength : expandedB.minY,\n\t\t}\n\t} else if (gapY < -minLegDistanceNeeded) {\n\t\tmyRange = {\n\t\t\ta: aTerminal.isPoint ? aTerminal.bounds.minY - aMinLength : expandedA.minY,\n\t\t\tb: bTerminal.isPoint ? bTerminal.bounds.maxY + bMinLength : expandedB.maxY,\n\t\t}\n\t}\n\n\t// and finally we take the range and the midpoint prop and calculate the actual position of the\n\t// midpoint. Note that the midpoint and midpoint range can be null if the gap is too small for a\n\t// midpoint line.\n\tconst midpoint = swapOrder ? 1 - options.elbowMidpoint : options.elbowMidpoint\n\tconst mx = mxRange ? lerp(mxRange.a, mxRange.b, midpoint) : null\n\tconst my = myRange ? lerp(myRange.a, myRange.b, midpoint) : null\n\n\t// The info without route is given to the route-finding functions to route between the two\n\t// terminals.\n\tconst info: ElbowArrowInfoWithoutRoute = {\n\t\toptions,\n\t\tswapOrder,\n\t\tA: {\n\t\t\tisPoint: aTerminal.isPoint,\n\t\t\ttarget: aTerminal.target,\n\t\t\tisExact: aTerminal.isExact,\n\t\t\tarrowheadOffset: aTerminal.arrowheadOffset,\n\t\t\tminEndSegmentLength: aTerminal.minEndSegmentLength,\n\t\t\toriginal: aTerminal.bounds,\n\t\t\texpanded: expandedA,\n\t\t\tedges: edgesA,\n\t\t\tgeometry: aTerminal.geometry,\n\t\t},\n\t\tB: {\n\t\t\tisPoint: bTerminal.isPoint,\n\t\t\ttarget: bTerminal.target,\n\t\t\tisExact: bTerminal.isExact,\n\t\t\tarrowheadOffset: bTerminal.arrowheadOffset,\n\t\t\tminEndSegmentLength: bTerminal.minEndSegmentLength,\n\t\t\toriginal: bTerminal.bounds,\n\t\t\texpanded: expandedB,\n\t\t\tedges: edgesB,\n\t\t\tgeometry: bTerminal.geometry,\n\t\t},\n\t\tcommon,\n\t\tgapX,\n\t\tgapY,\n\t\tmidX: mx,\n\t\tmidY: my,\n\t}\n\n\t// We wrap the info in a working info object that lets us mutate and reset it as needed.\n\tconst workingInfo = new ElbowArrowWorkingInfo(info)\n\n\t// Figure out the final sides to use for each terminal.\n\tconst aSide = getSideToUse(aTerminal, bTerminal, info.A.edges)\n\tconst bSide = getSideToUse(bTerminal, aTerminal, info.B.edges)\n\n\t// try to find a route with the specification we have:\n\tlet route\n\tif (aSide && bSide) {\n\t\troute = routeArrowWithManualEdgePicking(workingInfo, aSide, bSide)\n\t} else if (aSide && !bSide) {\n\t\troute = routeArrowWithPartialEdgePicking(workingInfo, aSide)\n\t}\n\tif (!route) {\n\t\troute = routeArrowWithAutoEdgePicking(workingInfo, aSide || bSide ? 'fallback' : 'auto')\n\t}\n\n\tif (route) {\n\t\t// If we found a route, we need to fix it up. The route will only go to the bounding box of\n\t\t// the shape, so we need to cast the final segments into the actual geometry of the shape.\n\t\tcastPathSegmentIntoGeometry('first', info.A, info.B, route)\n\t\tcastPathSegmentIntoGeometry('last', info.B, info.A, route)\n\t\t// If we have tiny L-shaped arrows, the arrowheads look super janky. We fix those up by just\n\t\t// drawing a straight line instead.\n\t\tfixTinyEndNubs(route, aTerminal, bTerminal)\n\n\t\t// If we swapped the order way back of the start of things, we need to reverse the route so\n\t\t// it flows start -> end instead of A -> B.\n\t\tif (swapOrder) route.points.reverse()\n\t}\n\n\treturn {\n\t\t...info,\n\t\troute,\n\t\tmidXRange: mxRange\n\t\t\t? swapOrder\n\t\t\t\t? { lo: mxRange.b, hi: mxRange.a }\n\t\t\t\t: { lo: mxRange.a, hi: mxRange.b }\n\t\t\t: null,\n\t\tmidYRange: myRange\n\t\t\t? swapOrder\n\t\t\t\t? { lo: myRange.b, hi: myRange.a }\n\t\t\t\t: { lo: myRange.a, hi: myRange.b }\n\t\t\t: null,\n\t}\n}\n\n/**\n * Take the route from `getElbowArrowInfo` (which represents the visible body of the arrow) and\n * convert it into a path we can use to show that paths to the handles, which may extend further\n * into the target shape geometries.\n * @returns\n */\nexport function getRouteHandlePath(info: ElbowArrowInfo, route: ElbowArrowRoute): ElbowArrowRoute {\n\tconst startTarget = info.swapOrder ? info.B.target : info.A.target\n\tconst endTarget = info.swapOrder ? info.A.target : info.B.target\n\n\tconst firstSegmentLength = Vec.ManhattanDist(route.points[0], route.points[1])\n\tconst lastSegmentLength = Vec.ManhattanDist(\n\t\troute.points[route.points.length - 2],\n\t\troute.points[route.points.length - 1]\n\t)\n\n\tconst newFirstSegmentLength = Vec.ManhattanDist(startTarget, route.points[1])\n\tconst newLastSegmentLength = Vec.ManhattanDist(route.points[route.points.length - 2], endTarget)\n\n\tconst firstSegmentLengthChange = firstSegmentLength - newFirstSegmentLength\n\tconst lastSegmentLengthChange = lastSegmentLength - newLastSegmentLength\n\n\tconst newPoints = [startTarget, ...route.points, endTarget]\n\n\treturn {\n\t\tname: route.name,\n\t\tdistance: route.distance + firstSegmentLengthChange + lastSegmentLengthChange,\n\t\tpoints: newPoints.filter((p) => !route.skipPointsWhenDrawing.has(p)),\n\t\taEdgePicking: route.aEdgePicking,\n\t\tbEdgePicking: route.bEdgePicking,\n\t\tskipPointsWhenDrawing: route.skipPointsWhenDrawing,\n\t\tmidpointHandle: route.midpointHandle,\n\t}\n}\n\n/**\n * Take a normalizes anchor and return the side we think it's closest to.\n */\nexport function getEdgeFromNormalizedAnchor(normalizedAnchor: VecLike) {\n\tif (approximately(normalizedAnchor.x, 0.5) && approximately(normalizedAnchor.y, 0.5)) {\n\t\treturn null\n\t}\n\n\tif (\n\t\tMath.abs(normalizedAnchor.x - 0.5) >\n\t\t// slightly bias towards x arrows to prevent flickering when the anchor is right on the line\n\t\t// between the two directions\n\t\tMath.abs(normalizedAnchor.y - 0.5) - 0.0001\n\t) {\n\t\treturn normalizedAnchor.x < 0.5 ? 'left' : 'right'\n\t}\n\n\treturn normalizedAnchor.y < 0.5 ? 'top' : 'bottom'\n}\n\nfunction getElbowArrowTerminalInfo(\n\teditor: Editor,\n\tarrow: TLArrowShape,\n\tbinding: TLArrowBinding | undefined,\n\tpoint: VecModel,\n\tarrowStrokeWidth?: number\n): ElbowArrowTerminal {\n\tconst theme = editor.getCurrentTheme()\n\tconst arrowSW = arrowStrokeWidth ?? theme.strokeWidth * STROKE_SIZES[arrow.props.size]\n\tconst arrowStrokeSize = (arrowSW * arrow.props.scale) / 2\n\tconst minEndSegmentLength = arrowStrokeSize * 3\n\n\tif (binding) {\n\t\tconst target = editor.getShape(binding.toId)\n\t\tconst geometry = getBindingGeometryInArrowSpace(editor, arrow, binding.toId, binding.props)\n\t\tif (geometry && target) {\n\t\t\tlet arrowheadOffset = 0\n\t\t\tconst arrowheadProp = binding.props.terminal === 'start' ? 'arrowheadStart' : 'arrowheadEnd'\n\t\t\tif (arrow.props[arrowheadProp] !== 'none') {\n\t\t\t\tconst targetScale = 'scale' in target.props ? target.props.scale : 1\n\t\t\t\tconst targetStrokeSize =\n\t\t\t\t\t'size' in target.props\n\t\t\t\t\t\t? (theme.strokeWidth * (STROKE_SIZES[target.props.size] ?? 0) * targetScale) / 2\n\t\t\t\t\t\t: 0\n\n\t\t\t\tarrowheadOffset =\n\t\t\t\t\tarrowStrokeSize + targetStrokeSize + BOUND_ARROW_OFFSET * arrow.props.scale\n\t\t\t}\n\n\t\t\tlet side: ElbowArrowSideWithAxis | null = null\n\t\t\tconst targetPoint = geometry.target\n\t\t\tif (binding.props.isPrecise) {\n\t\t\t\tside = getEdgeFromNormalizedAnchor(\n\t\t\t\t\tVec.RotWith(\n\t\t\t\t\t\tbinding.props.normalizedAnchor,\n\t\t\t\t\t\t{ x: 0.5, y: 0.5 },\n\t\t\t\t\t\tgeometry.shapeToArrowTransform.rotation()\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttargetShapeId: binding.toId,\n\t\t\t\tisPoint: false,\n\t\t\t\tisExact: binding.props.isExact,\n\t\t\t\tbounds: geometry.bounds,\n\t\t\t\tgeometry: geometry.geometry,\n\t\t\t\ttarget: targetPoint,\n\t\t\t\tarrowheadOffset,\n\t\t\t\tminEndSegmentLength,\n\t\t\t\tside,\n\t\t\t\tsnap: binding.props.snap,\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\ttargetShapeId: null,\n\t\tbounds: Box.FromCenter(point, { x: 0, y: 0 }),\n\t\tgeometry: null,\n\t\tisExact: false,\n\t\tisPoint: true,\n\t\ttarget: Vec.From(point),\n\t\tarrowheadOffset: 0,\n\t\tminEndSegmentLength,\n\t\tside: null,\n\t\tsnap: 'none',\n\t}\n}\n\nfunction getBindingGeometryInArrowSpace(\n\teditor: Editor,\n\tarrow: TLArrowShape,\n\ttargetId: TLShapeId,\n\tbindingProps: TLArrowBindingProps\n) {\n\tconst hasArrowhead =\n\t\tbindingProps.terminal === 'start'\n\t\t\t? arrow.props.arrowheadStart !== 'none'\n\t\t\t: arrow.props.arrowheadEnd !== 'none'\n\n\tconst targetGeometryInTargetSpace = editor.getShapeGeometry(\n\t\ttargetId,\n\t\thasArrowhead ? undefined : { context: '@tldraw/arrow-without-arrowhead' }\n\t)\n\n\tif (!targetGeometryInTargetSpace) {\n\t\treturn null\n\t}\n\n\tconst arrowTransform = editor.getShapePageTransform(arrow.id)\n\tconst shapeTransform = editor.getShapePageTransform(targetId)\n\tconst shapeToArrowTransform = arrowTransform.clone().invert().multiply(shapeTransform)\n\n\tconst targetGeometryInArrowSpace = targetGeometryInTargetSpace.transform(shapeToArrowTransform)\n\n\tconst center = { x: 0.5, y: 0.5 }\n\tconst normalizedAnchor = bindingProps.isPrecise ? bindingProps.normalizedAnchor : center\n\n\tconst targetInShapeSpace = {\n\t\tx: lerp(\n\t\t\ttargetGeometryInTargetSpace.bounds.minX,\n\t\t\ttargetGeometryInTargetSpace.bounds.maxX,\n\t\t\tnormalizedAnchor.x\n\t\t),\n\t\ty: lerp(\n\t\t\ttargetGeometryInTargetSpace.bounds.minY,\n\t\t\ttargetGeometryInTargetSpace.bounds.maxY,\n\t\t\tnormalizedAnchor.y\n\t\t),\n\t}\n\tconst centerInShapeSpace = {\n\t\tx: lerp(\n\t\t\ttargetGeometryInTargetSpace.bounds.minX,\n\t\t\ttargetGeometryInTargetSpace.bounds.maxX,\n\t\t\tcenter.x\n\t\t),\n\t\ty: lerp(\n\t\t\ttargetGeometryInTargetSpace.bounds.minY,\n\t\t\ttargetGeometryInTargetSpace.bounds.maxY,\n\t\t\tcenter.y\n\t\t),\n\t}\n\n\tconst targetInArrowSpace = Mat.applyToPoint(shapeToArrowTransform, targetInShapeSpace)\n\tconst centerInArrowSpace = Mat.applyToPoint(shapeToArrowTransform, centerInShapeSpace)\n\n\treturn {\n\t\tbounds: targetGeometryInArrowSpace.bounds,\n\t\tgeometry: targetGeometryInArrowSpace,\n\t\ttarget: targetInArrowSpace,\n\t\tcenter: centerInArrowSpace,\n\t\tshapeToArrowTransform,\n\t}\n}\n\nconst sideProps = {\n\ttop: {\n\t\texpand: -1,\n\t\tmain: 'minY',\n\t\topposite: 'maxY',\n\t\tcrossMid: 'midX',\n\t\tcrossMin: 'minX',\n\t\tcrossMax: 'maxX',\n\t\tbRangeExpand: 'max',\n\t\tcrossAxis: 'x',\n\t},\n\tbottom: {\n\t\texpand: 1,\n\t\tmain: 'maxY',\n\t\topposite: 'minY',\n\t\tcrossMid: 'midX',\n\t\tcrossMin: 'minX',\n\t\tcrossMax: 'maxX',\n\t\tbRangeExpand: 'min',\n\t\tcrossAxis: 'x',\n\t},\n\tleft: {\n\t\texpand: -1,\n\t\tmain: 'minX',\n\t\topposite: 'maxX',\n\t\tcrossMid: 'midY',\n\t\tcrossMin: 'minY',\n\t\tcrossMax: 'maxY',\n\t\tbRangeExpand: 'max',\n\t\tcrossAxis: 'y',\n\t},\n\tright: {\n\t\texpand: 1,\n\t\tmain: 'maxX',\n\t\topposite: 'minX',\n\t\tcrossMid: 'midY',\n\t\tcrossMin: 'minY',\n\t\tcrossMax: 'maxY',\n\t\tbRangeExpand: 'min',\n\t\tcrossAxis: 'y',\n\t},\n} as const\n\nexport function getUsableEdge(\n\ta: ElbowArrowTerminal,\n\tb: ElbowArrowTerminal,\n\tside: 'top' | 'right' | 'bottom' | 'left',\n\toptions: ElbowArrowOptions\n): ElbowArrowEdge | null {\n\tconst props = sideProps[side]\n\n\t// if a shape is bound to itself, by default we'd end up routing the arrow _within_ the shape -\n\t// as if it were a point-to-point arrow. if one of the bindings is specifically to the edge\n\t// though, we route it externally instead.\n\tconst isSelfBoundAndShouldRouteExternal =\n\t\ta.targetShapeId === b.targetShapeId &&\n\t\ta.targetShapeId !== null &&\n\t\t(a.snap === 'edge' || a.snap === 'edge-point') &&\n\t\t(b.snap === 'edge' || b.snap === 'edge-point')\n\n\tconst aValue = a.bounds[props.main]\n\tconst aExpanded = a.isPoint ? null : aValue + props.expand * options.expandElbowLegLength\n\n\tconst originalACrossRange = createRange(a.bounds[props.crossMin], a.bounds[props.crossMax])\n\tlet aCrossRange = originalACrossRange\n\n\t// this edge is too small to be useful:\n\tif (!aCrossRange) {\n\t\treturn null\n\t}\n\n\tassert(originalACrossRange)\n\tconst bRange = createRange(b.bounds[props.main], b.bounds[props.opposite])\n\tif (!b.isPoint) {\n\t\tbRange[props.bRangeExpand] -= options.minElbowLegLength * 2 * props.expand\n\t}\n\n\tconst bCrossRange = expandRange(\n\t\tcreateRange(b.bounds[props.crossMin], b.bounds[props.crossMax]),\n\t\toptions.expandElbowLegLength\n\t)\n\tassert(bRange && bCrossRange)\n\n\tlet isPartial = false\n\tif (\n\t\tisWithinRange(aValue, bRange) &&\n\t\t!a.isPoint &&\n\t\t!b.isPoint &&\n\t\t!isSelfBoundAndShouldRouteExternal\n\t) {\n\t\tconst subtracted = subtractRange(aCrossRange, bCrossRange)\n\t\tswitch (subtracted.length) {\n\t\t\tcase 0:\n\t\t\t\treturn null\n\t\t\tcase 1:\n\t\t\t\tisPartial = subtracted[0] !== aCrossRange\n\t\t\t\taCrossRange = subtracted[0]\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\tisPartial = true\n\t\t\t\taCrossRange =\n\t\t\t\t\trangeSize(subtracted[0]) > rangeSize(subtracted[1]) ? subtracted[0] : subtracted[1]\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\texhaustiveSwitchError(subtracted)\n\t\t}\n\t}\n\n\tif (!isWithinRange(a.target[props.crossAxis], aCrossRange)) {\n\t\treturn null\n\t}\n\tconst crossTarget = a.target[props.crossAxis]\n\n\treturn {\n\t\tvalue: aValue,\n\t\texpanded: aExpanded,\n\t\tcross: aCrossRange,\n\t\tcrossTarget,\n\t\tisPartial,\n\t}\n}\n\nfunction hasUsableEdge(edges: ElbowArrowBoxEdges, side: ElbowArrowSideWithAxis | null) {\n\tif (side === null) {\n\t\treturn !!(edges.bottom || edges.left || edges.right || edges.top)\n\t}\n\n\tif (side === 'x') {\n\t\treturn !!edges.left || !!edges.right\n\t}\n\n\tif (side === 'y') {\n\t\treturn !!edges.top || !!edges.bottom\n\t}\n\n\treturn !!edges[side]\n}\n\nfunction getSideToUse(\n\tbinding: ElbowArrowTerminal,\n\tother: ElbowArrowTerminal,\n\tedges: ElbowArrowBoxEdges | null\n): ElbowArrowSide | null {\n\tswitch (binding.side) {\n\t\tcase null:\n\t\t\treturn null\n\t\tcase 'x':\n\t\t\tif (binding.bounds.center.x > other.bounds.center.x && edges?.left) {\n\t\t\t\treturn 'left'\n\t\t\t} else if (edges?.right) {\n\t\t\t\treturn 'right'\n\t\t\t}\n\t\t\treturn null\n\t\tcase 'y':\n\t\t\tif (binding.bounds.center.y > other.bounds.center.y && edges?.top) {\n\t\t\t\treturn 'top'\n\t\t\t} else if (edges?.bottom) {\n\t\t\t\treturn 'bottom'\n\t\t\t}\n\t\t\treturn null\n\t\tdefault:\n\t\t\treturn binding.side\n\t}\n}\n\nfunction convertTerminalToPoint(terminal: ElbowArrowTerminal): ElbowArrowTerminal {\n\tif (terminal.isPoint) return terminal\n\n\tlet side: ElbowArrowSideWithAxis | null = null\n\tlet arrowheadOffset = 0\n\tif (terminal.snap === 'edge' || terminal.snap === 'edge-point') {\n\t\tarrowheadOffset = terminal.arrowheadOffset\n\t\tif (terminal.side === 'x' || terminal.side === 'left' || terminal.side === 'right') {\n\t\t\tside = 'x'\n\t\t}\n\t\tif (terminal.side === 'y' || terminal.side === 'top' || terminal.side === 'bottom') {\n\t\t\tside = 'y'\n\t\t}\n\t}\n\n\treturn {\n\t\ttargetShapeId: terminal.targetShapeId,\n\t\tside,\n\t\tbounds: new Box(terminal.target.x, terminal.target.y, 0, 0),\n\t\tgeometry: terminal.geometry,\n\t\ttarget: terminal.target,\n\t\tarrowheadOffset,\n\t\tminEndSegmentLength: terminal.minEndSegmentLength,\n\t\tisExact: terminal.isExact,\n\t\tisPoint: true,\n\t\tsnap: terminal.snap,\n\t}\n}\n\n/**\n * Make sure the first path segments goes fully into the target, and doesn't just point to its\n * bounding box. This modifies the route in-place.\n */\nfunction castPathSegmentIntoGeometry(\n\tsegment: 'first' | 'last',\n\ttarget: ElbowArrowTargetBox,\n\tother: ElbowArrowTargetBox,\n\troute: ElbowArrowRoute\n) {\n\tif (!target.geometry) return\n\n\tconst point1 = segment === 'first' ? route.points[0] : route.points[route.points.length - 1]\n\tconst point2 = segment === 'first' ? route.points[1] : route.points[route.points.length - 2]\n\n\tconst pointToFindClosestIntersectionTo = target.geometry.isClosed ? point2 : target.target\n\n\tconst initialDistance = Vec.ManhattanDist(point1, pointToFindClosestIntersectionTo)\n\n\tlet nearestIntersectionToPoint2: VecLike | null = null\n\tlet nearestDistanceToPoint2 = Infinity\n\n\tif (target.isExact) {\n\t\tnearestIntersectionToPoint2 = target.target\n\t} else if (target.geometry) {\n\t\tconst intersections = target.geometry.intersectLineSegment(point2, target.target, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\t\tif (\n\t\t\ttarget.geometry.hitTestPoint(\n\t\t\t\ttarget.target,\n\t\t\t\tMath.max(1, target.arrowheadOffset),\n\t\t\t\ttrue,\n\t\t\t\tGeometry2dFilters.EXCLUDE_NON_STANDARD\n\t\t\t)\n\t\t) {\n\t\t\tintersections.push(target.target)\n\t\t}\n\t\tfor (const intersection of intersections) {\n\t\t\tconst point2Distance = Vec.ManhattanDist(pointToFindClosestIntersectionTo, intersection)\n\t\t\tif (point2Distance < nearestDistanceToPoint2) {\n\t\t\t\tnearestDistanceToPoint2 = point2Distance\n\t\t\t\tnearestIntersectionToPoint2 = intersection\n\t\t\t}\n\t\t}\n\t}\n\n\tif (nearestIntersectionToPoint2) {\n\t\tlet offset = target.arrowheadOffset\n\n\t\tconst currentFinalSegmentLength = Vec.ManhattanDist(point2, nearestIntersectionToPoint2)\n\t\tconst minLength = target.arrowheadOffset * 2\n\t\tif (currentFinalSegmentLength < minLength) {\n\t\t\tconst targetLength = minLength - target.arrowheadOffset\n\t\t\toffset = currentFinalSegmentLength - targetLength\n\t\t}\n\t\tif (offset < target.minEndSegmentLength) {\n\t\t\tif (target.geometry.bounds.containsPoint(other.target)) {\n\t\t\t\toffset = Math.max(0, offset)\n\t\t\t} else {\n\t\t\t\toffset = -target.arrowheadOffset\n\t\t\t}\n\t\t}\n\n\t\tlet nudgedPoint = nearestIntersectionToPoint2\n\t\tlet shouldAddExtraPointForNudge = false\n\t\tif (!target.isExact && offset !== 0) {\n\t\t\tconst nudged = Vec.Nudge(nearestIntersectionToPoint2, point2, offset)\n\t\t\tnudgedPoint = nudged\n\t\t\tif (\n\t\t\t\toffset < 0 &&\n\t\t\t\t!target.geometry.hitTestPoint(nudged, 0, true, Geometry2dFilters.EXCLUDE_NON_STANDARD)\n\t\t\t) {\n\t\t\t\t// point has been nudged _out_ of the shape so lets not actually apply the nudge\n\t\t\t\tnudgedPoint = nearestIntersectionToPoint2\n\t\t\t} else {\n\t\t\t\tif (offset < 0) {\n\t\t\t\t\tshouldAddExtraPointForNudge = true\n\t\t\t\t}\n\t\t\t\tnudgedPoint = nudged\n\t\t\t}\n\t\t}\n\n\t\tconst newDistance = Vec.ManhattanDist(point2, nudgedPoint)\n\t\troute.distance += newDistance - initialDistance\n\t\tpoint1.x = nudgedPoint.x\n\t\tpoint1.y = nudgedPoint.y\n\n\t\tif (shouldAddExtraPointForNudge) {\n\t\t\tconst midPoint = Vec.Lrp(point2, point1, 0.5)\n\t\t\troute.skipPointsWhenDrawing.add(midPoint)\n\t\t\troute.points.splice(segment === 'first' ? 1 : route.points.length - 1, 0, midPoint)\n\t\t}\n\t}\n}\n\nfunction fixTinyEndNubs(\n\troute: ElbowArrowRoute,\n\taTerminal: ElbowArrowTerminal,\n\tbTerminal: ElbowArrowTerminal\n) {\n\tif (!route) return\n\n\tif (route.points.length >= 3) {\n\t\tconst a = route.points[0]\n\t\tconst b = route.points[1]\n\t\tconst firstSegmentLength = Vec.ManhattanDist(a, b)\n\t\tif (firstSegmentLength < aTerminal.minEndSegmentLength) {\n\t\t\troute.points.splice(1, 1)\n\t\t\tif (route.points.length >= 3) {\n\t\t\t\tconst matchAxis = approximately(a.x, b.x) ? 'y' : 'x'\n\t\t\t\troute.points[1][matchAxis] = a[matchAxis]\n\t\t\t}\n\t\t}\n\t}\n\n\tif (route.points.length >= 3) {\n\t\tconst a = route.points[route.points.length - 1]\n\t\tconst b = route.points[route.points.length - 2]\n\t\tconst lastSegmentLength = Vec.ManhattanDist(a, b)\n\t\tif (lastSegmentLength < bTerminal.minEndSegmentLength) {\n\t\t\troute.points.splice(route.points.length - 2, 1)\n\t\t\tif (route.points.length >= 3) {\n\t\t\t\tconst matchAxis = approximately(a.x, b.x) ? 'y' : 'x'\n\t\t\t\troute.points[route.points.length - 2][matchAxis] = a[matchAxis]\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction adjustTerminalForUnclosedPathIfNeeded(\n\tterminal: ElbowArrowTerminal,\n\totherTerminal: ElbowArrowTerminal,\n\toptions: ElbowArrowOptions\n): ElbowArrowTerminal {\n\tif (!terminal.geometry || terminal.geometry.isClosed) return terminal\n\tconst normalizedPointAlongPath = terminal.geometry.uninterpolateAlongEdge(\n\t\tterminal.target,\n\t\tGeometry2dFilters.EXCLUDE_NON_STANDARD\n\t)\n\n\tconst prev = terminal.geometry.interpolateAlongEdge(\n\t\tnormalizedPointAlongPath - 0.01 / terminal.geometry.length\n\t)\n\tconst next = terminal.geometry.interpolateAlongEdge(\n\t\tnormalizedPointAlongPath + 0.01 / terminal.geometry.length\n\t)\n\n\tconst normal = next.sub(prev).per().uni()\n\tconst axis = Math.abs(normal.x) > Math.abs(normal.y) ? ElbowArrowAxes.x : ElbowArrowAxes.y\n\n\tif (terminal.geometry.bounds.containsPoint(otherTerminal.target, options.expandElbowLegLength)) {\n\t\tterminal.side = axis.self\n\t\treturn convertTerminalToPoint(terminal)\n\t}\n\n\tconst min = axis.v(\n\t\tterminal.target[axis.self] - terminal.bounds[axis.size] * 2,\n\t\tterminal.target[axis.cross]\n\t)\n\tconst max = axis.v(\n\t\tterminal.target[axis.self] + terminal.bounds[axis.size] * 2,\n\t\tterminal.target[axis.cross]\n\t)\n\n\tlet furthestIntersectionTowardsMin: VecLike | null = null\n\tlet furthestIntersectionTowardsMinDistance = 0\n\tlet furthestIntersectionTowardsMax: VecLike | null = null\n\tlet furthestIntersectionTowardsMaxDistance = 0\n\tlet side: ElbowArrowSideWithAxis = axis.self\n\n\tfor (const intersection of terminal.geometry.intersectLineSegment(\n\t\tmin,\n\t\tmax,\n\t\tGeometry2dFilters.EXCLUDE_NON_STANDARD\n\t)) {\n\t\tif (Math.abs(intersection[axis.self] - terminal.target[axis.self]) < 1) {\n\t\t\tcontinue\n\t\t}\n\t\tif (intersection[axis.self] < terminal.target[axis.self]) {\n\t\t\tif (\n\t\t\t\tVec.ManhattanDist(intersection, terminal.target) > furthestIntersectionTowardsMinDistance\n\t\t\t) {\n\t\t\t\tfurthestIntersectionTowardsMinDistance = Vec.ManhattanDist(intersection, terminal.target)\n\t\t\t\tfurthestIntersectionTowardsMin = intersection\n\t\t\t}\n\t\t} else {\n\t\t\tif (\n\t\t\t\tVec.ManhattanDist(intersection, terminal.target) > furthestIntersectionTowardsMaxDistance\n\t\t\t) {\n\t\t\t\tfurthestIntersectionTowardsMaxDistance = Vec.ManhattanDist(intersection, terminal.target)\n\t\t\t\tfurthestIntersectionTowardsMax = intersection\n\t\t\t}\n\t\t}\n\t}\n\n\tif (furthestIntersectionTowardsMin && furthestIntersectionTowardsMax) {\n\t\tif (furthestIntersectionTowardsMinDistance > furthestIntersectionTowardsMaxDistance) {\n\t\t\tside = axis.hiEdge\n\t\t} else {\n\t\t\tside = axis.loEdge\n\t\t}\n\t} else if (furthestIntersectionTowardsMin && !furthestIntersectionTowardsMax) {\n\t\tside = axis.hiEdge\n\t} else if (!furthestIntersectionTowardsMin && furthestIntersectionTowardsMax) {\n\t\tside = axis.loEdge\n\t}\n\n\tterminal.side = side\n\treturn terminal\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n\tapproximately,\n\tassert,\n\tBox,\n\tEditor,\n\texhaustiveSwitchError,\n\tGeometry2dFilters,\n\tlerp,\n\tMat,\n\tTLArrowBinding,\n\tTLArrowBindingProps,\n\tTLArrowShape,\n\tTLShapeId,\n\tVec,\n\tVecLike,\n\tVecModel,\n} from '@tldraw/editor'\nimport { STROKE_SIZES } from '../../shared/default-shape-constants'\nimport { ArrowShapeUtil } from '../ArrowShapeUtil'\nimport { BOUND_ARROW_OFFSET, TLArrowBindings } from '../shared'\nimport {\n\tElbowArrowAxes,\n\tElbowArrowBox,\n\tElbowArrowBoxEdges,\n\tElbowArrowEdge,\n\tElbowArrowInfo,\n\tElbowArrowInfoWithoutRoute,\n\tElbowArrowOptions,\n\tElbowArrowRoute,\n\tElbowArrowSide,\n\tElbowArrowSideWithAxis,\n\tElbowArrowTargetBox,\n\tElbowArrowTerminal,\n} from './definitions'\nimport { createRange, expandRange, isWithinRange, rangeSize, subtractRange } from './range'\nimport { ElbowArrowWorkingInfo } from './routes/ElbowArrowWorkingInfo'\nimport {\n\trouteArrowWithAutoEdgePicking,\n\trouteArrowWithManualEdgePicking,\n\trouteArrowWithPartialEdgePicking,\n} from './routes/routeArrowWithAutoEdgePicking'\n\nexport function getElbowArrowInfo(\n\teditor: Editor,\n\tarrow: TLArrowShape,\n\tbindings: TLArrowBindings,\n\tarrowStrokeWidth?: number\n): ElbowArrowInfo {\n\tconst shapeOptions = editor.getShapeUtil<ArrowShapeUtil>(arrow.type).options\n\tconst options: ElbowArrowOptions = {\n\t\telbowMidpoint: arrow.props.elbowMidPoint,\n\t\texpandElbowLegLength: shapeOptions.expandElbowLegLength[arrow.props.size] * arrow.props.scale,\n\t\tminElbowLegLength: shapeOptions.minElbowLegLength[arrow.props.size] * arrow.props.scale,\n\t}\n\n\t// Before we can do anything else, we need to find the start and end terminals of the arrow.\n\t// These contain the binding info, geometry, bounds, etc.\n\tlet startTerminal = getElbowArrowTerminalInfo(\n\t\teditor,\n\t\tarrow,\n\t\tbindings.start,\n\t\tarrow.props.start,\n\t\tarrowStrokeWidth\n\t)\n\tlet endTerminal = getElbowArrowTerminalInfo(\n\t\teditor,\n\t\tarrow,\n\t\tbindings.end,\n\t\tarrow.props.end,\n\t\tarrowStrokeWidth\n\t)\n\t// unclosed paths are weird - we handle them outside of the initial terminal info.\n\tstartTerminal = adjustTerminalForUnclosedPathIfNeeded(startTerminal, endTerminal, options)\n\tendTerminal = adjustTerminalForUnclosedPathIfNeeded(endTerminal, startTerminal, options)\n\n\t// Ther terminal might include a \"side\" if the user has explicitly indicated what side the arrow\n\t// should come from. There are two terminals, and two cases for each terminal (explicit side or\n\t// not), for a total for 4 cases to handle. In order to keep things a bit simpler though, we\n\t// only handle 3 cases: if start no side and end has a side, we flip them around. From here on\n\t// out, we use A and B to refer to the terminals as they may be swapped.\n\tconst swapOrder = !!(!startTerminal.side && endTerminal.side)\n\n\tlet { aTerminal, bTerminal } = swapOrder\n\t\t? { aTerminal: endTerminal, bTerminal: startTerminal }\n\t\t: { aTerminal: startTerminal, bTerminal: endTerminal }\n\n\t// We model each edge that an arrow might enter/exit from separately. If an edge is blocked,\n\t// `getUsableEdge` might return null.\n\tlet edgesA = {\n\t\ttop: getUsableEdge(aTerminal, bTerminal, 'top', options),\n\t\tright: getUsableEdge(aTerminal, bTerminal, 'right', options),\n\t\tbottom: getUsableEdge(aTerminal, bTerminal, 'bottom', options),\n\t\tleft: getUsableEdge(aTerminal, bTerminal, 'left', options),\n\t}\n\n\tlet edgesB = {\n\t\ttop: getUsableEdge(bTerminal, aTerminal, 'top', options),\n\t\tright: getUsableEdge(bTerminal, aTerminal, 'right', options),\n\t\tbottom: getUsableEdge(bTerminal, aTerminal, 'bottom', options),\n\t\tleft: getUsableEdge(bTerminal, aTerminal, 'left', options),\n\t}\n\n\t// We we don't have a usable edge because it's blocked, we can convert some of the terminals to\n\t// points. Point terminals have less strict edge routing rules, but don't look as good\n\t// generally. For example, the arrow might go through the shape instead of around.\n\tconst aIsUsable = hasUsableEdge(edgesA, aTerminal.side)\n\tconst bIsUsable = hasUsableEdge(edgesB, bTerminal.side)\n\tlet needsNewEdges = false\n\tif (!aIsUsable || !bIsUsable) {\n\t\tneedsNewEdges = true\n\t\tif (!aIsUsable) {\n\t\t\tbTerminal = convertTerminalToPoint(bTerminal)\n\t\t}\n\n\t\tif (!bIsUsable) {\n\t\t\taTerminal = convertTerminalToPoint(aTerminal)\n\t\t}\n\n\t\tif (bTerminal.bounds.containsPoint(aTerminal.target, options.expandElbowLegLength)) {\n\t\t\tbTerminal = convertTerminalToPoint(bTerminal)\n\t\t}\n\n\t\tif (aTerminal.bounds.containsPoint(bTerminal.target, options.expandElbowLegLength)) {\n\t\t\taTerminal = convertTerminalToPoint(aTerminal)\n\t\t}\n\t}\n\n\tif (needsNewEdges) {\n\t\tedgesA = {\n\t\t\ttop: getUsableEdge(aTerminal, bTerminal, 'top', options),\n\t\t\tright: getUsableEdge(aTerminal, bTerminal, 'right', options),\n\t\t\tbottom: getUsableEdge(aTerminal, bTerminal, 'bottom', options),\n\t\t\tleft: getUsableEdge(aTerminal, bTerminal, 'left', options),\n\t\t}\n\n\t\tedgesB = {\n\t\t\ttop: getUsableEdge(bTerminal, aTerminal, 'top', options),\n\t\t\tright: getUsableEdge(bTerminal, aTerminal, 'right', options),\n\t\t\tbottom: getUsableEdge(bTerminal, aTerminal, 'bottom', options),\n\t\t\tleft: getUsableEdge(bTerminal, aTerminal, 'left', options),\n\t\t}\n\t}\n\n\t// We expand the bounds of the terminals so we can route arrows around them without the arrows\n\t// being too close to the shapes. Always a separate Box from `bounds`: ElbowArrowWorkingInfo\n\t// transforms `original` and `expanded` in place, so sharing one object would transform a point\n\t// terminal twice (a no-op for flips, a 180\u00B0 turn for rotations) and corrupt the route.\n\tconst expandedA = aTerminal.isPoint\n\t\t? aTerminal.bounds.clone()\n\t\t: aTerminal.bounds.clone().expandBy(options.expandElbowLegLength)\n\tconst expandedB = bTerminal.isPoint\n\t\t? bTerminal.bounds.clone()\n\t\t: bTerminal.bounds.clone().expandBy(options.expandElbowLegLength)\n\n\tconst common: ElbowArrowBox = {\n\t\toriginal: Box.Common([aTerminal.bounds, bTerminal.bounds]),\n\t\texpanded: Box.Common([expandedA, expandedB]),\n\t}\n\n\t// Calculate the gaps between the two terminals. If gap is positive, B is to the right of A. If\n\t// it's negative, the opposite is true. If it's 0, there's no gap between the shapes in that\n\t// dimension.\n\tlet gapX = bTerminal.bounds.minX - aTerminal.bounds.maxX\n\tif (gapX < 0) {\n\t\tgapX = aTerminal.bounds.minX - bTerminal.bounds.maxX\n\t\tif (gapX < 0) {\n\t\t\tgapX = 0\n\t\t}\n\t\tgapX = -gapX\n\t}\n\tlet gapY = bTerminal.bounds.minY - aTerminal.bounds.maxY\n\tif (gapY < 0) {\n\t\tgapY = aTerminal.bounds.minY - bTerminal.bounds.maxY\n\t\tif (gapY < 0) {\n\t\t\tgapY = 0\n\t\t}\n\t\tgapY = -gapY\n\t}\n\n\t// The midpoint of the gap is a useful point to route arrows through, but the user can also drag\n\t// it to choose a new midpoint. First, we calculate some constraints we'll need to keep in mind\n\t// when figuring out the midpoint...\n\tconst aMinLength = aTerminal.minEndSegmentLength * 3\n\tconst bMinLength = bTerminal.minEndSegmentLength * 3\n\tconst minLegDistanceNeeded =\n\t\t(aTerminal.isPoint ? aMinLength : options.minElbowLegLength) +\n\t\t(bTerminal.isPoint ? bMinLength : options.minElbowLegLength)\n\n\t// ...then, the possible range of the midpoint. This is also used when dragging the midpoint.\n\tlet mxRange: null | { a: number; b: number } = null\n\tif (gapX > minLegDistanceNeeded) {\n\t\tmxRange = {\n\t\t\ta: aTerminal.isPoint ? aTerminal.bounds.maxX + aMinLength : expandedA.maxX,\n\t\t\tb: bTerminal.isPoint ? bTerminal.bounds.minX - bMinLength : expandedB.minX,\n\t\t}\n\t} else if (gapX < -minLegDistanceNeeded) {\n\t\tmxRange = {\n\t\t\ta: aTerminal.isPoint ? aTerminal.bounds.minX - aMinLength : expandedA.minX,\n\t\t\tb: bTerminal.isPoint ? bTerminal.bounds.maxX + bMinLength : expandedB.maxX,\n\t\t}\n\t}\n\n\tlet myRange: null | { a: number; b: number } = null\n\tif (gapY > minLegDistanceNeeded) {\n\t\tmyRange = {\n\t\t\ta: aTerminal.isPoint ? aTerminal.bounds.maxY + aMinLength : expandedA.maxY,\n\t\t\tb: bTerminal.isPoint ? bTerminal.bounds.minY - bMinLength : expandedB.minY,\n\t\t}\n\t} else if (gapY < -minLegDistanceNeeded) {\n\t\tmyRange = {\n\t\t\ta: aTerminal.isPoint ? aTerminal.bounds.minY - aMinLength : expandedA.minY,\n\t\t\tb: bTerminal.isPoint ? bTerminal.bounds.maxY + bMinLength : expandedB.maxY,\n\t\t}\n\t}\n\n\t// and finally we take the range and the midpoint prop and calculate the actual position of the\n\t// midpoint. Note that the midpoint and midpoint range can be null if the gap is too small for a\n\t// midpoint line.\n\tconst midpoint = swapOrder ? 1 - options.elbowMidpoint : options.elbowMidpoint\n\tconst mx = mxRange ? lerp(mxRange.a, mxRange.b, midpoint) : null\n\tconst my = myRange ? lerp(myRange.a, myRange.b, midpoint) : null\n\n\t// The info without route is given to the route-finding functions to route between the two\n\t// terminals.\n\tconst info: ElbowArrowInfoWithoutRoute = {\n\t\toptions,\n\t\tswapOrder,\n\t\tA: {\n\t\t\tisPoint: aTerminal.isPoint,\n\t\t\ttarget: aTerminal.target,\n\t\t\tisExact: aTerminal.isExact,\n\t\t\tarrowheadOffset: aTerminal.arrowheadOffset,\n\t\t\tminEndSegmentLength: aTerminal.minEndSegmentLength,\n\t\t\toriginal: aTerminal.bounds,\n\t\t\texpanded: expandedA,\n\t\t\tedges: edgesA,\n\t\t\tgeometry: aTerminal.geometry,\n\t\t},\n\t\tB: {\n\t\t\tisPoint: bTerminal.isPoint,\n\t\t\ttarget: bTerminal.target,\n\t\t\tisExact: bTerminal.isExact,\n\t\t\tarrowheadOffset: bTerminal.arrowheadOffset,\n\t\t\tminEndSegmentLength: bTerminal.minEndSegmentLength,\n\t\t\toriginal: bTerminal.bounds,\n\t\t\texpanded: expandedB,\n\t\t\tedges: edgesB,\n\t\t\tgeometry: bTerminal.geometry,\n\t\t},\n\t\tcommon,\n\t\tgapX,\n\t\tgapY,\n\t\tmidX: mx,\n\t\tmidY: my,\n\t}\n\n\t// We wrap the info in a working info object that lets us mutate and reset it as needed.\n\tconst workingInfo = new ElbowArrowWorkingInfo(info)\n\n\t// Figure out the final sides to use for each terminal.\n\tconst aSide = getSideToUse(aTerminal, bTerminal, info.A.edges)\n\tconst bSide = getSideToUse(bTerminal, aTerminal, info.B.edges)\n\n\t// try to find a route with the specification we have:\n\tlet route\n\tif (aSide && bSide) {\n\t\troute = routeArrowWithManualEdgePicking(workingInfo, aSide, bSide)\n\t} else if (aSide && !bSide) {\n\t\troute = routeArrowWithPartialEdgePicking(workingInfo, aSide)\n\t}\n\tif (!route) {\n\t\troute = routeArrowWithAutoEdgePicking(workingInfo, aSide || bSide ? 'fallback' : 'auto')\n\t}\n\n\tif (route) {\n\t\t// If we found a route, we need to fix it up. The route will only go to the bounding box of\n\t\t// the shape, so we need to cast the final segments into the actual geometry of the shape.\n\t\tcastPathSegmentIntoGeometry('first', info.A, info.B, route)\n\t\tcastPathSegmentIntoGeometry('last', info.B, info.A, route)\n\t\t// If we have tiny L-shaped arrows, the arrowheads look super janky. We fix those up by just\n\t\t// drawing a straight line instead.\n\t\tfixTinyEndNubs(route, aTerminal, bTerminal)\n\n\t\t// If we swapped the order way back of the start of things, we need to reverse the route so\n\t\t// it flows start -> end instead of A -> B.\n\t\tif (swapOrder) route.points.reverse()\n\t}\n\n\treturn {\n\t\t...info,\n\t\troute,\n\t\tmidXRange: mxRange\n\t\t\t? swapOrder\n\t\t\t\t? { lo: mxRange.b, hi: mxRange.a }\n\t\t\t\t: { lo: mxRange.a, hi: mxRange.b }\n\t\t\t: null,\n\t\tmidYRange: myRange\n\t\t\t? swapOrder\n\t\t\t\t? { lo: myRange.b, hi: myRange.a }\n\t\t\t\t: { lo: myRange.a, hi: myRange.b }\n\t\t\t: null,\n\t}\n}\n\n/**\n * Take the route from `getElbowArrowInfo` (which represents the visible body of the arrow) and\n * convert it into a path we can use to show that paths to the handles, which may extend further\n * into the target shape geometries.\n * @returns\n */\nexport function getRouteHandlePath(info: ElbowArrowInfo, route: ElbowArrowRoute): ElbowArrowRoute {\n\tconst startTarget = info.swapOrder ? info.B.target : info.A.target\n\tconst endTarget = info.swapOrder ? info.A.target : info.B.target\n\n\tconst firstSegmentLength = Vec.ManhattanDist(route.points[0], route.points[1])\n\tconst lastSegmentLength = Vec.ManhattanDist(\n\t\troute.points[route.points.length - 2],\n\t\troute.points[route.points.length - 1]\n\t)\n\n\tconst newFirstSegmentLength = Vec.ManhattanDist(startTarget, route.points[1])\n\tconst newLastSegmentLength = Vec.ManhattanDist(route.points[route.points.length - 2], endTarget)\n\n\tconst firstSegmentLengthChange = firstSegmentLength - newFirstSegmentLength\n\tconst lastSegmentLengthChange = lastSegmentLength - newLastSegmentLength\n\n\tconst newPoints = [startTarget, ...route.points, endTarget]\n\n\treturn {\n\t\tname: route.name,\n\t\tdistance: route.distance + firstSegmentLengthChange + lastSegmentLengthChange,\n\t\tpoints: newPoints.filter((p) => !route.skipPointsWhenDrawing.has(p)),\n\t\taEdgePicking: route.aEdgePicking,\n\t\tbEdgePicking: route.bEdgePicking,\n\t\tskipPointsWhenDrawing: route.skipPointsWhenDrawing,\n\t\tmidpointHandle: route.midpointHandle,\n\t}\n}\n\n/**\n * Take a normalizes anchor and return the side we think it's closest to.\n */\nexport function getEdgeFromNormalizedAnchor(normalizedAnchor: VecLike) {\n\tif (approximately(normalizedAnchor.x, 0.5) && approximately(normalizedAnchor.y, 0.5)) {\n\t\treturn null\n\t}\n\n\tif (\n\t\tMath.abs(normalizedAnchor.x - 0.5) >\n\t\t// slightly bias towards x arrows to prevent flickering when the anchor is right on the line\n\t\t// between the two directions\n\t\tMath.abs(normalizedAnchor.y - 0.5) - 0.0001\n\t) {\n\t\treturn normalizedAnchor.x < 0.5 ? 'left' : 'right'\n\t}\n\n\treturn normalizedAnchor.y < 0.5 ? 'top' : 'bottom'\n}\n\nfunction getElbowArrowTerminalInfo(\n\teditor: Editor,\n\tarrow: TLArrowShape,\n\tbinding: TLArrowBinding | undefined,\n\tpoint: VecModel,\n\tarrowStrokeWidth?: number\n): ElbowArrowTerminal {\n\tconst theme = editor.getCurrentTheme()\n\tconst arrowSW = arrowStrokeWidth ?? theme.strokeWidth * STROKE_SIZES[arrow.props.size]\n\tconst arrowStrokeSize = (arrowSW * arrow.props.scale) / 2\n\tconst minEndSegmentLength = arrowStrokeSize * 3\n\n\tif (binding) {\n\t\tconst target = editor.getShape(binding.toId)\n\t\tconst geometry = getBindingGeometryInArrowSpace(editor, arrow, binding.toId, binding.props)\n\t\tif (geometry && target) {\n\t\t\tlet arrowheadOffset = 0\n\t\t\tconst arrowheadProp = binding.props.terminal === 'start' ? 'arrowheadStart' : 'arrowheadEnd'\n\t\t\tif (arrow.props[arrowheadProp] !== 'none') {\n\t\t\t\tconst targetScale = 'scale' in target.props ? target.props.scale : 1\n\t\t\t\tconst targetStrokeSize =\n\t\t\t\t\t'size' in target.props\n\t\t\t\t\t\t? (theme.strokeWidth * (STROKE_SIZES[target.props.size] ?? 0) * targetScale) / 2\n\t\t\t\t\t\t: 0\n\n\t\t\t\tarrowheadOffset =\n\t\t\t\t\tarrowStrokeSize + targetStrokeSize + BOUND_ARROW_OFFSET * arrow.props.scale\n\t\t\t}\n\n\t\t\tlet side: ElbowArrowSideWithAxis | null = null\n\t\t\tconst targetPoint = geometry.target\n\t\t\tif (binding.props.isPrecise) {\n\t\t\t\tside = getEdgeFromNormalizedAnchor(\n\t\t\t\t\tVec.RotWith(\n\t\t\t\t\t\tbinding.props.normalizedAnchor,\n\t\t\t\t\t\t{ x: 0.5, y: 0.5 },\n\t\t\t\t\t\tgeometry.shapeToArrowTransform.rotation()\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttargetShapeId: binding.toId,\n\t\t\t\tisPoint: false,\n\t\t\t\tisExact: binding.props.isExact,\n\t\t\t\tbounds: geometry.bounds,\n\t\t\t\tgeometry: geometry.geometry,\n\t\t\t\ttarget: targetPoint,\n\t\t\t\tarrowheadOffset,\n\t\t\t\tminEndSegmentLength,\n\t\t\t\tside,\n\t\t\t\tsnap: binding.props.snap,\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\ttargetShapeId: null,\n\t\tbounds: Box.FromCenter(point, { x: 0, y: 0 }),\n\t\tgeometry: null,\n\t\tisExact: false,\n\t\tisPoint: true,\n\t\ttarget: Vec.From(point),\n\t\tarrowheadOffset: 0,\n\t\tminEndSegmentLength,\n\t\tside: null,\n\t\tsnap: 'none',\n\t}\n}\n\nfunction getBindingGeometryInArrowSpace(\n\teditor: Editor,\n\tarrow: TLArrowShape,\n\ttargetId: TLShapeId,\n\tbindingProps: TLArrowBindingProps\n) {\n\tconst hasArrowhead =\n\t\tbindingProps.terminal === 'start'\n\t\t\t? arrow.props.arrowheadStart !== 'none'\n\t\t\t: arrow.props.arrowheadEnd !== 'none'\n\n\tconst targetGeometryInTargetSpace = editor.getShapeGeometry(\n\t\ttargetId,\n\t\thasArrowhead ? undefined : { context: '@tldraw/arrow-without-arrowhead' }\n\t)\n\n\tif (!targetGeometryInTargetSpace) {\n\t\treturn null\n\t}\n\n\tconst arrowTransform = editor.getShapePageTransform(arrow.id)\n\tconst shapeTransform = editor.getShapePageTransform(targetId)\n\tconst shapeToArrowTransform = arrowTransform.clone().invert().multiply(shapeTransform)\n\n\tconst targetGeometryInArrowSpace = targetGeometryInTargetSpace.transform(shapeToArrowTransform)\n\n\tconst center = { x: 0.5, y: 0.5 }\n\tconst normalizedAnchor = bindingProps.isPrecise ? bindingProps.normalizedAnchor : center\n\n\tconst targetInShapeSpace = {\n\t\tx: lerp(\n\t\t\ttargetGeometryInTargetSpace.bounds.minX,\n\t\t\ttargetGeometryInTargetSpace.bounds.maxX,\n\t\t\tnormalizedAnchor.x\n\t\t),\n\t\ty: lerp(\n\t\t\ttargetGeometryInTargetSpace.bounds.minY,\n\t\t\ttargetGeometryInTargetSpace.bounds.maxY,\n\t\t\tnormalizedAnchor.y\n\t\t),\n\t}\n\tconst centerInShapeSpace = {\n\t\tx: lerp(\n\t\t\ttargetGeometryInTargetSpace.bounds.minX,\n\t\t\ttargetGeometryInTargetSpace.bounds.maxX,\n\t\t\tcenter.x\n\t\t),\n\t\ty: lerp(\n\t\t\ttargetGeometryInTargetSpace.bounds.minY,\n\t\t\ttargetGeometryInTargetSpace.bounds.maxY,\n\t\t\tcenter.y\n\t\t),\n\t}\n\n\tconst targetInArrowSpace = Mat.applyToPoint(shapeToArrowTransform, targetInShapeSpace)\n\tconst centerInArrowSpace = Mat.applyToPoint(shapeToArrowTransform, centerInShapeSpace)\n\n\treturn {\n\t\tbounds: targetGeometryInArrowSpace.bounds,\n\t\tgeometry: targetGeometryInArrowSpace,\n\t\ttarget: targetInArrowSpace,\n\t\tcenter: centerInArrowSpace,\n\t\tshapeToArrowTransform,\n\t}\n}\n\nconst sideProps = {\n\ttop: {\n\t\texpand: -1,\n\t\tmain: 'minY',\n\t\topposite: 'maxY',\n\t\tcrossMid: 'midX',\n\t\tcrossMin: 'minX',\n\t\tcrossMax: 'maxX',\n\t\tbRangeExpand: 'max',\n\t\tcrossAxis: 'x',\n\t},\n\tbottom: {\n\t\texpand: 1,\n\t\tmain: 'maxY',\n\t\topposite: 'minY',\n\t\tcrossMid: 'midX',\n\t\tcrossMin: 'minX',\n\t\tcrossMax: 'maxX',\n\t\tbRangeExpand: 'min',\n\t\tcrossAxis: 'x',\n\t},\n\tleft: {\n\t\texpand: -1,\n\t\tmain: 'minX',\n\t\topposite: 'maxX',\n\t\tcrossMid: 'midY',\n\t\tcrossMin: 'minY',\n\t\tcrossMax: 'maxY',\n\t\tbRangeExpand: 'max',\n\t\tcrossAxis: 'y',\n\t},\n\tright: {\n\t\texpand: 1,\n\t\tmain: 'maxX',\n\t\topposite: 'minX',\n\t\tcrossMid: 'midY',\n\t\tcrossMin: 'minY',\n\t\tcrossMax: 'maxY',\n\t\tbRangeExpand: 'min',\n\t\tcrossAxis: 'y',\n\t},\n} as const\n\nexport function getUsableEdge(\n\ta: ElbowArrowTerminal,\n\tb: ElbowArrowTerminal,\n\tside: 'top' | 'right' | 'bottom' | 'left',\n\toptions: ElbowArrowOptions\n): ElbowArrowEdge | null {\n\tconst props = sideProps[side]\n\n\t// if a shape is bound to itself, by default we'd end up routing the arrow _within_ the shape -\n\t// as if it were a point-to-point arrow. if one of the bindings is specifically to the edge\n\t// though, we route it externally instead.\n\tconst isSelfBoundAndShouldRouteExternal =\n\t\ta.targetShapeId === b.targetShapeId &&\n\t\ta.targetShapeId !== null &&\n\t\t(a.snap === 'edge' || a.snap === 'edge-point') &&\n\t\t(b.snap === 'edge' || b.snap === 'edge-point')\n\n\tconst aValue = a.bounds[props.main]\n\tconst aExpanded = a.isPoint ? null : aValue + props.expand * options.expandElbowLegLength\n\n\tconst originalACrossRange = createRange(a.bounds[props.crossMin], a.bounds[props.crossMax])\n\tlet aCrossRange = originalACrossRange\n\n\t// this edge is too small to be useful:\n\tif (!aCrossRange) {\n\t\treturn null\n\t}\n\n\tassert(originalACrossRange)\n\tconst bRange = createRange(b.bounds[props.main], b.bounds[props.opposite])\n\tif (!b.isPoint) {\n\t\tbRange[props.bRangeExpand] -= options.minElbowLegLength * 2 * props.expand\n\t}\n\n\tconst bCrossRange = expandRange(\n\t\tcreateRange(b.bounds[props.crossMin], b.bounds[props.crossMax]),\n\t\toptions.expandElbowLegLength\n\t)\n\tassert(bRange && bCrossRange)\n\n\tlet isPartial = false\n\tif (\n\t\tisWithinRange(aValue, bRange) &&\n\t\t!a.isPoint &&\n\t\t!b.isPoint &&\n\t\t!isSelfBoundAndShouldRouteExternal\n\t) {\n\t\tconst subtracted = subtractRange(aCrossRange, bCrossRange)\n\t\tswitch (subtracted.length) {\n\t\t\tcase 0:\n\t\t\t\treturn null\n\t\t\tcase 1:\n\t\t\t\tisPartial = subtracted[0] !== aCrossRange\n\t\t\t\taCrossRange = subtracted[0]\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\tisPartial = true\n\t\t\t\taCrossRange =\n\t\t\t\t\trangeSize(subtracted[0]) > rangeSize(subtracted[1]) ? subtracted[0] : subtracted[1]\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\texhaustiveSwitchError(subtracted)\n\t\t}\n\t}\n\n\tif (!isWithinRange(a.target[props.crossAxis], aCrossRange)) {\n\t\treturn null\n\t}\n\tconst crossTarget = a.target[props.crossAxis]\n\n\treturn {\n\t\tvalue: aValue,\n\t\texpanded: aExpanded,\n\t\tcross: aCrossRange,\n\t\tcrossTarget,\n\t\tisPartial,\n\t}\n}\n\nfunction hasUsableEdge(edges: ElbowArrowBoxEdges, side: ElbowArrowSideWithAxis | null) {\n\tif (side === null) {\n\t\treturn !!(edges.bottom || edges.left || edges.right || edges.top)\n\t}\n\n\tif (side === 'x') {\n\t\treturn !!edges.left || !!edges.right\n\t}\n\n\tif (side === 'y') {\n\t\treturn !!edges.top || !!edges.bottom\n\t}\n\n\treturn !!edges[side]\n}\n\nfunction getSideToUse(\n\tbinding: ElbowArrowTerminal,\n\tother: ElbowArrowTerminal,\n\tedges: ElbowArrowBoxEdges | null\n): ElbowArrowSide | null {\n\tswitch (binding.side) {\n\t\tcase null:\n\t\t\treturn null\n\t\tcase 'x':\n\t\t\tif (binding.bounds.center.x > other.bounds.center.x && edges?.left) {\n\t\t\t\treturn 'left'\n\t\t\t} else if (edges?.right) {\n\t\t\t\treturn 'right'\n\t\t\t}\n\t\t\treturn null\n\t\tcase 'y':\n\t\t\tif (binding.bounds.center.y > other.bounds.center.y && edges?.top) {\n\t\t\t\treturn 'top'\n\t\t\t} else if (edges?.bottom) {\n\t\t\t\treturn 'bottom'\n\t\t\t}\n\t\t\treturn null\n\t\tdefault:\n\t\t\treturn binding.side\n\t}\n}\n\nfunction convertTerminalToPoint(terminal: ElbowArrowTerminal): ElbowArrowTerminal {\n\tif (terminal.isPoint) return terminal\n\n\tlet side: ElbowArrowSideWithAxis | null = null\n\tlet arrowheadOffset = 0\n\tif (terminal.snap === 'edge' || terminal.snap === 'edge-point') {\n\t\tarrowheadOffset = terminal.arrowheadOffset\n\t\tif (terminal.side === 'x' || terminal.side === 'left' || terminal.side === 'right') {\n\t\t\tside = 'x'\n\t\t}\n\t\tif (terminal.side === 'y' || terminal.side === 'top' || terminal.side === 'bottom') {\n\t\t\tside = 'y'\n\t\t}\n\t}\n\n\treturn {\n\t\ttargetShapeId: terminal.targetShapeId,\n\t\tside,\n\t\tbounds: new Box(terminal.target.x, terminal.target.y, 0, 0),\n\t\tgeometry: terminal.geometry,\n\t\ttarget: terminal.target,\n\t\tarrowheadOffset,\n\t\tminEndSegmentLength: terminal.minEndSegmentLength,\n\t\tisExact: terminal.isExact,\n\t\tisPoint: true,\n\t\tsnap: terminal.snap,\n\t}\n}\n\n/**\n * Make sure the first path segments goes fully into the target, and doesn't just point to its\n * bounding box. This modifies the route in-place.\n */\nfunction castPathSegmentIntoGeometry(\n\tsegment: 'first' | 'last',\n\ttarget: ElbowArrowTargetBox,\n\tother: ElbowArrowTargetBox,\n\troute: ElbowArrowRoute\n) {\n\tif (!target.geometry) return\n\n\tconst point1 = segment === 'first' ? route.points[0] : route.points[route.points.length - 1]\n\tconst point2 = segment === 'first' ? route.points[1] : route.points[route.points.length - 2]\n\n\tconst pointToFindClosestIntersectionTo = target.geometry.isClosed ? point2 : target.target\n\n\tconst initialDistance = Vec.ManhattanDist(point1, pointToFindClosestIntersectionTo)\n\n\tlet nearestIntersectionToPoint2: VecLike | null = null\n\tlet nearestDistanceToPoint2 = Infinity\n\n\tif (target.isExact) {\n\t\tnearestIntersectionToPoint2 = target.target\n\t} else if (target.geometry) {\n\t\tconst intersections = target.geometry.intersectLineSegment(point2, target.target, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\t\tif (\n\t\t\ttarget.geometry.hitTestPoint(\n\t\t\t\ttarget.target,\n\t\t\t\tMath.max(1, target.arrowheadOffset),\n\t\t\t\ttrue,\n\t\t\t\tGeometry2dFilters.EXCLUDE_NON_STANDARD\n\t\t\t)\n\t\t) {\n\t\t\tintersections.push(target.target)\n\t\t}\n\t\tfor (const intersection of intersections) {\n\t\t\tconst point2Distance = Vec.ManhattanDist(pointToFindClosestIntersectionTo, intersection)\n\t\t\tif (point2Distance < nearestDistanceToPoint2) {\n\t\t\t\tnearestDistanceToPoint2 = point2Distance\n\t\t\t\tnearestIntersectionToPoint2 = intersection\n\t\t\t}\n\t\t}\n\t}\n\n\tif (nearestIntersectionToPoint2) {\n\t\tlet offset = target.arrowheadOffset\n\n\t\tconst currentFinalSegmentLength = Vec.ManhattanDist(point2, nearestIntersectionToPoint2)\n\t\tconst minLength = target.arrowheadOffset * 2\n\t\tif (currentFinalSegmentLength < minLength) {\n\t\t\tconst targetLength = minLength - target.arrowheadOffset\n\t\t\toffset = currentFinalSegmentLength - targetLength\n\t\t}\n\t\tif (offset < target.minEndSegmentLength) {\n\t\t\tif (target.geometry.bounds.containsPoint(other.target)) {\n\t\t\t\toffset = Math.max(0, offset)\n\t\t\t} else {\n\t\t\t\toffset = -target.arrowheadOffset\n\t\t\t}\n\t\t}\n\n\t\tlet nudgedPoint = nearestIntersectionToPoint2\n\t\tlet shouldAddExtraPointForNudge = false\n\t\tif (!target.isExact && offset !== 0) {\n\t\t\tconst nudged = Vec.Nudge(nearestIntersectionToPoint2, point2, offset)\n\t\t\tnudgedPoint = nudged\n\t\t\tif (\n\t\t\t\toffset < 0 &&\n\t\t\t\t!target.geometry.hitTestPoint(nudged, 0, true, Geometry2dFilters.EXCLUDE_NON_STANDARD)\n\t\t\t) {\n\t\t\t\t// point has been nudged _out_ of the shape so lets not actually apply the nudge\n\t\t\t\tnudgedPoint = nearestIntersectionToPoint2\n\t\t\t} else {\n\t\t\t\tif (offset < 0) {\n\t\t\t\t\tshouldAddExtraPointForNudge = true\n\t\t\t\t}\n\t\t\t\tnudgedPoint = nudged\n\t\t\t}\n\t\t}\n\n\t\tconst newDistance = Vec.ManhattanDist(point2, nudgedPoint)\n\t\troute.distance += newDistance - initialDistance\n\t\tpoint1.x = nudgedPoint.x\n\t\tpoint1.y = nudgedPoint.y\n\n\t\tif (shouldAddExtraPointForNudge) {\n\t\t\tconst midPoint = Vec.Lrp(point2, point1, 0.5)\n\t\t\troute.skipPointsWhenDrawing.add(midPoint)\n\t\t\troute.points.splice(segment === 'first' ? 1 : route.points.length - 1, 0, midPoint)\n\t\t}\n\t}\n}\n\nfunction fixTinyEndNubs(\n\troute: ElbowArrowRoute,\n\taTerminal: ElbowArrowTerminal,\n\tbTerminal: ElbowArrowTerminal\n) {\n\tif (!route) return\n\n\tif (route.points.length >= 3) {\n\t\tconst a = route.points[0]\n\t\tconst b = route.points[1]\n\t\tconst firstSegmentLength = Vec.ManhattanDist(a, b)\n\t\tif (firstSegmentLength < aTerminal.minEndSegmentLength) {\n\t\t\troute.points.splice(1, 1)\n\t\t\tif (route.points.length >= 3) {\n\t\t\t\tconst matchAxis = approximately(a.x, b.x) ? 'y' : 'x'\n\t\t\t\troute.points[1][matchAxis] = a[matchAxis]\n\t\t\t}\n\t\t}\n\t}\n\n\tif (route.points.length >= 3) {\n\t\tconst a = route.points[route.points.length - 1]\n\t\tconst b = route.points[route.points.length - 2]\n\t\tconst lastSegmentLength = Vec.ManhattanDist(a, b)\n\t\tif (lastSegmentLength < bTerminal.minEndSegmentLength) {\n\t\t\troute.points.splice(route.points.length - 2, 1)\n\t\t\tif (route.points.length >= 3) {\n\t\t\t\tconst matchAxis = approximately(a.x, b.x) ? 'y' : 'x'\n\t\t\t\troute.points[route.points.length - 2][matchAxis] = a[matchAxis]\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction adjustTerminalForUnclosedPathIfNeeded(\n\tterminal: ElbowArrowTerminal,\n\totherTerminal: ElbowArrowTerminal,\n\toptions: ElbowArrowOptions\n): ElbowArrowTerminal {\n\tif (!terminal.geometry || terminal.geometry.isClosed) return terminal\n\tconst normalizedPointAlongPath = terminal.geometry.uninterpolateAlongEdge(\n\t\tterminal.target,\n\t\tGeometry2dFilters.EXCLUDE_NON_STANDARD\n\t)\n\n\tconst prev = terminal.geometry.interpolateAlongEdge(\n\t\tnormalizedPointAlongPath - 0.01 / terminal.geometry.length\n\t)\n\tconst next = terminal.geometry.interpolateAlongEdge(\n\t\tnormalizedPointAlongPath + 0.01 / terminal.geometry.length\n\t)\n\n\tconst normal = next.sub(prev).per().uni()\n\tconst axis = Math.abs(normal.x) > Math.abs(normal.y) ? ElbowArrowAxes.x : ElbowArrowAxes.y\n\n\tif (terminal.geometry.bounds.containsPoint(otherTerminal.target, options.expandElbowLegLength)) {\n\t\tterminal.side = axis.self\n\t\treturn convertTerminalToPoint(terminal)\n\t}\n\n\tconst min = axis.v(\n\t\tterminal.target[axis.self] - terminal.bounds[axis.size] * 2,\n\t\tterminal.target[axis.cross]\n\t)\n\tconst max = axis.v(\n\t\tterminal.target[axis.self] + terminal.bounds[axis.size] * 2,\n\t\tterminal.target[axis.cross]\n\t)\n\n\tlet furthestIntersectionTowardsMin: VecLike | null = null\n\tlet furthestIntersectionTowardsMinDistance = 0\n\tlet furthestIntersectionTowardsMax: VecLike | null = null\n\tlet furthestIntersectionTowardsMaxDistance = 0\n\tlet side: ElbowArrowSideWithAxis = axis.self\n\n\tfor (const intersection of terminal.geometry.intersectLineSegment(\n\t\tmin,\n\t\tmax,\n\t\tGeometry2dFilters.EXCLUDE_NON_STANDARD\n\t)) {\n\t\tif (Math.abs(intersection[axis.self] - terminal.target[axis.self]) < 1) {\n\t\t\tcontinue\n\t\t}\n\t\tif (intersection[axis.self] < terminal.target[axis.self]) {\n\t\t\tif (\n\t\t\t\tVec.ManhattanDist(intersection, terminal.target) > furthestIntersectionTowardsMinDistance\n\t\t\t) {\n\t\t\t\tfurthestIntersectionTowardsMinDistance = Vec.ManhattanDist(intersection, terminal.target)\n\t\t\t\tfurthestIntersectionTowardsMin = intersection\n\t\t\t}\n\t\t} else {\n\t\t\tif (\n\t\t\t\tVec.ManhattanDist(intersection, terminal.target) > furthestIntersectionTowardsMaxDistance\n\t\t\t) {\n\t\t\t\tfurthestIntersectionTowardsMaxDistance = Vec.ManhattanDist(intersection, terminal.target)\n\t\t\t\tfurthestIntersectionTowardsMax = intersection\n\t\t\t}\n\t\t}\n\t}\n\n\tif (furthestIntersectionTowardsMin && furthestIntersectionTowardsMax) {\n\t\tif (furthestIntersectionTowardsMinDistance > furthestIntersectionTowardsMaxDistance) {\n\t\t\tside = axis.hiEdge\n\t\t} else {\n\t\t\tside = axis.loEdge\n\t\t}\n\t} else if (furthestIntersectionTowardsMin && !furthestIntersectionTowardsMax) {\n\t\tside = axis.hiEdge\n\t} else if (!furthestIntersectionTowardsMin && furthestIntersectionTowardsMax) {\n\t\tside = axis.loEdge\n\t}\n\n\tterminal.side = side\n\treturn terminal\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -34,7 +34,7 @@ const arrowInfoCache = (0, import_store.createComputedCache)(
|
|
|
34
34
|
(editor, shape) => {
|
|
35
35
|
const bindings = (0, import_shared.getArrowBindings)(editor, shape);
|
|
36
36
|
const util = editor.getShapeUtil(shape);
|
|
37
|
-
const sw = "
|
|
37
|
+
const sw = "getDefaultDisplayValues" in util.options && "getCustomDisplayValues" in util.options ? (0, import_getDisplayValues.getDisplayValues)(util, shape).strokeWidth : editor.getCurrentTheme().strokeWidth * import_default_shape_constants.STROKE_SIZES[shape.props.size];
|
|
38
38
|
if (shape.props.kind === "elbow") {
|
|
39
39
|
const elbowInfo = (0, import_getElbowArrowInfo.getElbowArrowInfo)(editor, shape, bindings, sw);
|
|
40
40
|
if (!elbowInfo?.route) return (0, import_straight_arrow.getStraightArrowInfo)(editor, shape, bindings, sw);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/arrow/getArrowInfo.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tEditor,\n\tisEqualAllowingForFloatingPointErrors,\n\tTLArrowShape,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport { createComputedCache } from '@tldraw/store'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { getDisplayValues } from '../shared/getDisplayValues'\nimport { TLArrowInfo } from './arrow-types'\nimport { getCurvedArrowInfo } from './curved-arrow'\nimport { getElbowArrowInfo } from './elbow/getElbowArrowInfo'\nimport { getArrowBindings, getIsArrowStraight } from './shared'\nimport { getStraightArrowInfo } from './straight-arrow'\n\nconst arrowInfoCache = createComputedCache<Editor, TLArrowInfo, TLArrowShape>(\n\t'arrow info',\n\t(editor: Editor, shape: TLArrowShape): TLArrowInfo => {\n\t\tconst bindings = getArrowBindings(editor, shape)\n\t\tconst util = editor.getShapeUtil(shape)\n\t\tconst sw =\n\t\t\t'
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAKO;AACP,mBAAoC;AACpC,qCAA6B;AAC7B,8BAAiC;AAEjC,0BAAmC;AACnC,+BAAkC;AAClC,oBAAqD;AACrD,4BAAqC;AAErC,MAAM,qBAAiB;AAAA,EACtB;AAAA,EACA,CAAC,QAAgB,UAAqC;AACrD,UAAM,eAAW,gCAAiB,QAAQ,KAAK;AAC/C,UAAM,OAAO,OAAO,aAAa,KAAK;
|
|
4
|
+
"sourcesContent": ["import {\n\tEditor,\n\tisEqualAllowingForFloatingPointErrors,\n\tTLArrowShape,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport { createComputedCache } from '@tldraw/store'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { getDisplayValues } from '../shared/getDisplayValues'\nimport { TLArrowInfo } from './arrow-types'\nimport { getCurvedArrowInfo } from './curved-arrow'\nimport { getElbowArrowInfo } from './elbow/getElbowArrowInfo'\nimport { getArrowBindings, getIsArrowStraight } from './shared'\nimport { getStraightArrowInfo } from './straight-arrow'\n\nconst arrowInfoCache = createComputedCache<Editor, TLArrowInfo, TLArrowShape>(\n\t'arrow info',\n\t(editor: Editor, shape: TLArrowShape): TLArrowInfo => {\n\t\tconst bindings = getArrowBindings(editor, shape)\n\t\tconst util = editor.getShapeUtil(shape)\n\t\t// A replacement arrow util may not carry display values; fall back to the theme width.\n\t\tconst sw =\n\t\t\t'getDefaultDisplayValues' in util.options && 'getCustomDisplayValues' in util.options\n\t\t\t\t? (getDisplayValues(util as any, shape) as { strokeWidth: number }).strokeWidth\n\t\t\t\t: editor.getCurrentTheme().strokeWidth * STROKE_SIZES[shape.props.size]\n\n\t\tif (shape.props.kind === 'elbow') {\n\t\t\tconst elbowInfo = getElbowArrowInfo(editor, shape, bindings, sw)\n\t\t\tif (!elbowInfo?.route) return getStraightArrowInfo(editor, shape, bindings, sw)\n\n\t\t\tconst start = elbowInfo.swapOrder ? elbowInfo.B : elbowInfo.A\n\t\t\tconst end = elbowInfo.swapOrder ? elbowInfo.A : elbowInfo.B\n\n\t\t\treturn {\n\t\t\t\ttype: 'elbow',\n\t\t\t\tbindings,\n\t\t\t\tstart: {\n\t\t\t\t\thandle: start.target,\n\t\t\t\t\tpoint: elbowInfo.route.points[0],\n\t\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t\t},\n\t\t\t\tend: {\n\t\t\t\t\thandle: end.target,\n\t\t\t\t\tpoint: elbowInfo.route.points[elbowInfo.route.points.length - 1],\n\t\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t\t},\n\t\t\t\telbow: elbowInfo,\n\t\t\t\troute: elbowInfo.route,\n\t\t\t\tisValid: true,\n\t\t\t}\n\t\t}\n\n\t\tif (getIsArrowStraight(shape)) {\n\t\t\treturn getStraightArrowInfo(editor, shape, bindings, sw)\n\t\t} else {\n\t\t\treturn getCurvedArrowInfo(editor, shape, bindings, sw)\n\t\t}\n\t},\n\t{\n\t\tareRecordsEqual: (a, b) => a.props === b.props,\n\t\tareResultsEqual: isEqualAllowingForFloatingPointErrors,\n\t}\n)\n\n/** @public */\nexport function getArrowInfo(editor: Editor, shape: TLArrowShape | TLShapeId) {\n\tconst id = typeof shape === 'string' ? shape : shape.id\n\treturn arrowInfoCache.get(editor, id)\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAKO;AACP,mBAAoC;AACpC,qCAA6B;AAC7B,8BAAiC;AAEjC,0BAAmC;AACnC,+BAAkC;AAClC,oBAAqD;AACrD,4BAAqC;AAErC,MAAM,qBAAiB;AAAA,EACtB;AAAA,EACA,CAAC,QAAgB,UAAqC;AACrD,UAAM,eAAW,gCAAiB,QAAQ,KAAK;AAC/C,UAAM,OAAO,OAAO,aAAa,KAAK;AAEtC,UAAM,KACL,6BAA6B,KAAK,WAAW,4BAA4B,KAAK,cAC1E,0CAAiB,MAAa,KAAK,EAA8B,cAClE,OAAO,gBAAgB,EAAE,cAAc,4CAAa,MAAM,MAAM,IAAI;AAExE,QAAI,MAAM,MAAM,SAAS,SAAS;AACjC,YAAM,gBAAY,4CAAkB,QAAQ,OAAO,UAAU,EAAE;AAC/D,UAAI,CAAC,WAAW,MAAO,YAAO,4CAAqB,QAAQ,OAAO,UAAU,EAAE;AAE9E,YAAM,QAAQ,UAAU,YAAY,UAAU,IAAI,UAAU;AAC5D,YAAM,MAAM,UAAU,YAAY,UAAU,IAAI,UAAU;AAE1D,aAAO;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA,OAAO;AAAA,UACN,QAAQ,MAAM;AAAA,UACd,OAAO,UAAU,MAAM,OAAO,CAAC;AAAA,UAC/B,WAAW,MAAM,MAAM;AAAA,QACxB;AAAA,QACA,KAAK;AAAA,UACJ,QAAQ,IAAI;AAAA,UACZ,OAAO,UAAU,MAAM,OAAO,UAAU,MAAM,OAAO,SAAS,CAAC;AAAA,UAC/D,WAAW,MAAM,MAAM;AAAA,QACxB;AAAA,QACA,OAAO;AAAA,QACP,OAAO,UAAU;AAAA,QACjB,SAAS;AAAA,MACV;AAAA,IACD;AAEA,YAAI,kCAAmB,KAAK,GAAG;AAC9B,iBAAO,4CAAqB,QAAQ,OAAO,UAAU,EAAE;AAAA,IACxD,OAAO;AACN,iBAAO,wCAAmB,QAAQ,OAAO,UAAU,EAAE;AAAA,IACtD;AAAA,EACD;AAAA,EACA;AAAA,IACC,iBAAiB,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE;AAAA,IACzC,iBAAiB;AAAA,EAClB;AACD;AAGO,SAAS,aAAa,QAAgB,OAAiC;AAC7E,QAAM,KAAK,OAAO,UAAU,WAAW,QAAQ,MAAM;AACrD,SAAO,eAAe,IAAI,QAAQ,EAAE;AACrC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -100,12 +100,12 @@ function getStraightArrowInfo(editor, shape, bindings, arrowStrokeWidth) {
|
|
|
100
100
|
const didFlip = !import_editor.Vec.Equals(u, uAB);
|
|
101
101
|
if (!isSelfIntersection) {
|
|
102
102
|
if (relationship !== "start-contains-end" && startShapeInfo && arrowheadStart !== "none" && !startShapeInfo.isExact) {
|
|
103
|
-
strokeOffsetA = arrowSW / 2 + ("size" in startShapeInfo.shape.props ? theme.strokeWidth * import_default_shape_constants.STROKE_SIZES[startShapeInfo.shape.props.size] / 2 : 0);
|
|
103
|
+
strokeOffsetA = arrowSW / 2 + ("size" in startShapeInfo.shape.props ? theme.strokeWidth * (import_default_shape_constants.STROKE_SIZES[startShapeInfo.shape.props.size] ?? 0) / 2 : 0);
|
|
104
104
|
offsetA = (import_shared.BOUND_ARROW_OFFSET + strokeOffsetA) * shape.props.scale;
|
|
105
105
|
minLength += strokeOffsetA * shape.props.scale;
|
|
106
106
|
}
|
|
107
107
|
if (relationship !== "end-contains-start" && endShapeInfo && arrowheadEnd !== "none" && !endShapeInfo.isExact) {
|
|
108
|
-
strokeOffsetB = arrowSW / 2 + ("size" in endShapeInfo.shape.props ? theme.strokeWidth * import_default_shape_constants.STROKE_SIZES[endShapeInfo.shape.props.size] / 2 : 0);
|
|
108
|
+
strokeOffsetB = arrowSW / 2 + ("size" in endShapeInfo.shape.props ? theme.strokeWidth * (import_default_shape_constants.STROKE_SIZES[endShapeInfo.shape.props.size] ?? 0) / 2 : 0);
|
|
109
109
|
offsetB = (import_shared.BOUND_ARROW_OFFSET + strokeOffsetB) * shape.props.scale;
|
|
110
110
|
minLength += strokeOffsetB * shape.props.scale;
|
|
111
111
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/arrow/straight-arrow.ts"],
|
|
4
|
-
"sourcesContent": ["import { Editor, Mat, MatModel, TLArrowShape, Vec, VecLike } from '@tldraw/editor'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { TLArrowInfo } from './arrow-types'\nimport {\n\tBOUND_ARROW_OFFSET,\n\tBoundShapeInfo,\n\tMIN_ARROW_LENGTH,\n\tTLArrowBindings,\n\tclampArrowTerminalToMask,\n\tgetArrowTerminalsInArrowSpace,\n\tgetBoundShapeInfoForTerminal,\n\tgetBoundShapeRelationships,\n} from './shared'\n\nexport function getStraightArrowInfo(\n\teditor: Editor,\n\tshape: TLArrowShape,\n\tbindings: TLArrowBindings,\n\tarrowStrokeWidth?: number\n): TLArrowInfo {\n\tconst { arrowheadStart, arrowheadEnd } = shape.props\n\n\tconst terminalsInArrowSpace = getArrowTerminalsInArrowSpace(editor, shape, bindings)\n\n\tconst a = terminalsInArrowSpace.start.clone()\n\tconst b = terminalsInArrowSpace.end.clone()\n\tconst c = Vec.Med(a, b)\n\n\tif (Vec.Equals(a, b)) {\n\t\treturn {\n\t\t\tbindings,\n\t\t\ttype: 'straight',\n\t\t\tstart: {\n\t\t\t\thandle: a,\n\t\t\t\tpoint: a,\n\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\thandle: b,\n\t\t\t\tpoint: b,\n\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t},\n\t\t\tmiddle: c,\n\t\t\tisValid: false,\n\t\t\tlength: 0,\n\t\t}\n\t}\n\n\tconst uAB = Vec.Sub(b, a).uni()\n\n\t// Update the arrowhead points using intersections with the bound shapes, if any.\n\n\tconst startShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'start')\n\tconst endShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'end')\n\n\tconst arrowPageTransform = editor.getShapePageTransform(shape)!\n\n\t// Update the position of the arrowhead's end point\n\tupdateArrowheadPointWithBoundShape(\n\t\tb, // <-- will be mutated\n\t\tterminalsInArrowSpace.start,\n\t\tarrowPageTransform,\n\t\tendShapeInfo\n\t)\n\n\t// Then update the position of the arrowhead's end point\n\tupdateArrowheadPointWithBoundShape(\n\t\ta, // <-- will be mutated\n\t\tterminalsInArrowSpace.end,\n\t\tarrowPageTransform,\n\t\tstartShapeInfo\n\t)\n\n\t// Clamp terminals to mask boundaries if the bound shape is clipped (e.g. by a frame)\n\tclampArrowTerminalToMask(editor, b, terminalsInArrowSpace.end, arrowPageTransform, endShapeInfo)\n\tclampArrowTerminalToMask(\n\t\teditor,\n\t\ta,\n\t\tterminalsInArrowSpace.start,\n\t\tarrowPageTransform,\n\t\tstartShapeInfo\n\t)\n\n\tlet offsetA = 0\n\tlet offsetB = 0\n\tlet strokeOffsetA = 0\n\tlet strokeOffsetB = 0\n\tlet minLength = MIN_ARROW_LENGTH * shape.props.scale\n\n\tconst theme = editor.getCurrentTheme()\n\tconst arrowSW = arrowStrokeWidth ?? theme.strokeWidth * STROKE_SIZES[shape.props.size]\n\n\tconst isSelfIntersection =\n\t\tstartShapeInfo && endShapeInfo && startShapeInfo.shape === endShapeInfo.shape\n\n\tconst relationship =\n\t\tstartShapeInfo && endShapeInfo\n\t\t\t? getBoundShapeRelationships(editor, startShapeInfo.shape.id, endShapeInfo.shape.id)\n\t\t\t: 'safe'\n\n\tif (\n\t\trelationship === 'safe' &&\n\t\tstartShapeInfo &&\n\t\tendShapeInfo &&\n\t\t!isSelfIntersection &&\n\t\t!startShapeInfo.isExact &&\n\t\t!endShapeInfo.isExact\n\t) {\n\t\tif (endShapeInfo.didIntersect && !startShapeInfo.didIntersect) {\n\t\t\t// ...and if only the end shape intersected, then make it\n\t\t\t// a short arrow ending at the end shape intersection.\n\t\t\tif (startShapeInfo.isClosed) {\n\t\t\t\ta.setTo(b.clone().add(uAB.clone().mul(MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t\t}\n\t\t} else if (!endShapeInfo.didIntersect) {\n\t\t\t// ...and if only the end shape intersected, or if neither\n\t\t\t// shape intersected, then make it a short arrow starting\n\t\t\t// at the start shape intersection.\n\t\t\tif (endShapeInfo.isClosed) {\n\t\t\t\tb.setTo(a.clone().sub(uAB.clone().mul(MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t\t}\n\t\t}\n\t}\n\n\tconst distance = Vec.Sub(b, a)\n\t// Check for divide-by-zero before we call uni()\n\tconst u = Vec.Len(distance) ? distance.uni() : Vec.From(distance)\n\tconst didFlip = !Vec.Equals(u, uAB)\n\n\t// If the arrow is bound non-exact to a start shape and the\n\t// start point has an arrowhead, then offset the start point\n\tif (!isSelfIntersection) {\n\t\tif (\n\t\t\trelationship !== 'start-contains-end' &&\n\t\t\tstartShapeInfo &&\n\t\t\tarrowheadStart !== 'none' &&\n\t\t\t!startShapeInfo.isExact\n\t\t) {\n\t\t\tstrokeOffsetA =\n\t\t\t\tarrowSW / 2 +\n\t\t\t\t('size' in startShapeInfo.shape.props\n\t\t\t\t\t? (theme.strokeWidth * STROKE_SIZES[startShapeInfo.shape.props.size]) / 2\n\t\t\t\t\t: 0)\n\t\t\toffsetA = (BOUND_ARROW_OFFSET + strokeOffsetA) * shape.props.scale\n\t\t\tminLength += strokeOffsetA * shape.props.scale\n\t\t}\n\n\t\t// If the arrow is bound non-exact to an end shape and the\n\t\t// end point has an arrowhead offset the end point\n\t\tif (\n\t\t\trelationship !== 'end-contains-start' &&\n\t\t\tendShapeInfo &&\n\t\t\tarrowheadEnd !== 'none' &&\n\t\t\t!endShapeInfo.isExact\n\t\t) {\n\t\t\tstrokeOffsetB =\n\t\t\t\tarrowSW / 2 +\n\t\t\t\t('size' in endShapeInfo.shape.props\n\t\t\t\t\t? (theme.strokeWidth * STROKE_SIZES[endShapeInfo.shape.props.size]) / 2\n\t\t\t\t\t: 0)\n\t\t\toffsetB = (BOUND_ARROW_OFFSET + strokeOffsetB) * shape.props.scale\n\t\t\tminLength += strokeOffsetB * shape.props.scale\n\t\t}\n\t}\n\n\t// Adjust offsets if the length of the arrow is too small\n\n\tconst tA = a.clone().add(u.clone().mul(offsetA * (didFlip ? -1 : 1)))\n\tconst tB = b.clone().sub(u.clone().mul(offsetB * (didFlip ? -1 : 1)))\n\n\tif (Vec.DistMin(tA, tB, minLength)) {\n\t\tif (offsetA !== 0 && offsetB !== 0) {\n\t\t\t// both bound + offset\n\t\t\toffsetA *= -1.5\n\t\t\toffsetB *= -1.5\n\t\t} else if (offsetA !== 0) {\n\t\t\t// start bound + offset\n\t\t\toffsetA *= -1\n\t\t} else if (offsetB !== 0) {\n\t\t\t// end bound + offset\n\t\t\toffsetB *= -1\n\t\t} else {\n\t\t\t// noop, its just a really short arrow\n\t\t}\n\t}\n\n\ta.add(u.clone().mul(offsetA * (didFlip ? -1 : 1)))\n\tb.sub(u.clone().mul(offsetB * (didFlip ? -1 : 1)))\n\n\t// If the handles flipped their order, then set the center handle\n\t// to the midpoint of the terminals (rather than the midpoint of the\n\t// arrow body); otherwise, it may not be \"between\" the other terminals.\n\tif (didFlip) {\n\t\tif (startShapeInfo && endShapeInfo) {\n\t\t\t// If we have two bound shapes...then make the arrow a short arrow from\n\t\t\t// the start point towards where the end point should be.\n\t\t\tb.setTo(Vec.Add(a, u.clone().mul(-MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t}\n\t\tc.setTo(Vec.Med(terminalsInArrowSpace.start, terminalsInArrowSpace.end))\n\t} else {\n\t\tc.setTo(Vec.Med(a, b))\n\t}\n\n\tconst length = Vec.Dist(a, b)\n\n\treturn {\n\t\tbindings,\n\t\ttype: 'straight',\n\t\tstart: {\n\t\t\thandle: terminalsInArrowSpace.start,\n\t\t\tpoint: a,\n\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t},\n\t\tend: {\n\t\t\thandle: terminalsInArrowSpace.end,\n\t\t\tpoint: b,\n\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t},\n\t\tmiddle: c,\n\t\tisValid: length > 0,\n\t\tlength,\n\t}\n}\n\n/** Get an intersection point from A -> B with bound shape (target) from shape (arrow). */\nfunction updateArrowheadPointWithBoundShape(\n\tpoint: Vec,\n\topposite: Vec,\n\tarrowPageTransform: MatModel,\n\ttargetShapeInfo?: BoundShapeInfo\n) {\n\tif (targetShapeInfo === undefined) {\n\t\t// No bound shape? The arrowhead point will be at the arrow terminal.\n\t\treturn\n\t}\n\n\tif (targetShapeInfo.isExact) {\n\t\t// Exact type binding? The arrowhead point will be at the arrow terminal.\n\t\treturn\n\t}\n\n\t// From and To in page space\n\tconst pageFrom = Mat.applyToPoint(arrowPageTransform, opposite)\n\tconst pageTo = Mat.applyToPoint(arrowPageTransform, point)\n\n\t// From and To in local space of the target shape\n\tconst targetFrom = Mat.applyToPoint(Mat.Inverse(targetShapeInfo.transform), pageFrom)\n\tconst targetTo = Mat.applyToPoint(Mat.Inverse(targetShapeInfo.transform), pageTo)\n\n\tconst intersection = Array.from(\n\t\ttargetShapeInfo.geometry.intersectLineSegment(targetFrom, targetTo, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\t)\n\n\tlet targetInt: VecLike | undefined\n\n\tif (intersection.length) {\n\t\ttargetInt =\n\t\t\tintersection.sort((p1, p2) => Vec.Dist2(p1, targetFrom) - Vec.Dist2(p2, targetFrom))[0] ??\n\t\t\t(targetShapeInfo.isClosed ? undefined : targetTo)\n\t}\n\n\tif (targetInt === undefined) {\n\t\t// No intersection? The arrowhead point will be at the arrow terminal.\n\t\t// if we _almost_ hit the target, just put the arrowhead at the target.\n\t\ttargetInt = targetShapeInfo.geometry.nearestPoint(targetTo, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\n\t\tif (!Vec.DistMin(targetInt, targetTo, 1)) {\n\t\t\treturn\n\t\t}\n\t}\n\n\tconst pageInt = Mat.applyToPoint(targetShapeInfo.transform, targetInt)\n\tconst arrowInt = Mat.applyToPoint(Mat.Inverse(arrowPageTransform), pageInt)\n\n\tpoint.setTo(arrowInt)\n\n\ttargetShapeInfo.didIntersect = true\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAkE;AAClE,qCAA6B;AAE7B,oBASO;AAEA,SAAS,qBACf,QACA,OACA,UACA,kBACc;AACd,QAAM,EAAE,gBAAgB,aAAa,IAAI,MAAM;AAE/C,QAAM,4BAAwB,6CAA8B,QAAQ,OAAO,QAAQ;AAEnF,QAAM,IAAI,sBAAsB,MAAM,MAAM;AAC5C,QAAM,IAAI,sBAAsB,IAAI,MAAM;AAC1C,QAAM,IAAI,kBAAI,IAAI,GAAG,CAAC;AAEtB,MAAI,kBAAI,OAAO,GAAG,CAAC,GAAG;AACrB,WAAO;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,QACN,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,WAAW,MAAM,MAAM;AAAA,MACxB;AAAA,MACA,KAAK;AAAA,QACJ,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,WAAW,MAAM,MAAM;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ;AAAA,IACT;AAAA,EACD;AAEA,QAAM,MAAM,kBAAI,IAAI,GAAG,CAAC,EAAE,IAAI;AAI9B,QAAM,qBAAiB,4CAA6B,QAAQ,OAAO,OAAO;AAC1E,QAAM,mBAAe,4CAA6B,QAAQ,OAAO,KAAK;AAEtE,QAAM,qBAAqB,OAAO,sBAAsB,KAAK;AAG7D;AAAA,IACC;AAAA;AAAA,IACA,sBAAsB;AAAA,IACtB;AAAA,IACA;AAAA,EACD;AAGA;AAAA,IACC;AAAA;AAAA,IACA,sBAAsB;AAAA,IACtB;AAAA,IACA;AAAA,EACD;AAGA,8CAAyB,QAAQ,GAAG,sBAAsB,KAAK,oBAAoB,YAAY;AAC/F;AAAA,IACC;AAAA,IACA;AAAA,IACA,sBAAsB;AAAA,IACtB;AAAA,IACA;AAAA,EACD;AAEA,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,gBAAgB;AACpB,MAAI,gBAAgB;AACpB,MAAI,YAAY,iCAAmB,MAAM,MAAM;AAE/C,QAAM,QAAQ,OAAO,gBAAgB;AACrC,QAAM,UAAU,oBAAoB,MAAM,cAAc,4CAAa,MAAM,MAAM,IAAI;AAErF,QAAM,qBACL,kBAAkB,gBAAgB,eAAe,UAAU,aAAa;AAEzE,QAAM,eACL,kBAAkB,mBACf,0CAA2B,QAAQ,eAAe,MAAM,IAAI,aAAa,MAAM,EAAE,IACjF;AAEJ,MACC,iBAAiB,UACjB,kBACA,gBACA,CAAC,sBACD,CAAC,eAAe,WAChB,CAAC,aAAa,SACb;AACD,QAAI,aAAa,gBAAgB,CAAC,eAAe,cAAc;AAG9D,UAAI,eAAe,UAAU;AAC5B,UAAE,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,MAAM,EAAE,IAAI,iCAAmB,MAAM,MAAM,KAAK,CAAC,CAAC;AAAA,MAC7E;AAAA,IACD,WAAW,CAAC,aAAa,cAAc;AAItC,UAAI,aAAa,UAAU;AAC1B,UAAE,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,MAAM,EAAE,IAAI,iCAAmB,MAAM,MAAM,KAAK,CAAC,CAAC;AAAA,MAC7E;AAAA,IACD;AAAA,EACD;AAEA,QAAM,WAAW,kBAAI,IAAI,GAAG,CAAC;AAE7B,QAAM,IAAI,kBAAI,IAAI,QAAQ,IAAI,SAAS,IAAI,IAAI,kBAAI,KAAK,QAAQ;AAChE,QAAM,UAAU,CAAC,kBAAI,OAAO,GAAG,GAAG;AAIlC,MAAI,CAAC,oBAAoB;AACxB,QACC,iBAAiB,wBACjB,kBACA,mBAAmB,UACnB,CAAC,eAAe,SACf;AACD,sBACC,UAAU,KACT,UAAU,eAAe,MAAM,QAC5B,MAAM,
|
|
4
|
+
"sourcesContent": ["import { Editor, Mat, MatModel, TLArrowShape, Vec, VecLike } from '@tldraw/editor'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { TLArrowInfo } from './arrow-types'\nimport {\n\tBOUND_ARROW_OFFSET,\n\tBoundShapeInfo,\n\tMIN_ARROW_LENGTH,\n\tTLArrowBindings,\n\tclampArrowTerminalToMask,\n\tgetArrowTerminalsInArrowSpace,\n\tgetBoundShapeInfoForTerminal,\n\tgetBoundShapeRelationships,\n} from './shared'\n\nexport function getStraightArrowInfo(\n\teditor: Editor,\n\tshape: TLArrowShape,\n\tbindings: TLArrowBindings,\n\tarrowStrokeWidth?: number\n): TLArrowInfo {\n\tconst { arrowheadStart, arrowheadEnd } = shape.props\n\n\tconst terminalsInArrowSpace = getArrowTerminalsInArrowSpace(editor, shape, bindings)\n\n\tconst a = terminalsInArrowSpace.start.clone()\n\tconst b = terminalsInArrowSpace.end.clone()\n\tconst c = Vec.Med(a, b)\n\n\tif (Vec.Equals(a, b)) {\n\t\treturn {\n\t\t\tbindings,\n\t\t\ttype: 'straight',\n\t\t\tstart: {\n\t\t\t\thandle: a,\n\t\t\t\tpoint: a,\n\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\thandle: b,\n\t\t\t\tpoint: b,\n\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t},\n\t\t\tmiddle: c,\n\t\t\tisValid: false,\n\t\t\tlength: 0,\n\t\t}\n\t}\n\n\tconst uAB = Vec.Sub(b, a).uni()\n\n\t// Update the arrowhead points using intersections with the bound shapes, if any.\n\n\tconst startShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'start')\n\tconst endShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'end')\n\n\tconst arrowPageTransform = editor.getShapePageTransform(shape)!\n\n\t// Update the position of the arrowhead's end point\n\tupdateArrowheadPointWithBoundShape(\n\t\tb, // <-- will be mutated\n\t\tterminalsInArrowSpace.start,\n\t\tarrowPageTransform,\n\t\tendShapeInfo\n\t)\n\n\t// Then update the position of the arrowhead's end point\n\tupdateArrowheadPointWithBoundShape(\n\t\ta, // <-- will be mutated\n\t\tterminalsInArrowSpace.end,\n\t\tarrowPageTransform,\n\t\tstartShapeInfo\n\t)\n\n\t// Clamp terminals to mask boundaries if the bound shape is clipped (e.g. by a frame)\n\tclampArrowTerminalToMask(editor, b, terminalsInArrowSpace.end, arrowPageTransform, endShapeInfo)\n\tclampArrowTerminalToMask(\n\t\teditor,\n\t\ta,\n\t\tterminalsInArrowSpace.start,\n\t\tarrowPageTransform,\n\t\tstartShapeInfo\n\t)\n\n\tlet offsetA = 0\n\tlet offsetB = 0\n\tlet strokeOffsetA = 0\n\tlet strokeOffsetB = 0\n\tlet minLength = MIN_ARROW_LENGTH * shape.props.scale\n\n\tconst theme = editor.getCurrentTheme()\n\tconst arrowSW = arrowStrokeWidth ?? theme.strokeWidth * STROKE_SIZES[shape.props.size]\n\n\tconst isSelfIntersection =\n\t\tstartShapeInfo && endShapeInfo && startShapeInfo.shape === endShapeInfo.shape\n\n\tconst relationship =\n\t\tstartShapeInfo && endShapeInfo\n\t\t\t? getBoundShapeRelationships(editor, startShapeInfo.shape.id, endShapeInfo.shape.id)\n\t\t\t: 'safe'\n\n\tif (\n\t\trelationship === 'safe' &&\n\t\tstartShapeInfo &&\n\t\tendShapeInfo &&\n\t\t!isSelfIntersection &&\n\t\t!startShapeInfo.isExact &&\n\t\t!endShapeInfo.isExact\n\t) {\n\t\tif (endShapeInfo.didIntersect && !startShapeInfo.didIntersect) {\n\t\t\t// ...and if only the end shape intersected, then make it\n\t\t\t// a short arrow ending at the end shape intersection.\n\t\t\tif (startShapeInfo.isClosed) {\n\t\t\t\ta.setTo(b.clone().add(uAB.clone().mul(MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t\t}\n\t\t} else if (!endShapeInfo.didIntersect) {\n\t\t\t// ...and if only the end shape intersected, or if neither\n\t\t\t// shape intersected, then make it a short arrow starting\n\t\t\t// at the start shape intersection.\n\t\t\tif (endShapeInfo.isClosed) {\n\t\t\t\tb.setTo(a.clone().sub(uAB.clone().mul(MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t\t}\n\t\t}\n\t}\n\n\tconst distance = Vec.Sub(b, a)\n\t// Check for divide-by-zero before we call uni()\n\tconst u = Vec.Len(distance) ? distance.uni() : Vec.From(distance)\n\tconst didFlip = !Vec.Equals(u, uAB)\n\n\t// If the arrow is bound non-exact to a start shape and the\n\t// start point has an arrowhead, then offset the start point\n\tif (!isSelfIntersection) {\n\t\tif (\n\t\t\trelationship !== 'start-contains-end' &&\n\t\t\tstartShapeInfo &&\n\t\t\tarrowheadStart !== 'none' &&\n\t\t\t!startShapeInfo.isExact\n\t\t) {\n\t\t\tstrokeOffsetA =\n\t\t\t\tarrowSW / 2 +\n\t\t\t\t('size' in startShapeInfo.shape.props\n\t\t\t\t\t? (theme.strokeWidth * (STROKE_SIZES[startShapeInfo.shape.props.size] ?? 0)) / 2\n\t\t\t\t\t: 0)\n\t\t\toffsetA = (BOUND_ARROW_OFFSET + strokeOffsetA) * shape.props.scale\n\t\t\tminLength += strokeOffsetA * shape.props.scale\n\t\t}\n\n\t\t// If the arrow is bound non-exact to an end shape and the\n\t\t// end point has an arrowhead offset the end point\n\t\tif (\n\t\t\trelationship !== 'end-contains-start' &&\n\t\t\tendShapeInfo &&\n\t\t\tarrowheadEnd !== 'none' &&\n\t\t\t!endShapeInfo.isExact\n\t\t) {\n\t\t\tstrokeOffsetB =\n\t\t\t\tarrowSW / 2 +\n\t\t\t\t('size' in endShapeInfo.shape.props\n\t\t\t\t\t? (theme.strokeWidth * (STROKE_SIZES[endShapeInfo.shape.props.size] ?? 0)) / 2\n\t\t\t\t\t: 0)\n\t\t\toffsetB = (BOUND_ARROW_OFFSET + strokeOffsetB) * shape.props.scale\n\t\t\tminLength += strokeOffsetB * shape.props.scale\n\t\t}\n\t}\n\n\t// Adjust offsets if the length of the arrow is too small\n\n\tconst tA = a.clone().add(u.clone().mul(offsetA * (didFlip ? -1 : 1)))\n\tconst tB = b.clone().sub(u.clone().mul(offsetB * (didFlip ? -1 : 1)))\n\n\tif (Vec.DistMin(tA, tB, minLength)) {\n\t\tif (offsetA !== 0 && offsetB !== 0) {\n\t\t\t// both bound + offset\n\t\t\toffsetA *= -1.5\n\t\t\toffsetB *= -1.5\n\t\t} else if (offsetA !== 0) {\n\t\t\t// start bound + offset\n\t\t\toffsetA *= -1\n\t\t} else if (offsetB !== 0) {\n\t\t\t// end bound + offset\n\t\t\toffsetB *= -1\n\t\t} else {\n\t\t\t// noop, its just a really short arrow\n\t\t}\n\t}\n\n\ta.add(u.clone().mul(offsetA * (didFlip ? -1 : 1)))\n\tb.sub(u.clone().mul(offsetB * (didFlip ? -1 : 1)))\n\n\t// If the handles flipped their order, then set the center handle\n\t// to the midpoint of the terminals (rather than the midpoint of the\n\t// arrow body); otherwise, it may not be \"between\" the other terminals.\n\tif (didFlip) {\n\t\tif (startShapeInfo && endShapeInfo) {\n\t\t\t// If we have two bound shapes...then make the arrow a short arrow from\n\t\t\t// the start point towards where the end point should be.\n\t\t\tb.setTo(Vec.Add(a, u.clone().mul(-MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t}\n\t\tc.setTo(Vec.Med(terminalsInArrowSpace.start, terminalsInArrowSpace.end))\n\t} else {\n\t\tc.setTo(Vec.Med(a, b))\n\t}\n\n\tconst length = Vec.Dist(a, b)\n\n\treturn {\n\t\tbindings,\n\t\ttype: 'straight',\n\t\tstart: {\n\t\t\thandle: terminalsInArrowSpace.start,\n\t\t\tpoint: a,\n\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t},\n\t\tend: {\n\t\t\thandle: terminalsInArrowSpace.end,\n\t\t\tpoint: b,\n\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t},\n\t\tmiddle: c,\n\t\tisValid: length > 0,\n\t\tlength,\n\t}\n}\n\n/** Get an intersection point from A -> B with bound shape (target) from shape (arrow). */\nfunction updateArrowheadPointWithBoundShape(\n\tpoint: Vec,\n\topposite: Vec,\n\tarrowPageTransform: MatModel,\n\ttargetShapeInfo?: BoundShapeInfo\n) {\n\tif (targetShapeInfo === undefined) {\n\t\t// No bound shape? The arrowhead point will be at the arrow terminal.\n\t\treturn\n\t}\n\n\tif (targetShapeInfo.isExact) {\n\t\t// Exact type binding? The arrowhead point will be at the arrow terminal.\n\t\treturn\n\t}\n\n\t// From and To in page space\n\tconst pageFrom = Mat.applyToPoint(arrowPageTransform, opposite)\n\tconst pageTo = Mat.applyToPoint(arrowPageTransform, point)\n\n\t// From and To in local space of the target shape\n\tconst targetFrom = Mat.applyToPoint(Mat.Inverse(targetShapeInfo.transform), pageFrom)\n\tconst targetTo = Mat.applyToPoint(Mat.Inverse(targetShapeInfo.transform), pageTo)\n\n\tconst intersection = Array.from(\n\t\ttargetShapeInfo.geometry.intersectLineSegment(targetFrom, targetTo, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\t)\n\n\tlet targetInt: VecLike | undefined\n\n\tif (intersection.length) {\n\t\ttargetInt =\n\t\t\tintersection.sort((p1, p2) => Vec.Dist2(p1, targetFrom) - Vec.Dist2(p2, targetFrom))[0] ??\n\t\t\t(targetShapeInfo.isClosed ? undefined : targetTo)\n\t}\n\n\tif (targetInt === undefined) {\n\t\t// No intersection? The arrowhead point will be at the arrow terminal.\n\t\t// if we _almost_ hit the target, just put the arrowhead at the target.\n\t\ttargetInt = targetShapeInfo.geometry.nearestPoint(targetTo, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\n\t\tif (!Vec.DistMin(targetInt, targetTo, 1)) {\n\t\t\treturn\n\t\t}\n\t}\n\n\tconst pageInt = Mat.applyToPoint(targetShapeInfo.transform, targetInt)\n\tconst arrowInt = Mat.applyToPoint(Mat.Inverse(arrowPageTransform), pageInt)\n\n\tpoint.setTo(arrowInt)\n\n\ttargetShapeInfo.didIntersect = true\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAkE;AAClE,qCAA6B;AAE7B,oBASO;AAEA,SAAS,qBACf,QACA,OACA,UACA,kBACc;AACd,QAAM,EAAE,gBAAgB,aAAa,IAAI,MAAM;AAE/C,QAAM,4BAAwB,6CAA8B,QAAQ,OAAO,QAAQ;AAEnF,QAAM,IAAI,sBAAsB,MAAM,MAAM;AAC5C,QAAM,IAAI,sBAAsB,IAAI,MAAM;AAC1C,QAAM,IAAI,kBAAI,IAAI,GAAG,CAAC;AAEtB,MAAI,kBAAI,OAAO,GAAG,CAAC,GAAG;AACrB,WAAO;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,QACN,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,WAAW,MAAM,MAAM;AAAA,MACxB;AAAA,MACA,KAAK;AAAA,QACJ,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,WAAW,MAAM,MAAM;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ;AAAA,IACT;AAAA,EACD;AAEA,QAAM,MAAM,kBAAI,IAAI,GAAG,CAAC,EAAE,IAAI;AAI9B,QAAM,qBAAiB,4CAA6B,QAAQ,OAAO,OAAO;AAC1E,QAAM,mBAAe,4CAA6B,QAAQ,OAAO,KAAK;AAEtE,QAAM,qBAAqB,OAAO,sBAAsB,KAAK;AAG7D;AAAA,IACC;AAAA;AAAA,IACA,sBAAsB;AAAA,IACtB;AAAA,IACA;AAAA,EACD;AAGA;AAAA,IACC;AAAA;AAAA,IACA,sBAAsB;AAAA,IACtB;AAAA,IACA;AAAA,EACD;AAGA,8CAAyB,QAAQ,GAAG,sBAAsB,KAAK,oBAAoB,YAAY;AAC/F;AAAA,IACC;AAAA,IACA;AAAA,IACA,sBAAsB;AAAA,IACtB;AAAA,IACA;AAAA,EACD;AAEA,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,gBAAgB;AACpB,MAAI,gBAAgB;AACpB,MAAI,YAAY,iCAAmB,MAAM,MAAM;AAE/C,QAAM,QAAQ,OAAO,gBAAgB;AACrC,QAAM,UAAU,oBAAoB,MAAM,cAAc,4CAAa,MAAM,MAAM,IAAI;AAErF,QAAM,qBACL,kBAAkB,gBAAgB,eAAe,UAAU,aAAa;AAEzE,QAAM,eACL,kBAAkB,mBACf,0CAA2B,QAAQ,eAAe,MAAM,IAAI,aAAa,MAAM,EAAE,IACjF;AAEJ,MACC,iBAAiB,UACjB,kBACA,gBACA,CAAC,sBACD,CAAC,eAAe,WAChB,CAAC,aAAa,SACb;AACD,QAAI,aAAa,gBAAgB,CAAC,eAAe,cAAc;AAG9D,UAAI,eAAe,UAAU;AAC5B,UAAE,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,MAAM,EAAE,IAAI,iCAAmB,MAAM,MAAM,KAAK,CAAC,CAAC;AAAA,MAC7E;AAAA,IACD,WAAW,CAAC,aAAa,cAAc;AAItC,UAAI,aAAa,UAAU;AAC1B,UAAE,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,MAAM,EAAE,IAAI,iCAAmB,MAAM,MAAM,KAAK,CAAC,CAAC;AAAA,MAC7E;AAAA,IACD;AAAA,EACD;AAEA,QAAM,WAAW,kBAAI,IAAI,GAAG,CAAC;AAE7B,QAAM,IAAI,kBAAI,IAAI,QAAQ,IAAI,SAAS,IAAI,IAAI,kBAAI,KAAK,QAAQ;AAChE,QAAM,UAAU,CAAC,kBAAI,OAAO,GAAG,GAAG;AAIlC,MAAI,CAAC,oBAAoB;AACxB,QACC,iBAAiB,wBACjB,kBACA,mBAAmB,UACnB,CAAC,eAAe,SACf;AACD,sBACC,UAAU,KACT,UAAU,eAAe,MAAM,QAC5B,MAAM,eAAe,4CAAa,eAAe,MAAM,MAAM,IAAI,KAAK,KAAM,IAC7E;AACJ,iBAAW,mCAAqB,iBAAiB,MAAM,MAAM;AAC7D,mBAAa,gBAAgB,MAAM,MAAM;AAAA,IAC1C;AAIA,QACC,iBAAiB,wBACjB,gBACA,iBAAiB,UACjB,CAAC,aAAa,SACb;AACD,sBACC,UAAU,KACT,UAAU,aAAa,MAAM,QAC1B,MAAM,eAAe,4CAAa,aAAa,MAAM,MAAM,IAAI,KAAK,KAAM,IAC3E;AACJ,iBAAW,mCAAqB,iBAAiB,MAAM,MAAM;AAC7D,mBAAa,gBAAgB,MAAM,MAAM;AAAA,IAC1C;AAAA,EACD;AAIA,QAAM,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,WAAW,UAAU,KAAK,EAAE,CAAC;AACpE,QAAM,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,WAAW,UAAU,KAAK,EAAE,CAAC;AAEpE,MAAI,kBAAI,QAAQ,IAAI,IAAI,SAAS,GAAG;AACnC,QAAI,YAAY,KAAK,YAAY,GAAG;AAEnC,iBAAW;AACX,iBAAW;AAAA,IACZ,WAAW,YAAY,GAAG;AAEzB,iBAAW;AAAA,IACZ,WAAW,YAAY,GAAG;AAEzB,iBAAW;AAAA,IACZ,OAAO;AAAA,IAEP;AAAA,EACD;AAEA,IAAE,IAAI,EAAE,MAAM,EAAE,IAAI,WAAW,UAAU,KAAK,EAAE,CAAC;AACjD,IAAE,IAAI,EAAE,MAAM,EAAE,IAAI,WAAW,UAAU,KAAK,EAAE,CAAC;AAKjD,MAAI,SAAS;AACZ,QAAI,kBAAkB,cAAc;AAGnC,QAAE,MAAM,kBAAI,IAAI,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,iCAAmB,MAAM,MAAM,KAAK,CAAC,CAAC;AAAA,IACzE;AACA,MAAE,MAAM,kBAAI,IAAI,sBAAsB,OAAO,sBAAsB,GAAG,CAAC;AAAA,EACxE,OAAO;AACN,MAAE,MAAM,kBAAI,IAAI,GAAG,CAAC,CAAC;AAAA,EACtB;AAEA,QAAM,SAAS,kBAAI,KAAK,GAAG,CAAC;AAE5B,SAAO;AAAA,IACN;AAAA,IACA,MAAM;AAAA,IACN,OAAO;AAAA,MACN,QAAQ,sBAAsB;AAAA,MAC9B,OAAO;AAAA,MACP,WAAW,MAAM,MAAM;AAAA,IACxB;AAAA,IACA,KAAK;AAAA,MACJ,QAAQ,sBAAsB;AAAA,MAC9B,OAAO;AAAA,MACP,WAAW,MAAM,MAAM;AAAA,IACxB;AAAA,IACA,QAAQ;AAAA,IACR,SAAS,SAAS;AAAA,IAClB;AAAA,EACD;AACD;AAGA,SAAS,mCACR,OACA,UACA,oBACA,iBACC;AACD,MAAI,oBAAoB,QAAW;AAElC;AAAA,EACD;AAEA,MAAI,gBAAgB,SAAS;AAE5B;AAAA,EACD;AAGA,QAAM,WAAW,kBAAI,aAAa,oBAAoB,QAAQ;AAC9D,QAAM,SAAS,kBAAI,aAAa,oBAAoB,KAAK;AAGzD,QAAM,aAAa,kBAAI,aAAa,kBAAI,QAAQ,gBAAgB,SAAS,GAAG,QAAQ;AACpF,QAAM,WAAW,kBAAI,aAAa,kBAAI,QAAQ,gBAAgB,SAAS,GAAG,MAAM;AAEhF,QAAM,eAAe,MAAM;AAAA,IAC1B,gBAAgB,SAAS,qBAAqB,YAAY,UAAU;AAAA,MACnE,eAAe;AAAA,MACf,iBAAiB;AAAA,IAClB,CAAC;AAAA,EACF;AAEA,MAAI;AAEJ,MAAI,aAAa,QAAQ;AACxB,gBACC,aAAa,KAAK,CAAC,IAAI,OAAO,kBAAI,MAAM,IAAI,UAAU,IAAI,kBAAI,MAAM,IAAI,UAAU,CAAC,EAAE,CAAC,MACrF,gBAAgB,WAAW,SAAY;AAAA,EAC1C;AAEA,MAAI,cAAc,QAAW;AAG5B,gBAAY,gBAAgB,SAAS,aAAa,UAAU;AAAA,MAC3D,eAAe;AAAA,MACf,iBAAiB;AAAA,IAClB,CAAC;AAED,QAAI,CAAC,kBAAI,QAAQ,WAAW,UAAU,CAAC,GAAG;AACzC;AAAA,IACD;AAAA,EACD;AAEA,QAAM,UAAU,kBAAI,aAAa,gBAAgB,WAAW,SAAS;AACrE,QAAM,WAAW,kBAAI,aAAa,kBAAI,QAAQ,kBAAkB,GAAG,OAAO;AAE1E,QAAM,MAAM,QAAQ;AAEpB,kBAAgB,eAAe;AAChC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -55,9 +55,8 @@ class Idle extends import_editor.StateNode {
|
|
|
55
55
|
this.update();
|
|
56
56
|
if (info.key === "Enter") {
|
|
57
57
|
const onlySelectedShape = this.editor.getOnlySelectedShape();
|
|
58
|
-
if (this.editor.canEditShape(onlySelectedShape))
|
|
59
|
-
|
|
60
|
-
}
|
|
58
|
+
if (!this.editor.canEditShape(onlySelectedShape)) return;
|
|
59
|
+
(0, import_selectHelpers.startEditingShape)(this.editor, onlySelectedShape, { selectAll: true });
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
update() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/arrow/toolStates/Idle.tsx"],
|
|
4
|
-
"sourcesContent": ["import { StateNode, TLKeyboardEventInfo, TLPointerEventInfo, TLShapeId } from '@tldraw/editor'\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA8E;AAC9E,
|
|
4
|
+
"sourcesContent": ["import { StateNode, TLKeyboardEventInfo, TLPointerEventInfo, TLShapeId } from '@tldraw/editor'\nimport { startEditingShape } from '../../../tools/SelectTool/selectHelpers'\nimport { ArrowShapeUtil } from '../ArrowShapeUtil'\nimport { clearArrowTargetState, updateArrowTargetState } from '../arrowTargetState'\n\nexport class Idle extends StateNode {\n\tstatic override id = 'idle'\n\n\tisPrecise = false\n\tisPreciseTimerId: number | null = null\n\tpreciseTargetId: TLShapeId | null = null\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerDown(info: TLPointerEventInfo) {\n\t\tthis.parent.transition('pointing', { ...info, isPrecise: this.isPrecise })\n\t}\n\n\toverride onEnter() {\n\t\tthis.editor.setCursor({ type: 'cross', rotation: 0 })\n\t\tthis.update()\n\t}\n\n\toverride onCancel() {\n\t\tthis.editor.setCurrentTool('select')\n\t}\n\n\toverride onExit() {\n\t\tclearArrowTargetState(this.editor)\n\t\tif (this.isPreciseTimerId !== null) {\n\t\t\tclearTimeout(this.isPreciseTimerId)\n\t\t}\n\t}\n\n\toverride onKeyDown() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyUp(info: TLKeyboardEventInfo) {\n\t\tthis.update()\n\t\tif (info.key === 'Enter') {\n\t\t\tconst onlySelectedShape = this.editor.getOnlySelectedShape()\n\t\t\tif (!this.editor.canEditShape(onlySelectedShape)) return\n\t\t\tstartEditingShape(this.editor, onlySelectedShape, { selectAll: true })\n\t\t}\n\t}\n\n\tupdate() {\n\t\tconst arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')\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 && targetState.target.id !== this.preciseTargetId) {\n\t\t\tif (this.isPreciseTimerId !== null) {\n\t\t\t\tclearTimeout(this.isPreciseTimerId)\n\t\t\t}\n\n\t\t\tthis.preciseTargetId = targetState.target.id\n\t\t\tthis.isPreciseTimerId = this.editor.timers.setTimeout(() => {\n\t\t\t\tthis.isPrecise = true\n\t\t\t\tthis.update()\n\t\t\t}, arrowUtil.options.hoverPreciseTimeout)\n\t\t} else if (!targetState && this.preciseTargetId) {\n\t\t\tthis.isPrecise = false\n\t\t\tthis.preciseTargetId = null\n\t\t\tif (this.isPreciseTimerId !== null) {\n\t\t\t\tclearTimeout(this.isPreciseTimerId)\n\t\t\t}\n\t\t}\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA8E;AAC9E,2BAAkC;AAElC,8BAA8D;AAEvD,MAAM,aAAa,wBAAU;AAAA,EACnC,OAAgB,KAAK;AAAA,EAErB,YAAY;AAAA,EACZ,mBAAkC;AAAA,EAClC,kBAAoC;AAAA,EAE3B,gBAAgB;AACxB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,cAAc,MAA0B;AAChD,SAAK,OAAO,WAAW,YAAY,EAAE,GAAG,MAAM,WAAW,KAAK,UAAU,CAAC;AAAA,EAC1E;AAAA,EAES,UAAU;AAClB,SAAK,OAAO,UAAU,EAAE,MAAM,SAAS,UAAU,EAAE,CAAC;AACpD,SAAK,OAAO;AAAA,EACb;AAAA,EAES,WAAW;AACnB,SAAK,OAAO,eAAe,QAAQ;AAAA,EACpC;AAAA,EAES,SAAS;AACjB,uDAAsB,KAAK,MAAM;AACjC,QAAI,KAAK,qBAAqB,MAAM;AACnC,mBAAa,KAAK,gBAAgB;AAAA,IACnC;AAAA,EACD;AAAA,EAES,YAAY;AACpB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,QAAQ,MAA2B;AAC3C,SAAK,OAAO;AACZ,QAAI,KAAK,QAAQ,SAAS;AACzB,YAAM,oBAAoB,KAAK,OAAO,qBAAqB;AAC3D,UAAI,CAAC,KAAK,OAAO,aAAa,iBAAiB,EAAG;AAClD,kDAAkB,KAAK,QAAQ,mBAAmB,EAAE,WAAW,KAAK,CAAC;AAAA,IACtE;AAAA,EACD;AAAA,EAEA,SAAS;AACR,UAAM,YAAY,KAAK,OAAO,aAA6B,OAAO;AAElE,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,eAAe,YAAY,OAAO,OAAO,KAAK,iBAAiB;AAClE,UAAI,KAAK,qBAAqB,MAAM;AACnC,qBAAa,KAAK,gBAAgB;AAAA,MACnC;AAEA,WAAK,kBAAkB,YAAY,OAAO;AAC1C,WAAK,mBAAmB,KAAK,OAAO,OAAO,WAAW,MAAM;AAC3D,aAAK,YAAY;AACjB,aAAK,OAAO;AAAA,MACb,GAAG,UAAU,QAAQ,mBAAmB;AAAA,IACzC,WAAW,CAAC,eAAe,KAAK,iBAAiB;AAChD,WAAK,YAAY;AACjB,WAAK,kBAAkB;AACvB,UAAI,KAAK,qBAAqB,MAAM;AACnC,qBAAa,KAAK,gBAAgB;AAAA,MACnC;AAAA,IACD;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -50,7 +50,10 @@ class Pointing extends import_editor.StateNode {
|
|
|
50
50
|
this.startPreciseTimeout();
|
|
51
51
|
}
|
|
52
52
|
onExit() {
|
|
53
|
-
this.shape
|
|
53
|
+
if (this.shape) {
|
|
54
|
+
this.editor.bailToMark(this.markId);
|
|
55
|
+
this.shape = void 0;
|
|
56
|
+
}
|
|
54
57
|
(0, import_arrowTargetState.clearArrowTargetState)(this.editor);
|
|
55
58
|
this.clearPreciseTimeout();
|
|
56
59
|
}
|
|
@@ -64,8 +67,10 @@ class Pointing extends import_editor.StateNode {
|
|
|
64
67
|
return;
|
|
65
68
|
}
|
|
66
69
|
this.updateArrowShapeEndHandle();
|
|
70
|
+
const shape = this.shape;
|
|
71
|
+
this.shape = void 0;
|
|
67
72
|
this.editor.setCurrentTool("select.dragging_handle", {
|
|
68
|
-
shape
|
|
73
|
+
shape,
|
|
69
74
|
handle: { id: "end", type: "vertex", index: "a3", x: 0, y: 0 },
|
|
70
75
|
isCreating: true,
|
|
71
76
|
creatingMarkId: this.markId || void 0,
|
|
@@ -89,9 +94,6 @@ class Pointing extends import_editor.StateNode {
|
|
|
89
94
|
this.cancel();
|
|
90
95
|
}
|
|
91
96
|
cancel() {
|
|
92
|
-
if (this.shape) {
|
|
93
|
-
this.editor.bailToMark(this.markId);
|
|
94
|
-
}
|
|
95
97
|
this.parent.transition("idle");
|
|
96
98
|
}
|
|
97
99
|
createArrowShape() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/arrow/toolStates/Pointing.tsx"],
|
|
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
|
|
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;
|
|
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\t// The press already created the arrow, so leaving without a drag (pointer up, cancel, or a\n\t\t// tool switch) would otherwise strand a zero-length stub on the canvas\n\t\tif (this.shape) {\n\t\t\tthis.editor.bailToMark(this.markId)\n\t\t\tthis.shape = undefined\n\t\t}\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\t// Hand the arrow off before exiting so onExit does not bail it away\n\t\t\tconst shape = this.shape\n\t\t\tthis.shape = undefined\n\t\t\tthis.editor.setCurrentTool('select.dragging_handle', {\n\t\t\t\tshape,\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\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": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -159,7 +159,7 @@ class Drawing extends import_editor.StateNode {
|
|
|
159
159
|
this.lastRecordedPoint = originPagePoint.clone();
|
|
160
160
|
if (this.initialShape) {
|
|
161
161
|
const shape2 = this.editor.getShape(this.initialShape.id);
|
|
162
|
-
if (shape2 && this.segmentMode === "straight") {
|
|
162
|
+
if (shape2 && this.segmentMode === "straight" && this.editor.isShapeInPage(shape2)) {
|
|
163
163
|
this.didJustShiftClickToExtendPreviousShapeLine = true;
|
|
164
164
|
const prevSegment = (0, import_editor.last)(shape2.props.segments);
|
|
165
165
|
if (!prevSegment) throw Error("Expected a previous segment!");
|
|
@@ -244,7 +244,8 @@ class Drawing extends import_editor.StateNode {
|
|
|
244
244
|
if (pagePointWhereNextSegmentChanged === null) {
|
|
245
245
|
throw Error("We should have a point where the segment changed");
|
|
246
246
|
}
|
|
247
|
-
const
|
|
247
|
+
const zoom = this.editor.getZoomLevel();
|
|
248
|
+
const hasMovedFarEnough = import_editor.Vec.Dist2(pagePointWhereNextSegmentChanged, inputs.getCurrentPagePoint()) * zoom * zoom > this.editor.options.dragDistanceSquared;
|
|
248
249
|
if (hasMovedFarEnough) {
|
|
249
250
|
this.pagePointWhereCurrentSegmentChanged = this.pagePointWhereNextSegmentChanged.clone();
|
|
250
251
|
this.pagePointWhereNextSegmentChanged = null;
|
|
@@ -287,7 +288,8 @@ class Drawing extends import_editor.StateNode {
|
|
|
287
288
|
if (pagePointWhereNextSegmentChanged === null) {
|
|
288
289
|
throw Error("We should have a point where the segment changed");
|
|
289
290
|
}
|
|
290
|
-
const
|
|
291
|
+
const zoom = this.editor.getZoomLevel();
|
|
292
|
+
const hasMovedFarEnough = import_editor.Vec.Dist2(pagePointWhereNextSegmentChanged, inputs.getCurrentPagePoint()) * zoom * zoom > this.editor.options.dragDistanceSquared;
|
|
291
293
|
if (hasMovedFarEnough) {
|
|
292
294
|
this.pagePointWhereCurrentSegmentChanged = this.pagePointWhereNextSegmentChanged.clone();
|
|
293
295
|
this.pagePointWhereNextSegmentChanged = null;
|
|
@@ -487,7 +489,7 @@ class Drawing extends import_editor.StateNode {
|
|
|
487
489
|
const props = this.editor.getShape(id).props;
|
|
488
490
|
if (!this.editor.canCreateShapes([newShapeId])) return this.cancel();
|
|
489
491
|
const currentPagePoint2 = inputs.getCurrentPagePoint();
|
|
490
|
-
const initialPoint = new import_editor.Vec(0, 0, this.isPenOrStylus ? +(z * 1.25).toFixed() : 0.5);
|
|
492
|
+
const initialPoint = new import_editor.Vec(0, 0, this.isPenOrStylus ? +(z * 1.25).toFixed(2) : 0.5);
|
|
491
493
|
this.currentSegmentPoints = [initialPoint];
|
|
492
494
|
this.editor.createShape({
|
|
493
495
|
id: newShapeId,
|
|
@@ -518,10 +520,10 @@ class Drawing extends import_editor.StateNode {
|
|
|
518
520
|
for (let j = 0; j < segments.length; j++) {
|
|
519
521
|
const points = import_editor.b64Vecs.decodePoints(segments[j].path, segments[j].dim);
|
|
520
522
|
for (let i = 0; i < points.length - 1; i++) {
|
|
521
|
-
length += import_editor.Vec.
|
|
523
|
+
length += import_editor.Vec.Dist(points[i], points[i + 1]);
|
|
522
524
|
}
|
|
523
525
|
}
|
|
524
|
-
return
|
|
526
|
+
return length;
|
|
525
527
|
}
|
|
526
528
|
onPointerUp() {
|
|
527
529
|
this.complete();
|