@excalidraw/excalidraw 0.17.1-88812e0 → 0.17.1-96eeec5
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/CHANGELOG.md +2 -0
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-47LVF2XL.js → chunk-DEYXWPUO.js} +4933 -1520
- package/dist/browser/dev/excalidraw-assets-dev/chunk-DEYXWPUO.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-XOM7LNOU.js → chunk-EM6LVGFW.js} +27 -4
- package/dist/browser/dev/excalidraw-assets-dev/chunk-EM6LVGFW.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{dist-ITJNUBZF.js → dist-6QVAH5JA.js} +36 -14
- package/dist/browser/dev/excalidraw-assets-dev/dist-6QVAH5JA.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{en-TR4QLF5E.js → en-AZFA5HJJ.js} +4 -2
- package/dist/browser/dev/excalidraw-assets-dev/{image-LHMGJWTI.js → image-5XCR4WHS.js} +2 -2
- package/dist/browser/dev/index.css +157 -62
- package/dist/browser/dev/index.css.map +3 -3
- package/dist/browser/dev/index.js +12016 -7663
- package/dist/browser/dev/index.js.map +4 -4
- package/dist/browser/prod/excalidraw-assets/{chunk-5SYIAZGL.js → chunk-7DXALCB2.js} +5 -5
- package/dist/browser/prod/excalidraw-assets/chunk-ODWTVSS7.js +68 -0
- package/dist/browser/prod/excalidraw-assets/dist-567JAXHK.js +7 -0
- package/dist/browser/prod/excalidraw-assets/en-6E7MYLWO.js +1 -0
- package/dist/browser/prod/excalidraw-assets/image-LQAMCFQI.js +1 -0
- package/dist/browser/prod/index.css +1 -1
- package/dist/browser/prod/index.js +69 -51
- package/dist/dev/{en-XW4JO6VX.json → en-EB2MBPAV.json} +24 -3
- package/dist/dev/index.css +157 -62
- package/dist/dev/index.css.map +3 -3
- package/dist/dev/index.js +18250 -16114
- package/dist/dev/index.js.map +4 -4
- package/dist/excalidraw/actions/actionAddToLibrary.d.ts +15 -6
- package/dist/excalidraw/actions/actionAlign.d.ts +8 -8
- package/dist/excalidraw/actions/actionBoundText.d.ts +14 -8
- package/dist/excalidraw/actions/actionBoundText.js +3 -1
- package/dist/excalidraw/actions/actionCanvas.d.ts +64 -28
- package/dist/excalidraw/actions/actionCanvas.js +1 -1
- package/dist/excalidraw/actions/actionClipboard.d.ts +40 -19
- package/dist/excalidraw/actions/actionDeleteSelected.d.ts +17 -8
- package/dist/excalidraw/actions/actionDistribute.d.ts +4 -4
- package/dist/excalidraw/actions/actionDuplicateSelection.d.ts +3 -3
- package/dist/excalidraw/actions/actionElementLock.d.ts +11 -5
- package/dist/excalidraw/actions/actionExport.d.ts +48 -21
- package/dist/excalidraw/actions/actionFinalize.d.ts +11 -5
- package/dist/excalidraw/actions/actionFinalize.js +1 -1
- package/dist/excalidraw/actions/actionFlip.d.ts +4 -4
- package/dist/excalidraw/actions/actionFlip.js +5 -6
- package/dist/excalidraw/actions/actionFrame.d.ts +328 -8
- package/dist/excalidraw/actions/actionGroup.d.ts +320 -4
- package/dist/excalidraw/actions/actionHistory.d.ts +3 -3
- package/dist/excalidraw/actions/actionHistory.js +4 -4
- package/dist/excalidraw/actions/actionLinearEditor.d.ts +9 -4
- package/dist/excalidraw/actions/actionLinearEditor.js +19 -4
- package/dist/excalidraw/actions/actionLink.d.ts +5 -2
- package/dist/excalidraw/actions/actionMenu.d.ts +15 -6
- package/dist/excalidraw/actions/actionNavigate.d.ts +11 -5
- package/dist/excalidraw/actions/actionProperties.d.ts +67 -28
- package/dist/excalidraw/actions/actionProperties.js +1 -1
- package/dist/excalidraw/actions/actionSelectAll.d.ts +6 -3
- package/dist/excalidraw/actions/actionStyles.d.ts +9 -3
- package/dist/excalidraw/actions/actionTextAutoResize.d.ts +17 -0
- package/dist/excalidraw/actions/actionTextAutoResize.js +38 -0
- package/dist/excalidraw/actions/actionToggleGridMode.d.ts +6 -3
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +5 -2
- package/dist/excalidraw/actions/actionToggleStats.d.ts +6 -2
- package/dist/excalidraw/actions/actionToggleStats.js +4 -3
- package/dist/excalidraw/actions/actionToggleViewMode.d.ts +5 -2
- package/dist/excalidraw/actions/actionToggleZenMode.d.ts +5 -2
- package/dist/excalidraw/actions/actionZindex.d.ts +8 -4
- package/dist/excalidraw/actions/actionZindex.js +4 -0
- package/dist/excalidraw/actions/manager.d.ts +3 -3
- package/dist/excalidraw/actions/register.d.ts +1 -1
- package/dist/excalidraw/actions/shortcuts.d.ts +2 -2
- package/dist/excalidraw/actions/types.d.ts +6 -6
- package/dist/excalidraw/align.d.ts +1 -1
- package/dist/excalidraw/animated-trail.d.ts +2 -2
- package/dist/excalidraw/appState.d.ts +5 -2
- package/dist/excalidraw/appState.js +6 -3
- package/dist/excalidraw/change.d.ts +4 -4
- package/dist/excalidraw/change.js +14 -7
- package/dist/excalidraw/charts.d.ts +1 -1
- package/dist/excalidraw/clients.d.ts +2 -2
- package/dist/excalidraw/clients.js +1 -1
- package/dist/excalidraw/clipboard.d.ts +3 -3
- package/dist/excalidraw/colors.d.ts +1 -1
- package/dist/excalidraw/components/Actions.d.ts +3 -3
- package/dist/excalidraw/components/Actions.js +9 -6
- package/dist/excalidraw/components/App.d.ts +10 -16
- package/dist/excalidraw/components/App.js +190 -142
- package/dist/excalidraw/components/ButtonIconSelect.js +1 -1
- package/dist/excalidraw/components/CheckboxItem.js +1 -1
- package/dist/excalidraw/components/ColorPicker/ColorInput.d.ts +1 -1
- package/dist/excalidraw/components/ColorPicker/ColorInput.js +1 -1
- package/dist/excalidraw/components/ColorPicker/ColorPicker.d.ts +4 -4
- package/dist/excalidraw/components/ColorPicker/ColorPicker.js +1 -1
- package/dist/excalidraw/components/ColorPicker/Picker.d.ts +3 -3
- package/dist/excalidraw/components/ColorPicker/PickerColorList.d.ts +1 -1
- package/dist/excalidraw/components/ColorPicker/PickerHeading.d.ts +1 -1
- package/dist/excalidraw/components/ColorPicker/ShadeList.d.ts +1 -1
- package/dist/excalidraw/components/ColorPicker/TopPicks.d.ts +1 -1
- package/dist/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +2 -2
- package/dist/excalidraw/components/ColorPicker/colorPickerUtils.js +1 -1
- package/dist/excalidraw/components/ColorPicker/keyboardNavHandlers.d.ts +2 -2
- package/dist/excalidraw/components/ColorPicker/keyboardNavHandlers.js +1 -1
- package/dist/excalidraw/components/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/excalidraw/components/CommandPalette/CommandPalette.js +5 -5
- package/dist/excalidraw/components/CommandPalette/defaultCommandPaletteItems.d.ts +1 -1
- package/dist/excalidraw/components/CommandPalette/types.d.ts +3 -3
- package/dist/excalidraw/components/ConfirmDialog.d.ts +1 -1
- package/dist/excalidraw/components/ContextMenu.d.ts +2 -2
- package/dist/excalidraw/components/ContextMenu.js +2 -2
- package/dist/excalidraw/components/DarkModeToggle.d.ts +1 -1
- package/dist/excalidraw/components/DefaultSidebar.d.ts +2 -2
- package/dist/excalidraw/components/Dialog.js +1 -1
- package/dist/excalidraw/components/DialogActionButton.d.ts +1 -1
- package/dist/excalidraw/components/EyeDropper.d.ts +2 -2
- package/dist/excalidraw/components/FollowMode/FollowMode.d.ts +1 -1
- package/dist/excalidraw/components/FollowMode/FollowMode.js +1 -1
- package/dist/excalidraw/components/HelpDialog.js +1 -1
- package/dist/excalidraw/components/HintViewer.d.ts +1 -1
- package/dist/excalidraw/components/IconPicker.js +2 -2
- package/dist/excalidraw/components/ImageExportDialog.d.ts +1 -1
- package/dist/excalidraw/components/InitializeApp.d.ts +2 -2
- package/dist/excalidraw/components/JSONExportDialog.d.ts +3 -3
- package/dist/excalidraw/components/LayerUI.d.ts +4 -4
- package/dist/excalidraw/components/LayerUI.js +10 -7
- package/dist/excalidraw/components/LibraryMenu.d.ts +2 -2
- package/dist/excalidraw/components/LibraryMenuBrowseButton.d.ts +1 -1
- package/dist/excalidraw/components/LibraryMenuControlButtons.d.ts +1 -1
- package/dist/excalidraw/components/LibraryMenuHeaderContent.d.ts +2 -2
- package/dist/excalidraw/components/LibraryMenuItems.d.ts +1 -1
- package/dist/excalidraw/components/LibraryMenuSection.d.ts +5 -4
- package/dist/excalidraw/components/LibraryUnit.d.ts +2 -2
- package/dist/excalidraw/components/LoadingMessage.d.ts +1 -1
- package/dist/excalidraw/components/MagicSettings.js +2 -2
- package/dist/excalidraw/components/MobileMenu.d.ts +3 -3
- package/dist/excalidraw/components/MobileMenu.js +2 -6
- package/dist/excalidraw/components/Modal.d.ts +1 -1
- package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
- package/dist/excalidraw/components/PasteChartDialog.d.ts +1 -1
- package/dist/excalidraw/components/PasteChartDialog.js +1 -1
- package/dist/excalidraw/components/PublishLibrary.d.ts +1 -1
- package/dist/excalidraw/components/SVGLayer.d.ts +1 -1
- package/dist/excalidraw/components/Sidebar/Sidebar.js +1 -1
- package/dist/excalidraw/components/Sidebar/SidebarTab.d.ts +1 -1
- package/dist/excalidraw/components/Sidebar/SidebarTabTrigger.d.ts +1 -1
- package/dist/excalidraw/components/Sidebar/SidebarTrigger.d.ts +1 -1
- package/dist/excalidraw/components/Sidebar/common.d.ts +1 -1
- package/dist/excalidraw/components/Stats/Angle.d.ts +12 -0
- package/dist/excalidraw/components/Stats/Angle.js +52 -0
- package/dist/excalidraw/components/Stats/Collapsible.d.ts +9 -0
- package/dist/excalidraw/components/Stats/Collapsible.js +12 -0
- package/dist/excalidraw/components/Stats/Dimension.d.ts +12 -0
- package/dist/excalidraw/components/Stats/Dimension.js +67 -0
- package/dist/excalidraw/components/Stats/DragInput.d.ts +32 -0
- package/dist/excalidraw/components/Stats/DragInput.js +174 -0
- package/dist/excalidraw/components/Stats/FontSize.d.ts +12 -0
- package/dist/excalidraw/components/Stats/FontSize.js +50 -0
- package/dist/excalidraw/components/Stats/MultiAngle.d.ts +12 -0
- package/dist/excalidraw/components/Stats/MultiAngle.js +66 -0
- package/dist/excalidraw/components/Stats/MultiDimension.d.ts +15 -0
- package/dist/excalidraw/components/Stats/MultiDimension.js +197 -0
- package/dist/excalidraw/components/Stats/MultiFontSize.d.ts +13 -0
- package/dist/excalidraw/components/Stats/MultiFontSize.js +72 -0
- package/dist/excalidraw/components/Stats/MultiPosition.d.ts +15 -0
- package/dist/excalidraw/components/Stats/MultiPosition.js +100 -0
- package/dist/excalidraw/components/Stats/Position.d.ts +13 -0
- package/dist/excalidraw/components/Stats/Position.js +39 -0
- package/dist/excalidraw/components/Stats/index.d.ts +16 -0
- package/dist/excalidraw/components/Stats/index.js +78 -0
- package/dist/excalidraw/components/Stats/utils.d.ts +25 -0
- package/dist/excalidraw/components/Stats/utils.js +158 -0
- package/dist/excalidraw/components/TTDDialog/MermaidToExcalidraw.d.ts +1 -1
- package/dist/excalidraw/components/TTDDialog/TTDDialog.js +2 -2
- package/dist/excalidraw/components/TTDDialog/TTDDialogInput.d.ts +1 -1
- package/dist/excalidraw/components/TTDDialog/TTDDialogPanel.d.ts +1 -1
- package/dist/excalidraw/components/TTDDialog/TTDDialogPanels.d.ts +1 -1
- package/dist/excalidraw/components/TTDDialog/TTDDialogTabs.d.ts +1 -1
- package/dist/excalidraw/components/TTDDialog/TTDDialogTrigger.d.ts +1 -1
- package/dist/excalidraw/components/TTDDialog/common.d.ts +4 -4
- package/dist/excalidraw/components/TextField.d.ts +1 -1
- package/dist/excalidraw/components/Toast.d.ts +1 -1
- package/dist/excalidraw/components/ToolButton.d.ts +3 -2
- package/dist/excalidraw/components/Trans.d.ts +1 -1
- package/dist/excalidraw/components/UserList.d.ts +1 -1
- package/dist/excalidraw/components/canvases/InteractiveCanvas.d.ts +3 -2
- package/dist/excalidraw/components/canvases/InteractiveCanvas.js +4 -2
- package/dist/excalidraw/components/canvases/StaticCanvas.d.ts +2 -2
- package/dist/excalidraw/components/canvases/StaticCanvas.js +2 -2
- package/dist/excalidraw/components/dropdownMenu/DropdownMenuItem.js +2 -2
- package/dist/excalidraw/components/footer/Footer.d.ts +2 -2
- package/dist/excalidraw/components/hyperlink/Hyperlink.d.ts +2 -2
- package/dist/excalidraw/components/hyperlink/helpers.d.ts +3 -3
- package/dist/excalidraw/components/icons.d.ts +6 -2
- package/dist/excalidraw/components/icons.js +22 -6
- package/dist/excalidraw/constants.d.ts +8 -2
- package/dist/excalidraw/constants.js +8 -1
- package/dist/excalidraw/context/ui-appState.d.ts +1 -1
- package/dist/excalidraw/cursor.d.ts +1 -1
- package/dist/excalidraw/data/EditorLocalStorage.d.ts +2 -2
- package/dist/excalidraw/data/blob.d.ts +5 -5
- package/dist/excalidraw/data/filesystem.d.ts +2 -1
- package/dist/excalidraw/data/index.d.ts +4 -4
- package/dist/excalidraw/data/json.d.ts +3 -3
- package/dist/excalidraw/data/library.d.ts +3 -3
- package/dist/excalidraw/data/magic.d.ts +3 -3
- package/dist/excalidraw/data/reconcile.d.ts +3 -3
- package/dist/excalidraw/data/resave.d.ts +2 -2
- package/dist/excalidraw/data/restore.d.ts +3 -3
- package/dist/excalidraw/data/restore.js +16 -1
- package/dist/excalidraw/data/transform.d.ts +3 -3
- package/dist/excalidraw/data/types.d.ts +3 -3
- package/dist/excalidraw/element/ElementCanvasButtons.d.ts +1 -1
- package/dist/excalidraw/element/binding.d.ts +7 -21
- package/dist/excalidraw/element/binding.js +127 -102
- package/dist/excalidraw/element/bounds.d.ts +3 -3
- package/dist/excalidraw/element/collision.d.ts +3 -3
- package/dist/excalidraw/element/collision.js +1 -1
- package/dist/excalidraw/element/containerCache.d.ts +1 -1
- package/dist/excalidraw/element/dragElements.d.ts +4 -4
- package/dist/excalidraw/element/dragElements.js +27 -3
- package/dist/excalidraw/element/embeddable.d.ts +8 -5
- package/dist/excalidraw/element/image.d.ts +2 -2
- package/dist/excalidraw/element/index.d.ts +2 -2
- package/dist/excalidraw/element/index.js +1 -1
- package/dist/excalidraw/element/linearElementEditor.d.ts +8 -5
- package/dist/excalidraw/element/linearElementEditor.js +7 -4
- package/dist/excalidraw/element/mutateElement.d.ts +2 -2
- package/dist/excalidraw/element/mutateElement.js +1 -1
- package/dist/excalidraw/element/newElement.d.ts +5 -8
- package/dist/excalidraw/element/newElement.js +16 -14
- package/dist/excalidraw/element/resizeElements.d.ts +11 -3
- package/dist/excalidraw/element/resizeElements.js +75 -23
- package/dist/excalidraw/element/resizeTest.d.ts +4 -4
- package/dist/excalidraw/element/resizeTest.js +2 -4
- package/dist/excalidraw/element/showSelectedShapeActions.d.ts +2 -2
- package/dist/excalidraw/element/sizeHelpers.d.ts +2 -2
- package/dist/excalidraw/element/sortElements.d.ts +1 -1
- package/dist/excalidraw/element/textElement.d.ts +5 -4
- package/dist/excalidraw/element/textElement.js +11 -3
- package/dist/excalidraw/element/textWysiwyg.d.ts +12 -6
- package/dist/excalidraw/element/textWysiwyg.js +38 -17
- package/dist/excalidraw/element/transformHandles.d.ts +3 -3
- package/dist/excalidraw/element/transformHandles.js +0 -10
- package/dist/excalidraw/element/typeChecks.d.ts +4 -4
- package/dist/excalidraw/element/types.d.ts +11 -4
- package/dist/excalidraw/emitter.d.ts +1 -1
- package/dist/excalidraw/fractionalIndex.d.ts +1 -1
- package/dist/excalidraw/fractionalIndex.js +2 -4
- package/dist/excalidraw/frame.d.ts +3 -3
- package/dist/excalidraw/gatransforms.d.ts +1 -1
- package/dist/excalidraw/gesture.d.ts +1 -1
- package/dist/excalidraw/groups.d.ts +4 -4
- package/dist/excalidraw/history.d.ts +4 -4
- package/dist/excalidraw/hooks/useEmitter.d.ts +1 -1
- package/dist/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
- package/dist/excalidraw/i18n.d.ts +1 -1
- package/dist/excalidraw/index.d.ts +1 -1
- package/dist/excalidraw/jotai.d.ts +1 -1
- package/dist/excalidraw/laser-trails.d.ts +3 -2
- package/dist/excalidraw/locales/en.json +24 -3
- package/dist/excalidraw/math.d.ts +4 -2
- package/dist/excalidraw/math.js +6 -0
- package/dist/excalidraw/mermaid.d.ts +2 -0
- package/dist/excalidraw/mermaid.js +28 -0
- package/dist/excalidraw/points.d.ts +1 -1
- package/dist/excalidraw/queue.d.ts +1 -1
- package/dist/excalidraw/renderer/helpers.d.ts +2 -2
- package/dist/excalidraw/renderer/interactiveScene.d.ts +2 -2
- package/dist/excalidraw/renderer/interactiveScene.js +32 -6
- package/dist/excalidraw/renderer/renderElement.d.ts +4 -4
- package/dist/excalidraw/renderer/renderElement.js +5 -5
- package/dist/excalidraw/renderer/renderSnaps.d.ts +1 -1
- package/dist/excalidraw/renderer/staticScene.d.ts +1 -1
- package/dist/excalidraw/renderer/staticSvgScene.d.ts +4 -4
- package/dist/excalidraw/scene/Fonts.d.ts +2 -4
- package/dist/excalidraw/scene/Fonts.js +12 -15
- package/dist/excalidraw/scene/Renderer.d.ts +4 -4
- package/dist/excalidraw/scene/Renderer.js +2 -3
- package/dist/excalidraw/scene/Scene.d.ts +16 -7
- package/dist/excalidraw/scene/Scene.js +17 -8
- package/dist/excalidraw/scene/Shape.d.ts +1 -1
- package/dist/excalidraw/scene/ShapeCache.d.ts +4 -4
- package/dist/excalidraw/scene/comparisons.d.ts +2 -2
- package/dist/excalidraw/scene/export.d.ts +2 -2
- package/dist/excalidraw/scene/export.js +2 -2
- package/dist/excalidraw/scene/scroll.d.ts +2 -2
- package/dist/excalidraw/scene/scrollbars.d.ts +3 -3
- package/dist/excalidraw/scene/selection.d.ts +2 -2
- package/dist/excalidraw/scene/types.d.ts +6 -8
- package/dist/excalidraw/scene/zoom.d.ts +1 -1
- package/dist/excalidraw/shapes.d.ts +7 -0
- package/dist/excalidraw/shapes.js +40 -0
- package/dist/excalidraw/snapping.d.ts +4 -4
- package/dist/excalidraw/snapping.js +2 -1
- package/dist/excalidraw/store.d.ts +34 -4
- package/dist/excalidraw/store.js +27 -0
- package/dist/excalidraw/types.d.ts +25 -20
- package/dist/excalidraw/utils.d.ts +4 -4
- package/dist/excalidraw/zindex.d.ts +2 -2
- package/dist/prod/{en-XW4JO6VX.json → en-EB2MBPAV.json} +24 -3
- package/dist/prod/index.css +1 -1
- package/dist/prod/index.js +39 -39
- package/dist/utils/bbox.d.ts +2 -2
- package/dist/utils/collision.d.ts +1 -1
- package/dist/utils/export.d.ts +2 -2
- package/dist/utils/geometry/geometry.d.ts +1 -1
- package/dist/utils/geometry/shape.d.ts +1 -1
- package/dist/utils/withinBounds.d.ts +1 -1
- package/history.ts +4 -4
- package/package.json +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/chunk-47LVF2XL.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/chunk-XOM7LNOU.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/dist-ITJNUBZF.js.map +0 -7
- package/dist/browser/prod/excalidraw-assets/chunk-4SNEEDZH.js +0 -55
- package/dist/browser/prod/excalidraw-assets/dist-54276HPL.js +0 -6
- package/dist/browser/prod/excalidraw-assets/en-7GPZE2Y2.js +0 -1
- package/dist/browser/prod/excalidraw-assets/image-ISQJGWLB.js +0 -1
- package/dist/excalidraw/components/Stats.d.ts +0 -11
- package/dist/excalidraw/components/Stats.js +0 -13
- /package/dist/browser/dev/excalidraw-assets-dev/{en-TR4QLF5E.js.map → en-AZFA5HJJ.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{image-LHMGJWTI.js.map → image-5XCR4WHS.js.map} +0 -0
|
@@ -10,13 +10,14 @@ import { ActionManager } from "../actions/manager";
|
|
|
10
10
|
import { actions } from "../actions/register";
|
|
11
11
|
import { trackEvent } from "../analytics";
|
|
12
12
|
import { getDefaultAppState, isEraserActive, isHandToolActive, } from "../appState";
|
|
13
|
-
import { copyTextToSystemClipboard, parseClipboard
|
|
14
|
-
import {
|
|
13
|
+
import { copyTextToSystemClipboard, parseClipboard } from "../clipboard";
|
|
14
|
+
import { DEFAULT_FONT_SIZE } from "../constants";
|
|
15
|
+
import { APP_NAME, CURSOR_TYPE, DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT, DEFAULT_VERTICAL_ALIGN, DRAGGING_THRESHOLD, ELEMENT_SHIFT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT, ENV, EVENT, FRAME_STYLE, GRID_SIZE, IMAGE_MIME_TYPES, IMAGE_RENDER_TIMEOUT, isBrave, LINE_CONFIRM_THRESHOLD, MAX_ALLOWED_FILE_BYTES, MIME_TYPES, MQ_MAX_HEIGHT_LANDSCAPE, MQ_MAX_WIDTH_LANDSCAPE, MQ_MAX_WIDTH_PORTRAIT, MQ_RIGHT_SIDEBAR_MIN_WIDTH, POINTER_BUTTON, ROUNDNESS, SCROLL_TIMEOUT, TAP_TWICE_TIMEOUT, TEXT_TO_CENTER_SNAP_THRESHOLD, THEME, THEME_FILTER, TOUCH_CTX_MENU_TIMEOUT, VERTICAL_ALIGN, YOUTUBE_STATES, ZOOM_STEP, POINTER_EVENTS, TOOL_TYPE, EDITOR_LS_KEYS, isIOS, supportsResizeObserver, DEFAULT_COLLISION_THRESHOLD, DEFAULT_TEXT_ALIGN, } from "../constants";
|
|
15
16
|
import { exportCanvas, loadFromBlob } from "../data";
|
|
16
17
|
import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library";
|
|
17
18
|
import { restore, restoreElements } from "../data/restore";
|
|
18
|
-
import { dragNewElement, dragSelectedElements, duplicateElement, getCommonBounds, getCursorForResizingElement, getDragOffsetXY, getElementWithTransformHandleType, getNormalizedDimensions, getResizeArrowDirection, getResizeOffsetXY, getLockedLinearCursorAlignSize, getTransformHandleTypeFromCoords, isInvisiblySmallElement, isNonDeletedElement, isTextElement, newElement, newLinearElement, newTextElement, newImageElement, transformElements,
|
|
19
|
-
import { bindOrUnbindLinearElement,
|
|
19
|
+
import { dragNewElement, dragSelectedElements, duplicateElement, getCommonBounds, getCursorForResizingElement, getDragOffsetXY, getElementWithTransformHandleType, getNormalizedDimensions, getResizeArrowDirection, getResizeOffsetXY, getLockedLinearCursorAlignSize, getTransformHandleTypeFromCoords, isInvisiblySmallElement, isNonDeletedElement, isTextElement, newElement, newLinearElement, newTextElement, newImageElement, transformElements, refreshTextDimensions, redrawTextBoundingBox, getElementAbsoluteCoords, } from "../element";
|
|
20
|
+
import { bindOrUnbindLinearElement, bindOrUnbindLinearElements, fixBindingsAfterDeletion, fixBindingsAfterDuplication, getHoveredElementForBinding, isBindingEnabled, isLinearElementSimpleAndAlreadyBound, maybeBindLinearElement, shouldEnableBindingForPointerEvent, updateBoundElements, getSuggestedBindingsForArrows, } from "../element/binding";
|
|
20
21
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
|
21
22
|
import { mutateElement, newElementWith } from "../element/mutateElement";
|
|
22
23
|
import { deepCopyElement, duplicateElements, newFrameElement, newFreeDrawElement, newEmbeddableElement, newMagicFrameElement, newIframeElement, } from "../element/newElement";
|
|
@@ -31,12 +32,12 @@ import { distance2d, getCornerRadius, getGridPoint, isPathALoop, } from "../math
|
|
|
31
32
|
import { calculateScrollCenter, getElementsWithinSelection, getNormalizedZoom, getSelectedElements, hasBackground, isSomeElementSelected, } from "../scene";
|
|
32
33
|
import Scene from "../scene/Scene";
|
|
33
34
|
import { getStateForZoom } from "../scene/zoom";
|
|
34
|
-
import { findShapeByKey } from "../shapes";
|
|
35
|
-
import {
|
|
35
|
+
import { findShapeByKey, getElementShape } from "../shapes";
|
|
36
|
+
import { getSelectionBoxShape } from "../../utils/geometry/shape";
|
|
36
37
|
import { isPointInShape } from "../../utils/collision";
|
|
37
38
|
import { debounce, distance, getFontString, getNearestScrollableContainer, isInputLike, isToolIcon, isWritableElement, sceneCoordsToViewportCoords, tupleToCoors, viewportCoordsToSceneCoords, wrapEvent, updateObject, updateActiveTool, getShortcutKey, isTransparent, easeToValuesRAF, muteFSAbortError, isTestEnv, easeOut, updateStable, addEventListener, normalizeEOL, getDateTime, isShallowEqual, arrayToMap, } from "../utils";
|
|
38
39
|
import { createSrcDoc, embeddableURLValidator, maybeParseEmbedSrc, getEmbedLink, } from "../element/embeddable";
|
|
39
|
-
import { ContextMenu, CONTEXT_MENU_SEPARATOR
|
|
40
|
+
import { ContextMenu, CONTEXT_MENU_SEPARATOR } from "./ContextMenu";
|
|
40
41
|
import LayerUI from "./LayerUI";
|
|
41
42
|
import { Toast } from "./Toast";
|
|
42
43
|
import { actionToggleViewMode } from "../actions/actionToggleViewMode";
|
|
@@ -44,7 +45,7 @@ import { dataURLToFile, generateIdFromFile, getDataURL, getFileFromEvent, ImageU
|
|
|
44
45
|
import { getInitializedImageElements, loadHTMLImageElement, normalizeSVG, updateImageCache as _updateImageCache, } from "../element/image";
|
|
45
46
|
import throttle from "lodash.throttle";
|
|
46
47
|
import { fileOpen } from "../data/filesystem";
|
|
47
|
-
import { bindTextToShapeAfterDuplication, getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getContainerCenter, getContainerElement, getDefaultLineHeight, getLineHeightInPx, isMeasureTextSupported, isValidTextContainer, } from "../element/textElement";
|
|
48
|
+
import { bindTextToShapeAfterDuplication, getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getContainerCenter, getContainerElement, getDefaultLineHeight, getLineHeightInPx, getMinTextElementWidth, isMeasureTextSupported, isValidTextContainer, measureText, wrapText, } from "../element/textElement";
|
|
48
49
|
import { showHyperlinkTooltip, hideHyperlinkToolip, Hyperlink, } from "../components/hyperlink/Hyperlink";
|
|
49
50
|
import { isLocalLink, normalizeLink, toValidURL } from "../data/url";
|
|
50
51
|
import { shouldShowBoundingBox } from "../element/transformHandles";
|
|
@@ -62,7 +63,7 @@ import { getSnapLinesAtPointer, snapDraggedElements, isActiveToolNonLinearSnappa
|
|
|
62
63
|
import { actionWrapTextInContainer } from "../actions/actionBoundText";
|
|
63
64
|
import BraveMeasureTextError from "./BraveMeasureTextError";
|
|
64
65
|
import { activeEyeDropperAtom } from "./EyeDropper";
|
|
65
|
-
import { convertToExcalidrawElements
|
|
66
|
+
import { convertToExcalidrawElements } from "../data/transform";
|
|
66
67
|
import { isSidebarDockedAtom } from "./Sidebar/Sidebar";
|
|
67
68
|
import { StaticCanvas, InteractiveCanvas } from "./canvases";
|
|
68
69
|
import { Renderer } from "../scene/Renderer";
|
|
@@ -84,12 +85,15 @@ import { AnimatedTrail } from "../animated-trail";
|
|
|
84
85
|
import { LaserTrails } from "../laser-trails";
|
|
85
86
|
import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils";
|
|
86
87
|
import { getRenderOpacity } from "../renderer/renderElement";
|
|
87
|
-
import { hitElementBoundText, hitElementBoundingBoxOnly, hitElementItself,
|
|
88
|
+
import { hitElementBoundText, hitElementBoundingBoxOnly, hitElementItself, } from "../element/collision";
|
|
88
89
|
import { textWysiwyg } from "../element/textWysiwyg";
|
|
89
90
|
import { isOverScrollBars } from "../scene/scrollbars";
|
|
90
91
|
import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex";
|
|
91
92
|
import { isPointHittingLink, isPointHittingLinkIcon, } from "./hyperlink/helpers";
|
|
92
93
|
import { getShortcutFromShortcutName } from "../actions/shortcuts";
|
|
94
|
+
import { actionTextAutoResize } from "../actions/actionTextAutoResize";
|
|
95
|
+
import { getVisibleSceneBounds } from "../element/bounds";
|
|
96
|
+
import { isMaybeMermaidDefinition } from "../mermaid";
|
|
93
97
|
const AppContext = React.createContext(null);
|
|
94
98
|
const AppPropsContext = React.createContext(null);
|
|
95
99
|
const deviceContextInitialValue = {
|
|
@@ -286,10 +290,7 @@ class App extends React.Component {
|
|
|
286
290
|
container: this.excalidrawContainerRef.current,
|
|
287
291
|
id: this.id,
|
|
288
292
|
};
|
|
289
|
-
this.fonts = new Fonts({
|
|
290
|
-
scene: this.scene,
|
|
291
|
-
onSceneUpdated: this.onSceneUpdated,
|
|
292
|
-
});
|
|
293
|
+
this.fonts = new Fonts({ scene: this.scene });
|
|
293
294
|
this.history = new History();
|
|
294
295
|
this.actionManager.registerAll(actions);
|
|
295
296
|
this.actionManager.registerAction(createUndoAction(this.history, this.store));
|
|
@@ -444,7 +445,7 @@ class App extends React.Component {
|
|
|
444
445
|
return false;
|
|
445
446
|
});
|
|
446
447
|
if (updated) {
|
|
447
|
-
this.scene.
|
|
448
|
+
this.scene.triggerUpdate();
|
|
448
449
|
}
|
|
449
450
|
// GC
|
|
450
451
|
this.iFrameRefs.forEach((ref, id) => {
|
|
@@ -803,9 +804,9 @@ class App extends React.Component {
|
|
|
803
804
|
render() {
|
|
804
805
|
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
805
806
|
const { renderTopRightUI, renderCustomStats } = this.props;
|
|
806
|
-
const
|
|
807
|
+
const sceneNonce = this.scene.getSceneNonce();
|
|
807
808
|
const { elementsMap, visibleElements } = this.renderer.getRenderableElements({
|
|
808
|
-
|
|
809
|
+
sceneNonce,
|
|
809
810
|
zoom: this.state.zoom,
|
|
810
811
|
offsetLeft: this.state.offsetLeft,
|
|
811
812
|
offsetTop: this.state.offsetTop,
|
|
@@ -874,14 +875,14 @@ class App extends React.Component {
|
|
|
874
875
|
this.focusContainer();
|
|
875
876
|
callback?.();
|
|
876
877
|
});
|
|
877
|
-
} })), _jsx(StaticCanvas, { canvas: this.canvas, rc: this.rc, elementsMap: elementsMap, allElementsMap: allElementsMap, visibleElements: visibleElements,
|
|
878
|
+
} })), _jsx(StaticCanvas, { canvas: this.canvas, rc: this.rc, elementsMap: elementsMap, allElementsMap: allElementsMap, visibleElements: visibleElements, sceneNonce: sceneNonce, selectionNonce: this.state.selectionElement?.versionNonce, scale: window.devicePixelRatio, appState: this.state, renderConfig: {
|
|
878
879
|
imageCache: this.imageCache,
|
|
879
880
|
isExporting: false,
|
|
880
881
|
renderGrid: true,
|
|
881
882
|
canvasBackgroundColor: this.state.viewBackgroundColor,
|
|
882
883
|
embedsValidationStatus: this.embedsValidationStatus,
|
|
883
884
|
elementsPendingErasure: this.elementsPendingErasure,
|
|
884
|
-
} }), _jsx(InteractiveCanvas, { containerRef: this.excalidrawContainerRef, canvas: this.interactiveCanvas, elementsMap: elementsMap, visibleElements: visibleElements, selectedElements: selectedElements,
|
|
885
|
+
} }), _jsx(InteractiveCanvas, { containerRef: this.excalidrawContainerRef, canvas: this.interactiveCanvas, elementsMap: elementsMap, visibleElements: visibleElements, allElementsMap: allElementsMap, selectedElements: selectedElements, sceneNonce: sceneNonce, selectionNonce: this.state.selectionElement?.versionNonce, scale: window.devicePixelRatio, appState: this.state, device: this.device, renderInteractiveSceneCallback: this.renderInteractiveSceneCallback, handleCanvasRef: this.handleInteractiveCanvasRef, onContextMenu: this.handleCanvasContextMenu, onPointerMove: this.handleCanvasPointerMove, onPointerUp: this.handleCanvasPointerUp, onPointerCancel: this.removePointer, onTouchMove: this.handleTouchMove, onPointerDown: this.handleCanvasPointerDown, onDoubleClick: this.handleCanvasDoubleClick }), this.state.userToFollow && (_jsx(FollowMode, { width: this.state.width, height: this.state.height, userToFollow: this.state.userToFollow, onDisconnect: this.maybeUnfollowRemoteUser })), this.renderFrameNames()] }), this.renderEmbeddables()] }) }) }) }) }) }) }) }));
|
|
885
886
|
}
|
|
886
887
|
focusContainer = () => {
|
|
887
888
|
this.excalidrawContainerRef.current?.focus();
|
|
@@ -931,7 +932,7 @@ class App extends React.Component {
|
|
|
931
932
|
mutateElement(frameElement, { customData: { generationData: data } }, false);
|
|
932
933
|
}
|
|
933
934
|
this.magicGenerations.set(frameElement.id, data);
|
|
934
|
-
this.
|
|
935
|
+
this.triggerRender();
|
|
935
936
|
};
|
|
936
937
|
getTextFromElements(elements) {
|
|
937
938
|
const text = elements
|
|
@@ -1184,6 +1185,13 @@ class App extends React.Component {
|
|
|
1184
1185
|
if (this.unmounted || actionResult === false) {
|
|
1185
1186
|
return;
|
|
1186
1187
|
}
|
|
1188
|
+
if (actionResult.storeAction === StoreAction.UPDATE) {
|
|
1189
|
+
this.store.shouldUpdateSnapshot();
|
|
1190
|
+
}
|
|
1191
|
+
else if (actionResult.storeAction === StoreAction.CAPTURE) {
|
|
1192
|
+
this.store.shouldCaptureIncrement();
|
|
1193
|
+
}
|
|
1194
|
+
let didUpdate = false;
|
|
1187
1195
|
let editingElement = null;
|
|
1188
1196
|
if (actionResult.elements) {
|
|
1189
1197
|
actionResult.elements.forEach((element) => {
|
|
@@ -1193,13 +1201,8 @@ class App extends React.Component {
|
|
|
1193
1201
|
editingElement = element;
|
|
1194
1202
|
}
|
|
1195
1203
|
});
|
|
1196
|
-
if (actionResult.storeAction === StoreAction.UPDATE) {
|
|
1197
|
-
this.store.shouldUpdateSnapshot();
|
|
1198
|
-
}
|
|
1199
|
-
else if (actionResult.storeAction === StoreAction.CAPTURE) {
|
|
1200
|
-
this.store.shouldCaptureIncrement();
|
|
1201
|
-
}
|
|
1202
1204
|
this.scene.replaceAllElements(actionResult.elements);
|
|
1205
|
+
didUpdate = true;
|
|
1203
1206
|
}
|
|
1204
1207
|
if (actionResult.files) {
|
|
1205
1208
|
this.files = actionResult.replaceFiles
|
|
@@ -1208,12 +1211,6 @@ class App extends React.Component {
|
|
|
1208
1211
|
this.addNewImagesToImageCache();
|
|
1209
1212
|
}
|
|
1210
1213
|
if (actionResult.appState || editingElement || this.state.contextMenu) {
|
|
1211
|
-
if (actionResult.storeAction === StoreAction.UPDATE) {
|
|
1212
|
-
this.store.shouldUpdateSnapshot();
|
|
1213
|
-
}
|
|
1214
|
-
else if (actionResult.storeAction === StoreAction.CAPTURE) {
|
|
1215
|
-
this.store.shouldCaptureIncrement();
|
|
1216
|
-
}
|
|
1217
1214
|
let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
|
|
1218
1215
|
let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
|
|
1219
1216
|
let gridSize = actionResult?.appState?.gridSize || null;
|
|
@@ -1252,6 +1249,10 @@ class App extends React.Component {
|
|
|
1252
1249
|
errorMessage,
|
|
1253
1250
|
});
|
|
1254
1251
|
});
|
|
1252
|
+
didUpdate = true;
|
|
1253
|
+
}
|
|
1254
|
+
if (!didUpdate && actionResult.storeAction !== StoreAction.NONE) {
|
|
1255
|
+
this.scene.triggerUpdate();
|
|
1255
1256
|
}
|
|
1256
1257
|
});
|
|
1257
1258
|
// Lifecycle
|
|
@@ -1304,7 +1305,12 @@ class App extends React.Component {
|
|
|
1304
1305
|
}
|
|
1305
1306
|
let initialData = null;
|
|
1306
1307
|
try {
|
|
1307
|
-
|
|
1308
|
+
if (typeof this.props.initialData === "function") {
|
|
1309
|
+
initialData = (await this.props.initialData()) || null;
|
|
1310
|
+
}
|
|
1311
|
+
else {
|
|
1312
|
+
initialData = (await this.props.initialData) || null;
|
|
1313
|
+
}
|
|
1308
1314
|
if (initialData?.libraryItems) {
|
|
1309
1315
|
this.library
|
|
1310
1316
|
.updateLibrary({
|
|
@@ -1441,7 +1447,7 @@ class App extends React.Component {
|
|
|
1441
1447
|
this.store.onStoreIncrementEmitter.on((increment) => {
|
|
1442
1448
|
this.history.record(increment.elementsChange, increment.appStateChange);
|
|
1443
1449
|
});
|
|
1444
|
-
this.scene.
|
|
1450
|
+
this.scene.onUpdate(this.triggerRender);
|
|
1445
1451
|
this.addEventListeners();
|
|
1446
1452
|
if (this.props.autoFocus && this.excalidrawContainerRef.current) {
|
|
1447
1453
|
this.focusContainer();
|
|
@@ -1477,15 +1483,17 @@ class App extends React.Component {
|
|
|
1477
1483
|
}
|
|
1478
1484
|
}
|
|
1479
1485
|
componentWillUnmount() {
|
|
1486
|
+
window.launchQueue?.setConsumer(() => { });
|
|
1480
1487
|
this.renderer.destroy();
|
|
1488
|
+
this.scene.destroy();
|
|
1481
1489
|
this.scene = new Scene();
|
|
1490
|
+
this.fonts = new Fonts({ scene: this.scene });
|
|
1482
1491
|
this.renderer = new Renderer(this.scene);
|
|
1483
1492
|
this.files = {};
|
|
1484
1493
|
this.imageCache.clear();
|
|
1485
1494
|
this.resizeObserver?.disconnect();
|
|
1486
1495
|
this.unmounted = true;
|
|
1487
1496
|
this.removeEventListeners();
|
|
1488
|
-
this.scene.destroy();
|
|
1489
1497
|
this.library.destroy();
|
|
1490
1498
|
this.laserTrails.stop();
|
|
1491
1499
|
this.eraserTrail.stop();
|
|
@@ -1534,7 +1542,7 @@ class App extends React.Component {
|
|
|
1534
1542
|
this.onRemoveEventListenersEmitter.once(addEventListener(document, EVENT.KEYDOWN, this.onKeyDown, false));
|
|
1535
1543
|
}
|
|
1536
1544
|
this.onRemoveEventListenersEmitter.once(addEventListener(this.excalidrawContainerRef.current, EVENT.WHEEL, this.onWheel, { passive: false }), addEventListener(window, EVENT.MESSAGE, this.onWindowMessage, false), addEventListener(document, EVENT.POINTER_UP, this.removePointer), // #3553
|
|
1537
|
-
addEventListener(document, EVENT.COPY, this.onCopy), addEventListener(document, EVENT.KEYUP, this.onKeyUp, { passive: true }), addEventListener(document, EVENT.
|
|
1545
|
+
addEventListener(document, EVENT.COPY, this.onCopy), addEventListener(document, EVENT.KEYUP, this.onKeyUp, { passive: true }), addEventListener(document, EVENT.POINTER_MOVE, this.updateCurrentCursorPosition),
|
|
1538
1546
|
// rerender text elements on font load to fix #637 && #1553
|
|
1539
1547
|
addEventListener(document.fonts, "loadingdone", (event) => {
|
|
1540
1548
|
const loadedFontFaces = event.fontfaces;
|
|
@@ -1543,6 +1551,9 @@ class App extends React.Component {
|
|
|
1543
1551
|
// Safari-only desktop pinch zoom
|
|
1544
1552
|
addEventListener(document, EVENT.GESTURE_START, this.onGestureStart, false), addEventListener(document, EVENT.GESTURE_CHANGE, this.onGestureChange, false), addEventListener(document, EVENT.GESTURE_END, this.onGestureEnd, false), addEventListener(window, EVENT.FOCUS, () => {
|
|
1545
1553
|
this.maybeCleanupAfterMissingPointerUp(null);
|
|
1554
|
+
// browsers (chrome?) tend to free up memory a lot, which results
|
|
1555
|
+
// in canvas context being cleared. Thus re-render on focus.
|
|
1556
|
+
this.triggerRender(true);
|
|
1546
1557
|
}));
|
|
1547
1558
|
if (this.state.viewModeEnabled) {
|
|
1548
1559
|
return;
|
|
@@ -1660,7 +1671,7 @@ class App extends React.Component {
|
|
|
1660
1671
|
multiElement != null &&
|
|
1661
1672
|
isBindingEnabled(this.state) &&
|
|
1662
1673
|
isBindingElement(multiElement, false)) {
|
|
1663
|
-
maybeBindLinearElement(multiElement, this.state, tupleToCoors(LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, nonDeletedElementsMap)), this);
|
|
1674
|
+
maybeBindLinearElement(multiElement, this.state, tupleToCoors(LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, nonDeletedElementsMap)), this.scene.getNonDeletedElementsMap());
|
|
1664
1675
|
}
|
|
1665
1676
|
this.store.commit(elementsMap, this.state);
|
|
1666
1677
|
// Do not notify consumers if we're still loading the scene. Among other
|
|
@@ -1849,6 +1860,26 @@ class App extends React.Component {
|
|
|
1849
1860
|
});
|
|
1850
1861
|
}
|
|
1851
1862
|
else if (data.text) {
|
|
1863
|
+
if (data.text && isMaybeMermaidDefinition(data.text)) {
|
|
1864
|
+
const api = await import("@excalidraw/mermaid-to-excalidraw");
|
|
1865
|
+
try {
|
|
1866
|
+
const { elements: skeletonElements, files } = await api.parseMermaidToExcalidraw(data.text, {
|
|
1867
|
+
fontSize: DEFAULT_FONT_SIZE,
|
|
1868
|
+
});
|
|
1869
|
+
const elements = convertToExcalidrawElements(skeletonElements, {
|
|
1870
|
+
regenerateIds: true,
|
|
1871
|
+
});
|
|
1872
|
+
this.addElementsFromPasteOrLibrary({
|
|
1873
|
+
elements,
|
|
1874
|
+
files,
|
|
1875
|
+
position: "cursor",
|
|
1876
|
+
});
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1879
|
+
catch (err) {
|
|
1880
|
+
console.warn(`parsing pasted text as mermaid definition failed: ${err.message}`);
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1852
1883
|
const nonEmptyLines = normalizeEOL(data.text)
|
|
1853
1884
|
.split(/\n+/)
|
|
1854
1885
|
.map((s) => s.trim())
|
|
@@ -2053,27 +2084,46 @@ class App extends React.Component {
|
|
|
2053
2084
|
text,
|
|
2054
2085
|
fontSize: this.state.currentItemFontSize,
|
|
2055
2086
|
fontFamily: this.state.currentItemFontFamily,
|
|
2056
|
-
textAlign:
|
|
2087
|
+
textAlign: DEFAULT_TEXT_ALIGN,
|
|
2057
2088
|
verticalAlign: DEFAULT_VERTICAL_ALIGN,
|
|
2058
2089
|
locked: false,
|
|
2059
2090
|
};
|
|
2091
|
+
const fontString = getFontString({
|
|
2092
|
+
fontSize: textElementProps.fontSize,
|
|
2093
|
+
fontFamily: textElementProps.fontFamily,
|
|
2094
|
+
});
|
|
2095
|
+
const lineHeight = getDefaultLineHeight(textElementProps.fontFamily);
|
|
2096
|
+
const [x1, , x2] = getVisibleSceneBounds(this.state);
|
|
2097
|
+
// long texts should not go beyond 800 pixels in width nor should it go below 200 px
|
|
2098
|
+
const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.5, 800), 200);
|
|
2060
2099
|
const LINE_GAP = 10;
|
|
2061
2100
|
let currentY = y;
|
|
2062
2101
|
const lines = isPlainPaste ? [text] : text.split("\n");
|
|
2063
2102
|
const textElements = lines.reduce((acc, line, idx) => {
|
|
2064
|
-
const
|
|
2065
|
-
|
|
2066
|
-
if (text.length) {
|
|
2103
|
+
const originalText = line.trim();
|
|
2104
|
+
if (originalText.length) {
|
|
2067
2105
|
const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
|
|
2068
2106
|
x,
|
|
2069
2107
|
y: currentY,
|
|
2070
2108
|
});
|
|
2109
|
+
let metrics = measureText(originalText, fontString, lineHeight);
|
|
2110
|
+
const isTextWrapped = metrics.width > maxTextWidth;
|
|
2111
|
+
const text = isTextWrapped
|
|
2112
|
+
? wrapText(originalText, fontString, maxTextWidth)
|
|
2113
|
+
: originalText;
|
|
2114
|
+
metrics = isTextWrapped
|
|
2115
|
+
? measureText(text, fontString, lineHeight)
|
|
2116
|
+
: metrics;
|
|
2117
|
+
const startX = x - metrics.width / 2;
|
|
2118
|
+
const startY = currentY - metrics.height / 2;
|
|
2071
2119
|
const element = newTextElement({
|
|
2072
2120
|
...textElementProps,
|
|
2073
|
-
x,
|
|
2074
|
-
y:
|
|
2121
|
+
x: startX,
|
|
2122
|
+
y: startY,
|
|
2075
2123
|
text,
|
|
2124
|
+
originalText,
|
|
2076
2125
|
lineHeight,
|
|
2126
|
+
autoResize: !isTextWrapped,
|
|
2077
2127
|
frameId: topLayerFrame ? topLayerFrame.id : null,
|
|
2078
2128
|
});
|
|
2079
2129
|
acc.push(element);
|
|
@@ -2292,7 +2342,7 @@ class App extends React.Component {
|
|
|
2292
2342
|
ShapeCache.delete(element);
|
|
2293
2343
|
}
|
|
2294
2344
|
});
|
|
2295
|
-
this.scene.
|
|
2345
|
+
this.scene.triggerUpdate();
|
|
2296
2346
|
this.addNewImagesToImageCache();
|
|
2297
2347
|
});
|
|
2298
2348
|
updateScene = withBatchedUpdates((sceneData) => {
|
|
@@ -2326,8 +2376,15 @@ class App extends React.Component {
|
|
|
2326
2376
|
this.setState({ collaborators: sceneData.collaborators });
|
|
2327
2377
|
}
|
|
2328
2378
|
});
|
|
2329
|
-
|
|
2330
|
-
|
|
2379
|
+
triggerRender = (
|
|
2380
|
+
/** force always re-renders canvas even if no change */
|
|
2381
|
+
force) => {
|
|
2382
|
+
if (force === true) {
|
|
2383
|
+
this.scene.triggerUpdate();
|
|
2384
|
+
}
|
|
2385
|
+
else {
|
|
2386
|
+
this.setState({});
|
|
2387
|
+
}
|
|
2331
2388
|
};
|
|
2332
2389
|
/**
|
|
2333
2390
|
* @returns whether the menu was toggled on or off
|
|
@@ -2494,7 +2551,9 @@ class App extends React.Component {
|
|
|
2494
2551
|
simultaneouslyUpdated: selectedElements,
|
|
2495
2552
|
});
|
|
2496
2553
|
});
|
|
2497
|
-
this.
|
|
2554
|
+
this.setState({
|
|
2555
|
+
suggestedBindings: getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap()),
|
|
2556
|
+
});
|
|
2498
2557
|
event.preventDefault();
|
|
2499
2558
|
}
|
|
2500
2559
|
else if (event.key === KEYS.ENTER) {
|
|
@@ -2632,11 +2691,7 @@ class App extends React.Component {
|
|
|
2632
2691
|
this.setState({ isBindingEnabled: true });
|
|
2633
2692
|
}
|
|
2634
2693
|
if (isArrowKey(event.key)) {
|
|
2635
|
-
|
|
2636
|
-
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
2637
|
-
isBindingEnabled(this.state)
|
|
2638
|
-
? bindOrUnbindSelectedElements(selectedElements, this)
|
|
2639
|
-
: unbindLinearElements(selectedElements, elementsMap);
|
|
2694
|
+
bindOrUnbindLinearElements(this.scene.getSelectedElements(this.state).filter(isLinearElement), this.scene.getNonDeletedElementsMap(), isBindingEnabled(this.state), this.state.selectedLinearElement?.selectedPointsIndices ?? []);
|
|
2640
2695
|
this.setState({ suggestedBindings: [] });
|
|
2641
2696
|
}
|
|
2642
2697
|
});
|
|
@@ -2774,15 +2829,16 @@ class App extends React.Component {
|
|
|
2774
2829
|
});
|
|
2775
2830
|
handleTextWysiwyg(element, { isExistingElement = false, }) {
|
|
2776
2831
|
const elementsMap = this.scene.getElementsMapIncludingDeleted();
|
|
2777
|
-
const updateElement = (
|
|
2832
|
+
const updateElement = (nextOriginalText, isDeleted) => {
|
|
2778
2833
|
this.scene.replaceAllElements([
|
|
2779
2834
|
// Not sure why we include deleted elements as well hence using deleted elements map
|
|
2780
2835
|
...this.scene.getElementsIncludingDeleted().map((_element) => {
|
|
2781
2836
|
if (_element.id === element.id && isTextElement(_element)) {
|
|
2782
|
-
return
|
|
2783
|
-
|
|
2784
|
-
isDeleted,
|
|
2785
|
-
|
|
2837
|
+
return newElementWith(_element, {
|
|
2838
|
+
originalText: nextOriginalText,
|
|
2839
|
+
isDeleted: isDeleted ?? _element.isDeleted,
|
|
2840
|
+
// returns (wrapped) text and new dimensions
|
|
2841
|
+
...refreshTextDimensions(_element, getContainerElement(_element, elementsMap), elementsMap, nextOriginalText),
|
|
2786
2842
|
});
|
|
2787
2843
|
}
|
|
2788
2844
|
return _element;
|
|
@@ -2802,15 +2858,15 @@ class App extends React.Component {
|
|
|
2802
2858
|
viewportY - this.state.offsetTop,
|
|
2803
2859
|
];
|
|
2804
2860
|
},
|
|
2805
|
-
onChange: withBatchedUpdates((
|
|
2806
|
-
updateElement(
|
|
2861
|
+
onChange: withBatchedUpdates((nextOriginalText) => {
|
|
2862
|
+
updateElement(nextOriginalText, false);
|
|
2807
2863
|
if (isNonDeletedElement(element)) {
|
|
2808
2864
|
updateBoundElements(element, elementsMap);
|
|
2809
2865
|
}
|
|
2810
2866
|
}),
|
|
2811
|
-
onSubmit: withBatchedUpdates(({
|
|
2812
|
-
const isDeleted = !
|
|
2813
|
-
updateElement(
|
|
2867
|
+
onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
|
|
2868
|
+
const isDeleted = !nextOriginalText.trim();
|
|
2869
|
+
updateElement(nextOriginalText, isDeleted);
|
|
2814
2870
|
// select the created text element only if submitting via keyboard
|
|
2815
2871
|
// (when submitting via click it should act as signal to deselect)
|
|
2816
2872
|
if (!isDeleted && viaKeyboard) {
|
|
@@ -2844,12 +2900,17 @@ class App extends React.Component {
|
|
|
2844
2900
|
element,
|
|
2845
2901
|
excalidrawContainer: this.excalidrawContainerRef.current,
|
|
2846
2902
|
app: this,
|
|
2903
|
+
// when text is selected, it's hard (at least on iOS) to re-position the
|
|
2904
|
+
// caret (i.e. deselect). There's not much use for always selecting
|
|
2905
|
+
// the text on edit anyway (and users can select-all from contextmenu
|
|
2906
|
+
// if needed)
|
|
2907
|
+
autoSelect: !this.device.isTouchScreen,
|
|
2847
2908
|
});
|
|
2848
2909
|
// deselect all other elements when inserting text
|
|
2849
2910
|
this.deselectElements();
|
|
2850
2911
|
// do an initial update to re-initialize element position since we were
|
|
2851
2912
|
// modifying element's x/y for sake of editor (case: syncing to remote)
|
|
2852
|
-
updateElement(element.
|
|
2913
|
+
updateElement(element.originalText, false);
|
|
2853
2914
|
}
|
|
2854
2915
|
deselectElements() {
|
|
2855
2916
|
this.setState({
|
|
@@ -2868,54 +2929,18 @@ class App extends React.Component {
|
|
|
2868
2929
|
}
|
|
2869
2930
|
return null;
|
|
2870
2931
|
}
|
|
2871
|
-
/**
|
|
2872
|
-
* get the pure geometric shape of an excalidraw element
|
|
2873
|
-
* which is then used for hit detection
|
|
2874
|
-
*/
|
|
2875
|
-
getElementShape(element) {
|
|
2876
|
-
switch (element.type) {
|
|
2877
|
-
case "rectangle":
|
|
2878
|
-
case "diamond":
|
|
2879
|
-
case "frame":
|
|
2880
|
-
case "magicframe":
|
|
2881
|
-
case "embeddable":
|
|
2882
|
-
case "image":
|
|
2883
|
-
case "iframe":
|
|
2884
|
-
case "text":
|
|
2885
|
-
case "selection":
|
|
2886
|
-
return getPolygonShape(element);
|
|
2887
|
-
case "arrow":
|
|
2888
|
-
case "line": {
|
|
2889
|
-
const roughShape = ShapeCache.get(element)?.[0] ??
|
|
2890
|
-
ShapeCache.generateElementShape(element, null)[0];
|
|
2891
|
-
const [, , , , cx, cy] = getElementAbsoluteCoords(element, this.scene.getNonDeletedElementsMap());
|
|
2892
|
-
return shouldTestInside(element)
|
|
2893
|
-
? getClosedCurveShape(element, roughShape, [element.x, element.y], element.angle, [cx, cy])
|
|
2894
|
-
: getCurveShape(roughShape, [element.x, element.y], element.angle, [
|
|
2895
|
-
cx,
|
|
2896
|
-
cy,
|
|
2897
|
-
]);
|
|
2898
|
-
}
|
|
2899
|
-
case "ellipse":
|
|
2900
|
-
return getEllipseShape(element);
|
|
2901
|
-
case "freedraw": {
|
|
2902
|
-
const [, , , , cx, cy] = getElementAbsoluteCoords(element, this.scene.getNonDeletedElementsMap());
|
|
2903
|
-
return getFreedrawShape(element, [cx, cy], shouldTestInside(element));
|
|
2904
|
-
}
|
|
2905
|
-
}
|
|
2906
|
-
}
|
|
2907
2932
|
getBoundTextShape(element) {
|
|
2908
2933
|
const boundTextElement = getBoundTextElement(element, this.scene.getNonDeletedElementsMap());
|
|
2909
2934
|
if (boundTextElement) {
|
|
2910
2935
|
if (element.type === "arrow") {
|
|
2911
|
-
return
|
|
2936
|
+
return getElementShape({
|
|
2912
2937
|
...boundTextElement,
|
|
2913
2938
|
// arrow's bound text accurate position is not stored in the element's property
|
|
2914
2939
|
// but rather calculated and returned from the following static method
|
|
2915
2940
|
...LinearElementEditor.getBoundTextElementPosition(element, boundTextElement, this.scene.getNonDeletedElementsMap()),
|
|
2916
|
-
});
|
|
2941
|
+
}, this.scene.getNonDeletedElementsMap());
|
|
2917
2942
|
}
|
|
2918
|
-
return this.
|
|
2943
|
+
return getElementShape(boundTextElement, this.scene.getNonDeletedElementsMap());
|
|
2919
2944
|
}
|
|
2920
2945
|
return null;
|
|
2921
2946
|
}
|
|
@@ -2936,7 +2961,7 @@ class App extends React.Component {
|
|
|
2936
2961
|
x,
|
|
2937
2962
|
y,
|
|
2938
2963
|
element: elementWithHighestZIndex,
|
|
2939
|
-
shape: this.
|
|
2964
|
+
shape: getElementShape(elementWithHighestZIndex, this.scene.getNonDeletedElementsMap()),
|
|
2940
2965
|
// when overlapping, we would like to be more precise
|
|
2941
2966
|
// this also avoids the need to update past tests
|
|
2942
2967
|
threshold: this.getElementHitThreshold() / 2,
|
|
@@ -3006,7 +3031,7 @@ class App extends React.Component {
|
|
|
3006
3031
|
x,
|
|
3007
3032
|
y,
|
|
3008
3033
|
element,
|
|
3009
|
-
shape: this.
|
|
3034
|
+
shape: getElementShape(element, this.scene.getNonDeletedElementsMap()),
|
|
3010
3035
|
threshold: this.getElementHitThreshold(),
|
|
3011
3036
|
frameNameBound: isFrameLikeElement(element)
|
|
3012
3037
|
? this.frameNameBoundsCache.get(element)
|
|
@@ -3033,7 +3058,7 @@ class App extends React.Component {
|
|
|
3033
3058
|
x,
|
|
3034
3059
|
y,
|
|
3035
3060
|
element: elements[index],
|
|
3036
|
-
shape:
|
|
3061
|
+
shape: getElementShape(elements[index], this.scene.getNonDeletedElementsMap()),
|
|
3037
3062
|
threshold: this.getElementHitThreshold(),
|
|
3038
3063
|
})) {
|
|
3039
3064
|
hitElement = elements[index];
|
|
@@ -3046,7 +3071,7 @@ class App extends React.Component {
|
|
|
3046
3071
|
}
|
|
3047
3072
|
return isTextBindableContainer(hitElement, false) ? hitElement : null;
|
|
3048
3073
|
}
|
|
3049
|
-
startTextEditing = ({ sceneX, sceneY, insertAtParentCenter = true, container, }) => {
|
|
3074
|
+
startTextEditing = ({ sceneX, sceneY, insertAtParentCenter = true, container, autoEdit = true, }) => {
|
|
3050
3075
|
let shouldBindToContainer = false;
|
|
3051
3076
|
let parentCenterPosition = insertAtParentCenter &&
|
|
3052
3077
|
this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);
|
|
@@ -3147,12 +3172,17 @@ class App extends React.Component {
|
|
|
3147
3172
|
this.scene.insertElement(element);
|
|
3148
3173
|
}
|
|
3149
3174
|
}
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3175
|
+
if (autoEdit || existingTextElement || container) {
|
|
3176
|
+
this.handleTextWysiwyg(element, {
|
|
3177
|
+
isExistingElement: !!existingTextElement,
|
|
3178
|
+
});
|
|
3179
|
+
}
|
|
3180
|
+
else {
|
|
3181
|
+
this.setState({
|
|
3182
|
+
draggingElement: element,
|
|
3183
|
+
multiElement: null,
|
|
3184
|
+
});
|
|
3185
|
+
}
|
|
3156
3186
|
};
|
|
3157
3187
|
handleCanvasDoubleClick = (event) => {
|
|
3158
3188
|
// case: double-clicking with arrow/line tool selected would both create
|
|
@@ -3212,7 +3242,7 @@ class App extends React.Component {
|
|
|
3212
3242
|
x: sceneX,
|
|
3213
3243
|
y: sceneY,
|
|
3214
3244
|
element: container,
|
|
3215
|
-
shape: this.
|
|
3245
|
+
shape: getElementShape(container, this.scene.getNonDeletedElementsMap()),
|
|
3216
3246
|
threshold: this.getElementHitThreshold(),
|
|
3217
3247
|
})) {
|
|
3218
3248
|
const midPoint = getContainerCenter(container, this.state, this.scene.getNonDeletedElementsMap());
|
|
@@ -3319,8 +3349,11 @@ class App extends React.Component {
|
|
|
3319
3349
|
}, state);
|
|
3320
3350
|
this.translateCanvas({
|
|
3321
3351
|
zoom: zoomState.zoom,
|
|
3322
|
-
|
|
3323
|
-
|
|
3352
|
+
// 2x multiplier is just a magic number that makes this work correctly
|
|
3353
|
+
// on touchscreen devices (note: if we get report that panning is slower/faster
|
|
3354
|
+
// than actual movement, consider swapping with devicePixelRatio)
|
|
3355
|
+
scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),
|
|
3356
|
+
scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),
|
|
3324
3357
|
shouldCacheIgnoreZoom: true,
|
|
3325
3358
|
});
|
|
3326
3359
|
});
|
|
@@ -3641,7 +3674,7 @@ class App extends React.Component {
|
|
|
3641
3674
|
}
|
|
3642
3675
|
}
|
|
3643
3676
|
this.elementsPendingErasure = new Set(this.elementsPendingErasure);
|
|
3644
|
-
this.
|
|
3677
|
+
this.triggerRender();
|
|
3645
3678
|
}
|
|
3646
3679
|
};
|
|
3647
3680
|
// set touch moving for mobile context menu
|
|
@@ -3661,7 +3694,7 @@ class App extends React.Component {
|
|
|
3661
3694
|
x: scenePointerX,
|
|
3662
3695
|
y: scenePointerY,
|
|
3663
3696
|
element,
|
|
3664
|
-
shape: this.
|
|
3697
|
+
shape: getElementShape(element, this.scene.getNonDeletedElementsMap()),
|
|
3665
3698
|
})) {
|
|
3666
3699
|
hoverPointIndex = LinearElementEditor.getPointIndexUnderCursor(element, elementsMap, this.state.zoom, scenePointerX, scenePointerY);
|
|
3667
3700
|
segmentMidPointHoveredCoords =
|
|
@@ -3852,7 +3885,6 @@ class App extends React.Component {
|
|
|
3852
3885
|
}
|
|
3853
3886
|
if (this.state.activeTool.type === "text") {
|
|
3854
3887
|
this.handleTextOnPointerDown(event, pointerDownState);
|
|
3855
|
-
return;
|
|
3856
3888
|
}
|
|
3857
3889
|
else if (this.state.activeTool.type === "arrow" ||
|
|
3858
3890
|
this.state.activeTool.type === "line") {
|
|
@@ -4400,6 +4432,7 @@ class App extends React.Component {
|
|
|
4400
4432
|
sceneY,
|
|
4401
4433
|
insertAtParentCenter: !event.altKey,
|
|
4402
4434
|
container,
|
|
4435
|
+
autoEdit: false,
|
|
4403
4436
|
});
|
|
4404
4437
|
resetCursor(this.interactiveCanvas);
|
|
4405
4438
|
if (!this.state.activeTool.locked) {
|
|
@@ -4447,7 +4480,7 @@ class App extends React.Component {
|
|
|
4447
4480
|
points: [[0, 0]],
|
|
4448
4481
|
pressures,
|
|
4449
4482
|
});
|
|
4450
|
-
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this);
|
|
4483
|
+
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.getNonDeletedElementsMap());
|
|
4451
4484
|
this.scene.insertElement(element);
|
|
4452
4485
|
this.setState({
|
|
4453
4486
|
draggingElement: element,
|
|
@@ -4619,7 +4652,7 @@ class App extends React.Component {
|
|
|
4619
4652
|
mutateElement(element, {
|
|
4620
4653
|
points: [...element.points, [0, 0]],
|
|
4621
4654
|
});
|
|
4622
|
-
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this);
|
|
4655
|
+
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.getNonDeletedElementsMap());
|
|
4623
4656
|
this.scene.insertElement(element);
|
|
4624
4657
|
this.setState({
|
|
4625
4658
|
draggingElement: element,
|
|
@@ -4916,7 +4949,9 @@ class App extends React.Component {
|
|
|
4916
4949
|
// able to select and interact with the text input
|
|
4917
4950
|
!this.state.editingFrame &&
|
|
4918
4951
|
dragSelectedElements(pointerDownState, selectedElements, dragOffset, this.state, this.scene, snapOffset, event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);
|
|
4919
|
-
this.
|
|
4952
|
+
this.setState({
|
|
4953
|
+
suggestedBindings: getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap()),
|
|
4954
|
+
});
|
|
4920
4955
|
// We duplicate the selected element if alt is pressed on pointer move
|
|
4921
4956
|
if (event.altKey && !pointerDownState.hit.hasBeenDuplicated) {
|
|
4922
4957
|
// Move the currently selected elements to the top of the z index stack, and
|
|
@@ -5263,7 +5298,7 @@ class App extends React.Component {
|
|
|
5263
5298
|
else if (pointerDownState.drag.hasOccurred && !multiElement) {
|
|
5264
5299
|
if (isBindingEnabled(this.state) &&
|
|
5265
5300
|
isBindingElement(draggingElement, false)) {
|
|
5266
|
-
maybeBindLinearElement(draggingElement, this.state, pointerCoords, this);
|
|
5301
|
+
maybeBindLinearElement(draggingElement, this.state, pointerCoords, this.scene.getNonDeletedElementsMap());
|
|
5267
5302
|
}
|
|
5268
5303
|
this.setState({ suggestedBindings: [], startBoundElement: null });
|
|
5269
5304
|
if (!activeTool.locked) {
|
|
@@ -5288,6 +5323,21 @@ class App extends React.Component {
|
|
|
5288
5323
|
}
|
|
5289
5324
|
return;
|
|
5290
5325
|
}
|
|
5326
|
+
if (isTextElement(draggingElement)) {
|
|
5327
|
+
const minWidth = getMinTextElementWidth(getFontString({
|
|
5328
|
+
fontSize: draggingElement.fontSize,
|
|
5329
|
+
fontFamily: draggingElement.fontFamily,
|
|
5330
|
+
}), draggingElement.lineHeight);
|
|
5331
|
+
if (draggingElement.width < minWidth) {
|
|
5332
|
+
mutateElement(draggingElement, {
|
|
5333
|
+
autoResize: true,
|
|
5334
|
+
});
|
|
5335
|
+
}
|
|
5336
|
+
this.resetCursor();
|
|
5337
|
+
this.handleTextWysiwyg(draggingElement, {
|
|
5338
|
+
isExistingElement: true,
|
|
5339
|
+
});
|
|
5340
|
+
}
|
|
5291
5341
|
if (activeTool.type !== "selection" &&
|
|
5292
5342
|
draggingElement &&
|
|
5293
5343
|
isInvisiblySmallElement(draggingElement)) {
|
|
@@ -5323,7 +5373,7 @@ class App extends React.Component {
|
|
|
5323
5373
|
groupIds: [],
|
|
5324
5374
|
});
|
|
5325
5375
|
removeElementsFromFrame([linearElement], this.scene.getNonDeletedElementsMap());
|
|
5326
|
-
this.scene.
|
|
5376
|
+
this.scene.triggerUpdate();
|
|
5327
5377
|
}
|
|
5328
5378
|
}
|
|
5329
5379
|
}
|
|
@@ -5556,7 +5606,7 @@ class App extends React.Component {
|
|
|
5556
5606
|
x: pointerDownState.origin.x,
|
|
5557
5607
|
y: pointerDownState.origin.y,
|
|
5558
5608
|
element: hitElement,
|
|
5559
|
-
shape: this.
|
|
5609
|
+
shape: getElementShape(hitElement, this.scene.getNonDeletedElementsMap()),
|
|
5560
5610
|
threshold: this.getElementHitThreshold(),
|
|
5561
5611
|
frameNameBound: isFrameLikeElement(hitElement)
|
|
5562
5612
|
? this.frameNameBoundsCache.get(hitElement)
|
|
@@ -5600,9 +5650,12 @@ class App extends React.Component {
|
|
|
5600
5650
|
this.store.shouldCaptureIncrement();
|
|
5601
5651
|
}
|
|
5602
5652
|
if (pointerDownState.drag.hasOccurred || isResizing || isRotating) {
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5653
|
+
// We only allow binding via linear elements, specifically via dragging
|
|
5654
|
+
// the endpoints ("start" or "end").
|
|
5655
|
+
const linearElements = this.scene
|
|
5656
|
+
.getSelectedElements(this.state)
|
|
5657
|
+
.filter(isLinearElement);
|
|
5658
|
+
bindOrUnbindLinearElements(linearElements, this.scene.getNonDeletedElementsMap(), isBindingEnabled(this.state), this.state.selectedLinearElement?.selectedPointsIndices ?? []);
|
|
5606
5659
|
}
|
|
5607
5660
|
if (activeTool.type === "laser") {
|
|
5608
5661
|
this.laserTrails.endPath();
|
|
@@ -5637,7 +5690,7 @@ class App extends React.Component {
|
|
|
5637
5690
|
}
|
|
5638
5691
|
restoreReadyToEraseElements = () => {
|
|
5639
5692
|
this.elementsPendingErasure = new Set();
|
|
5640
|
-
this.
|
|
5693
|
+
this.triggerRender();
|
|
5641
5694
|
};
|
|
5642
5695
|
eraseElements = () => {
|
|
5643
5696
|
let didChange = false;
|
|
@@ -5929,7 +5982,7 @@ class App extends React.Component {
|
|
|
5929
5982
|
if (uncachedImageElements.length) {
|
|
5930
5983
|
const { updatedFiles } = await this.updateImageCache(uncachedImageElements, files);
|
|
5931
5984
|
if (updatedFiles.size) {
|
|
5932
|
-
this.scene.
|
|
5985
|
+
this.scene.triggerUpdate();
|
|
5933
5986
|
}
|
|
5934
5987
|
}
|
|
5935
5988
|
};
|
|
@@ -5945,7 +5998,7 @@ class App extends React.Component {
|
|
|
5945
5998
|
}
|
|
5946
5999
|
};
|
|
5947
6000
|
maybeSuggestBindingAtCursor = (pointerCoords) => {
|
|
5948
|
-
const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this);
|
|
6001
|
+
const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this.scene.getNonDeletedElementsMap());
|
|
5949
6002
|
this.setState({
|
|
5950
6003
|
suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : [],
|
|
5951
6004
|
});
|
|
@@ -5960,7 +6013,7 @@ class App extends React.Component {
|
|
|
5960
6013
|
return;
|
|
5961
6014
|
}
|
|
5962
6015
|
const suggestedBindings = pointerCoords.reduce((acc, coords) => {
|
|
5963
|
-
const hoveredBindableElement = getHoveredElementForBinding(coords, this);
|
|
6016
|
+
const hoveredBindableElement = getHoveredElementForBinding(coords, this.scene.getNonDeletedElementsMap());
|
|
5964
6017
|
if (hoveredBindableElement != null &&
|
|
5965
6018
|
!isLinearElementSimpleAndAlreadyBound(linearElement, oppositeBindingBoundElement?.id, hoveredBindableElement)) {
|
|
5966
6019
|
acc.push(hoveredBindableElement);
|
|
@@ -5969,13 +6022,6 @@ class App extends React.Component {
|
|
|
5969
6022
|
}, []);
|
|
5970
6023
|
this.setState({ suggestedBindings });
|
|
5971
6024
|
};
|
|
5972
|
-
maybeSuggestBindingForAll(selectedElements) {
|
|
5973
|
-
if (selectedElements.length > 50) {
|
|
5974
|
-
return;
|
|
5975
|
-
}
|
|
5976
|
-
const suggestedBindings = getEligibleElementsForBinding(selectedElements, this);
|
|
5977
|
-
this.setState({ suggestedBindings });
|
|
5978
|
-
}
|
|
5979
6025
|
clearSelection(hitElement) {
|
|
5980
6026
|
this.setState((prevState) => ({
|
|
5981
6027
|
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
|
@@ -6215,7 +6261,7 @@ class App extends React.Component {
|
|
|
6215
6261
|
}
|
|
6216
6262
|
if (draggingElement.type === "selection" &&
|
|
6217
6263
|
this.state.activeTool.type !== "eraser") {
|
|
6218
|
-
dragNewElement(draggingElement, this.state.activeTool.type, pointerDownState.origin.x, pointerDownState.origin.y, pointerCoords.x, pointerCoords.y, distance(pointerDownState.origin.x, pointerCoords.x), distance(pointerDownState.origin.y, pointerCoords.y), shouldMaintainAspectRatio(event), shouldResizeFromCenter(event));
|
|
6264
|
+
dragNewElement(draggingElement, this.state.activeTool.type, pointerDownState.origin.x, pointerDownState.origin.y, pointerCoords.x, pointerCoords.y, distance(pointerDownState.origin.x, pointerCoords.x), distance(pointerDownState.origin.y, pointerCoords.y), shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), this.state.zoom.value);
|
|
6219
6265
|
}
|
|
6220
6266
|
else {
|
|
6221
6267
|
let [gridX, gridY] = getGridPoint(pointerCoords.x, pointerCoords.y, event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);
|
|
@@ -6241,8 +6287,7 @@ class App extends React.Component {
|
|
|
6241
6287
|
});
|
|
6242
6288
|
dragNewElement(draggingElement, this.state.activeTool.type, pointerDownState.originInGrid.x, pointerDownState.originInGrid.y, gridX, gridY, distance(pointerDownState.originInGrid.x, gridX), distance(pointerDownState.originInGrid.y, gridY), isImageElement(draggingElement)
|
|
6243
6289
|
? !shouldMaintainAspectRatio(event)
|
|
6244
|
-
: shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), aspectRatio, this.state.originSnapOffset);
|
|
6245
|
-
this.maybeSuggestBindingForAll([draggingElement]);
|
|
6290
|
+
: shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), this.state.zoom.value, aspectRatio, this.state.originSnapOffset);
|
|
6246
6291
|
// highlight elements that are to be added to frames on frames creation
|
|
6247
6292
|
if (this.state.activeTool.type === TOOL_TYPE.frame ||
|
|
6248
6293
|
this.state.activeTool.type === TOOL_TYPE.magicframe) {
|
|
@@ -6299,13 +6344,14 @@ class App extends React.Component {
|
|
|
6299
6344
|
if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.some((element) => isImageElement(element))
|
|
6300
6345
|
? !shouldMaintainAspectRatio(event)
|
|
6301
6346
|
: shouldMaintainAspectRatio(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {
|
|
6302
|
-
this.
|
|
6347
|
+
const suggestedBindings = getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap());
|
|
6303
6348
|
const elementsToHighlight = new Set();
|
|
6304
6349
|
selectedFrames.forEach((frame) => {
|
|
6305
6350
|
getElementsInResizingFrame(this.scene.getNonDeletedElements(), frame, this.state, this.scene.getNonDeletedElementsMap()).forEach((element) => elementsToHighlight.add(element));
|
|
6306
6351
|
});
|
|
6307
6352
|
this.setState({
|
|
6308
6353
|
elementsToHighlight: [...elementsToHighlight],
|
|
6354
|
+
suggestedBindings,
|
|
6309
6355
|
});
|
|
6310
6356
|
return true;
|
|
6311
6357
|
}
|
|
@@ -6350,6 +6396,7 @@ class App extends React.Component {
|
|
|
6350
6396
|
return [actionCopy, ...options];
|
|
6351
6397
|
}
|
|
6352
6398
|
return [
|
|
6399
|
+
CONTEXT_MENU_SEPARATOR,
|
|
6353
6400
|
actionCut,
|
|
6354
6401
|
actionCopy,
|
|
6355
6402
|
actionPaste,
|
|
@@ -6362,6 +6409,7 @@ class App extends React.Component {
|
|
|
6362
6409
|
actionPasteStyles,
|
|
6363
6410
|
CONTEXT_MENU_SEPARATOR,
|
|
6364
6411
|
actionGroup,
|
|
6412
|
+
actionTextAutoResize,
|
|
6365
6413
|
actionUnbindText,
|
|
6366
6414
|
actionBindText,
|
|
6367
6415
|
actionWrapTextInContainer,
|