@excalidraw/excalidraw 0.17.1-890ed9f → 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 +15 -2
- package/dist/browser/dev/excalidraw-assets-dev/{blockDiagram-91b80b7a-ACFH36JV.js → blockDiagram-91b80b7a-H47FTXHA.js} +5 -5
- package/dist/browser/dev/excalidraw-assets-dev/{c4Diagram-b2a90758-QZ27YR47.js → c4Diagram-b2a90758-NNJK6GKC.js} +3 -3
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-HO2HMSK7.js → chunk-4KQVEBHW.js} +3 -3
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-USGV265L.js → chunk-53YI56GV.js} +4 -4
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-EDFX3S7X.js → chunk-A2WCJI4I.js} +3 -3
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-WQFMSDPT.js → chunk-DEYXWPUO.js} +7503 -2575
- package/dist/browser/dev/excalidraw-assets-dev/chunk-DEYXWPUO.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-IX4V72YG.js → chunk-EFLPX7NE.js} +6 -6
- 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/{chunk-MXVETLVM.js → chunk-JYIQCNWV.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-YZIOORVX.js → chunk-LVIQQW6F.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-6U7GQNJT.js → chunk-PXLO3FOU.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-7DACDEY3.js → chunk-TO2AW5PW.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-NJ77ZFNJ.js → chunk-VURILHLY.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-2T2GU7NF.js → chunk-ZAYGSUHF.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-Z3PH3V2B.js → chunk-ZQR5ML6Y.js} +26 -26
- package/dist/browser/dev/excalidraw-assets-dev/chunk-ZQR5ML6Y.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{classDiagram-30eddba6-QSLMH4JW.js → classDiagram-30eddba6-CUYIJICN.js} +5 -5
- package/dist/browser/dev/excalidraw-assets-dev/{classDiagram-v2-f2df5561-DY4DYQ5P.js → classDiagram-v2-f2df5561-K6WW6K73.js} +8 -8
- package/dist/browser/dev/excalidraw-assets-dev/{dist-Z46EOVOL.js → dist-6QVAH5JA.js} +37 -15
- 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/{erDiagram-47591fe2-SOOJRTCB.js → erDiagram-47591fe2-XGAD7EEP.js} +4 -4
- package/dist/browser/dev/excalidraw-assets-dev/{flowDiagram-5540d9b9-AHGL4KPK.js → flowDiagram-5540d9b9-B6EOVNNO.js} +9 -9
- package/dist/browser/dev/excalidraw-assets-dev/{flowDiagram-v2-3b53844e-56LDZZWY.js → flowDiagram-v2-3b53844e-NUG24FJH.js} +9 -9
- package/dist/browser/dev/excalidraw-assets-dev/{flowchart-elk-definition-5fe447d6-27LUKRI6.js → flowchart-elk-definition-5fe447d6-25Y7PCBL.js} +5 -5
- package/dist/browser/dev/excalidraw-assets-dev/{ganttDiagram-9a3bba1f-EHGYGNG6.js → ganttDiagram-9a3bba1f-GNL6ZDTC.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{gitGraphDiagram-96e6b4ee-AJQNBDW5.js → gitGraphDiagram-96e6b4ee-HNW52NVO.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{image-OIPMBJGR.js → image-5XCR4WHS.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{image-OFRRV5MB.css → image-O66MQ7WQ.css} +1 -1
- package/dist/browser/dev/excalidraw-assets-dev/image-O66MQ7WQ.css.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{infoDiagram-bcd20f53-SWLLQVES.js → infoDiagram-bcd20f53-FWEUVFLT.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{journeyDiagram-4fe6b3dc-7UAVCWOZ.js → journeyDiagram-4fe6b3dc-RZIUI7UG.js} +3 -3
- package/dist/browser/dev/excalidraw-assets-dev/{mindmap-definition-f354de21-SROW5KGM.js → mindmap-definition-f354de21-GBVN45GU.js} +3 -3
- package/dist/browser/dev/excalidraw-assets-dev/{pieDiagram-79897490-QKCI6NCB.js → pieDiagram-79897490-ECENNII6.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{quadrantDiagram-62f64e94-LNYJZFC5.js → quadrantDiagram-62f64e94-ZMEOFVNL.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{requirementDiagram-05bf5f74-ZZD7ZHFA.js → requirementDiagram-05bf5f74-FHZSFHCR.js} +4 -4
- package/dist/browser/dev/excalidraw-assets-dev/{sankeyDiagram-97764748-L75ZZ4UM.js → sankeyDiagram-97764748-VDKIKTA6.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{sequenceDiagram-acc0e65c-6PCU7TDK.js → sequenceDiagram-acc0e65c-6JUSPVKX.js} +3 -3
- package/dist/browser/dev/excalidraw-assets-dev/{stateDiagram-0ff1cf1a-WM76WOPR.js → stateDiagram-0ff1cf1a-L3AKWENF.js} +5 -5
- package/dist/browser/dev/excalidraw-assets-dev/{stateDiagram-v2-9a9d610d-N4HZW3O2.js → stateDiagram-v2-9a9d610d-NU3GGMCH.js} +8 -8
- package/dist/browser/dev/excalidraw-assets-dev/{timeline-definition-fea2a41d-ZHGCAXGP.js → timeline-definition-fea2a41d-JGP7XCHW.js} +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/{xychartDiagram-ab372869-2DLOVRAZ.js → xychartDiagram-ab372869-HLFHHF2I.js} +3 -3
- package/dist/browser/dev/index.css +199 -77
- package/dist/browser/dev/index.css.map +3 -3
- package/dist/browser/dev/index.js +12477 -8028
- package/dist/browser/dev/index.js.map +4 -4
- package/dist/browser/prod/excalidraw-assets/{blockDiagram-91b80b7a-ONPS22AM.js → blockDiagram-91b80b7a-FVCRVGN5.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{c4Diagram-b2a90758-XMIQY7ZT.js → c4Diagram-b2a90758-56CXO7GA.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-GCHQBOKV.js → chunk-635MQ3CK.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-5SYIAZGL.js → chunk-7DXALCB2.js} +5 -5
- package/dist/browser/prod/excalidraw-assets/{chunk-P5M3G2RP.js → chunk-AIKXYJX3.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-E2YLWFZX.js → chunk-CR7VMNWC.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-WEYK4A2L.js → chunk-FFF2CSVG.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-R3HAIP6R.js → chunk-G4WDCSPE.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-HFOXJM22.js → chunk-HKZSHFLX.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-XIMFFJTE.js → chunk-IKCDYWMW.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-AHLLBBVJ.js → chunk-L5DS24G6.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-CQJF3C6G.js → chunk-MUNOKHUD.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/chunk-ODWTVSS7.js +68 -0
- package/dist/browser/prod/excalidraw-assets/{chunk-NI6SYCUG.js → chunk-QOQYOOQ4.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-I2PZFXTK.js → chunk-ZTIWFPBM.js} +21 -21
- package/dist/browser/prod/excalidraw-assets/{classDiagram-30eddba6-IEJXXCVX.js → classDiagram-30eddba6-BCUTAUMD.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{classDiagram-v2-f2df5561-7LZDSWOS.js → classDiagram-v2-f2df5561-6SOXSGQ2.js} +1 -1
- 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/{erDiagram-47591fe2-E5V666CF.js → erDiagram-47591fe2-RE6HB7RM.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{flowDiagram-5540d9b9-GMBRCYVF.js → flowDiagram-5540d9b9-ZNJZBERW.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{flowDiagram-v2-3b53844e-Z4HUWP6B.js → flowDiagram-v2-3b53844e-LY44JLQJ.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{flowchart-elk-definition-5fe447d6-5ZCYTX5N.js → flowchart-elk-definition-5fe447d6-TMTJ6Z7O.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{ganttDiagram-9a3bba1f-WM32OMT5.js → ganttDiagram-9a3bba1f-5O6EA6LX.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{gitGraphDiagram-96e6b4ee-CAKZ2U6E.js → gitGraphDiagram-96e6b4ee-UHYNM5DI.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/image-LQAMCFQI.js +1 -0
- package/dist/browser/prod/excalidraw-assets/{infoDiagram-bcd20f53-MUIKXGC4.js → infoDiagram-bcd20f53-BP77NQEH.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{journeyDiagram-4fe6b3dc-NYRV4HK2.js → journeyDiagram-4fe6b3dc-XMGKCMES.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{mindmap-definition-f354de21-MY55DRSM.js → mindmap-definition-f354de21-ZQRRBRWF.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{pieDiagram-79897490-47L6J6L2.js → pieDiagram-79897490-IGXEC2KX.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{quadrantDiagram-62f64e94-DF5C2GDT.js → quadrantDiagram-62f64e94-WTHHDYJL.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{requirementDiagram-05bf5f74-C4IMUBDN.js → requirementDiagram-05bf5f74-MV4OFRVW.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{sankeyDiagram-97764748-YHW7EUST.js → sankeyDiagram-97764748-ZGYUHEJT.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{sequenceDiagram-acc0e65c-H3XEHT32.js → sequenceDiagram-acc0e65c-IBSENK6W.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{stateDiagram-0ff1cf1a-Z5WB6Q3P.js → stateDiagram-0ff1cf1a-DB73XNZH.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{stateDiagram-v2-9a9d610d-T7OZETQC.js → stateDiagram-v2-9a9d610d-2OOBUPNR.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{timeline-definition-fea2a41d-VVC22BWF.js → timeline-definition-fea2a41d-P3NQQVDU.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{xychartDiagram-ab372869-JAXODQF7.js → xychartDiagram-ab372869-HI3XLK3Y.js} +1 -1
- package/dist/browser/prod/index.css +1 -1
- package/dist/browser/prod/index.js +69 -51
- package/dist/{prod/en-XW4JO6VX.json → dev/en-EB2MBPAV.json} +24 -3
- package/dist/dev/index.css +199 -77
- package/dist/dev/index.css.map +3 -3
- package/dist/dev/index.js +15120 -11334
- package/dist/dev/index.js.map +4 -4
- package/dist/excalidraw/actions/actionAddToLibrary.d.ts +16 -7
- package/dist/excalidraw/actions/actionAddToLibrary.js +4 -3
- package/dist/excalidraw/actions/actionAlign.d.ts +22 -22
- package/dist/excalidraw/actions/actionAlign.js +7 -6
- package/dist/excalidraw/actions/actionBoundText.d.ts +18 -12
- package/dist/excalidraw/actions/actionBoundText.js +7 -4
- package/dist/excalidraw/actions/actionCanvas.d.ts +100 -64
- package/dist/excalidraw/actions/actionCanvas.js +17 -14
- package/dist/excalidraw/actions/actionClipboard.d.ts +52 -31
- package/dist/excalidraw/actions/actionClipboard.js +14 -13
- package/dist/excalidraw/actions/actionDeleteSelected.d.ts +22 -13
- package/dist/excalidraw/actions/actionDeleteSelected.js +6 -3
- package/dist/excalidraw/actions/actionDistribute.d.ts +10 -10
- package/dist/excalidraw/actions/actionDistribute.js +3 -2
- package/dist/excalidraw/actions/actionDuplicateSelection.d.ts +7 -8
- package/dist/excalidraw/actions/actionDuplicateSelection.js +4 -4
- package/dist/excalidraw/actions/actionElementLock.d.ts +17 -11
- package/dist/excalidraw/actions/actionElementLock.js +3 -2
- package/dist/excalidraw/actions/actionExport.d.ts +68 -41
- package/dist/excalidraw/actions/actionExport.js +15 -11
- package/dist/excalidraw/actions/actionFinalize.d.ts +17 -11
- package/dist/excalidraw/actions/actionFinalize.js +7 -3
- package/dist/excalidraw/actions/actionFlip.d.ts +10 -10
- package/dist/excalidraw/actions/actionFlip.js +9 -9
- package/dist/excalidraw/actions/actionFrame.d.ts +186 -21
- package/dist/excalidraw/actions/actionFrame.js +7 -6
- package/dist/excalidraw/actions/actionGroup.d.ts +24 -18
- package/dist/excalidraw/actions/actionGroup.js +7 -11
- package/dist/excalidraw/actions/actionHistory.d.ts +4 -3
- package/dist/excalidraw/actions/actionHistory.js +27 -31
- package/dist/excalidraw/actions/actionLinearEditor.d.ts +10 -5
- package/dist/excalidraw/actions/actionLinearEditor.js +21 -5
- package/dist/excalidraw/actions/actionLink.d.ts +9 -6
- package/dist/excalidraw/actions/actionLink.js +2 -1
- package/dist/excalidraw/actions/actionMenu.d.ts +20 -11
- package/dist/excalidraw/actions/actionMenu.js +4 -3
- package/dist/excalidraw/actions/actionNavigate.d.ts +12 -6
- package/dist/excalidraw/actions/actionNavigate.js +3 -2
- package/dist/excalidraw/actions/actionProperties.d.ts +86 -47
- package/dist/excalidraw/actions/actionProperties.js +19 -14
- package/dist/excalidraw/actions/actionSelectAll.d.ts +9 -6
- package/dist/excalidraw/actions/actionSelectAll.js +2 -1
- package/dist/excalidraw/actions/actionStyles.d.ts +15 -12
- package/dist/excalidraw/actions/actionStyles.js +4 -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 +9 -6
- package/dist/excalidraw/actions/actionToggleGridMode.js +2 -1
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +8 -5
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.js +2 -1
- package/dist/excalidraw/actions/actionToggleStats.d.ts +9 -5
- package/dist/excalidraw/actions/actionToggleStats.js +6 -4
- package/dist/excalidraw/actions/actionToggleViewMode.d.ts +8 -5
- package/dist/excalidraw/actions/actionToggleViewMode.js +2 -1
- package/dist/excalidraw/actions/actionToggleZenMode.d.ts +8 -5
- package/dist/excalidraw/actions/actionToggleZenMode.js +2 -1
- package/dist/excalidraw/actions/actionZindex.d.ts +20 -16
- package/dist/excalidraw/actions/actionZindex.js +9 -4
- package/dist/excalidraw/actions/manager.d.ts +5 -5
- 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 +8 -8
- package/dist/excalidraw/align.d.ts +1 -1
- package/dist/excalidraw/animated-trail.d.ts +2 -2
- package/dist/excalidraw/appState.d.ts +9 -6
- package/dist/excalidraw/appState.js +6 -3
- package/dist/excalidraw/change.d.ts +191 -0
- package/dist/excalidraw/change.js +901 -0
- 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 +19 -20
- package/dist/excalidraw/components/App.js +323 -195
- 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.d.ts +2 -2
- 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/Stack.d.ts +2 -2
- 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 +4 -2
- package/dist/excalidraw/components/ToolButton.js +1 -1
- 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 +5 -3
- package/dist/excalidraw/components/canvases/InteractiveCanvas.js +5 -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 +11 -2
- package/dist/excalidraw/constants.js +14 -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/reconcile.js +1 -1
- package/dist/excalidraw/data/resave.d.ts +2 -2
- package/dist/excalidraw/data/restore.d.ts +3 -3
- package/dist/excalidraw/data/restore.js +17 -2
- 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 +48 -20
- package/dist/excalidraw/element/binding.js +354 -168
- 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 +10 -7
- package/dist/excalidraw/element/embeddable.js +2 -1
- 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 +10 -7
- package/dist/excalidraw/element/linearElementEditor.js +9 -6
- package/dist/excalidraw/element/mutateElement.d.ts +3 -4
- 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 +12 -4
- package/dist/excalidraw/element/resizeElements.js +174 -98
- package/dist/excalidraw/element/resizeTest.d.ts +7 -7
- package/dist/excalidraw/element/resizeTest.js +53 -8
- package/dist/excalidraw/element/showSelectedShapeActions.d.ts +2 -2
- package/dist/excalidraw/element/sizeHelpers.d.ts +2 -2
- package/dist/excalidraw/element/sizeHelpers.js +3 -0
- package/dist/excalidraw/element/sortElements.d.ts +1 -1
- package/dist/excalidraw/element/textElement.d.ts +6 -5
- package/dist/excalidraw/element/textElement.js +16 -7
- package/dist/excalidraw/element/textWysiwyg.d.ts +12 -6
- package/dist/excalidraw/element/textWysiwyg.js +38 -17
- package/dist/excalidraw/element/transformHandles.d.ts +24 -6
- package/dist/excalidraw/element/transformHandles.js +22 -11
- package/dist/excalidraw/element/typeChecks.d.ts +5 -5
- package/dist/excalidraw/element/types.d.ts +16 -8
- 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 +6 -4
- package/dist/excalidraw/groups.js +17 -0
- package/dist/excalidraw/history.d.ts +35 -47
- package/dist/excalidraw/history.js +100 -167
- package/dist/excalidraw/hooks/useEmitter.d.ts +2 -0
- package/dist/excalidraw/hooks/useEmitter.js +13 -0
- package/dist/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
- package/dist/excalidraw/i18n.d.ts +1 -1
- package/dist/excalidraw/index.d.ts +3 -1
- package/dist/excalidraw/index.js +2 -0
- 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 +38 -11
- 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/staticScene.js +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 +17 -8
- package/dist/excalidraw/scene/Scene.js +19 -10
- 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 +7 -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 +129 -0
- package/dist/excalidraw/store.js +296 -0
- package/dist/excalidraw/types.d.ts +38 -20
- package/dist/excalidraw/utils.d.ts +10 -4
- package/dist/excalidraw/utils.js +7 -0
- package/dist/excalidraw/zindex.d.ts +2 -2
- package/dist/{dev/en-XW4JO6VX.json → prod/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 +2 -1
- package/dist/utils/geometry/shape.js +19 -0
- package/dist/utils/withinBounds.d.ts +1 -1
- package/history.ts +163 -218
- package/package.json +2 -2
- package/dist/browser/dev/excalidraw-assets-dev/chunk-WQFMSDPT.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/chunk-XOM7LNOU.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/chunk-Z3PH3V2B.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/dist-Z46EOVOL.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/image-OFRRV5MB.css.map +0 -7
- package/dist/browser/prod/excalidraw-assets/chunk-U3COIHDW.js +0 -55
- package/dist/browser/prod/excalidraw-assets/dist-PIPZXALV.js +0 -6
- package/dist/browser/prod/excalidraw-assets/en-7GPZE2Y2.js +0 -1
- package/dist/browser/prod/excalidraw-assets/image-ZLNYKWVQ.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/{blockDiagram-91b80b7a-ACFH36JV.js.map → blockDiagram-91b80b7a-H47FTXHA.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{c4Diagram-b2a90758-QZ27YR47.js.map → c4Diagram-b2a90758-NNJK6GKC.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-HO2HMSK7.js.map → chunk-4KQVEBHW.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-USGV265L.js.map → chunk-53YI56GV.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-EDFX3S7X.js.map → chunk-A2WCJI4I.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-IX4V72YG.js.map → chunk-EFLPX7NE.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-MXVETLVM.js.map → chunk-JYIQCNWV.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-YZIOORVX.js.map → chunk-LVIQQW6F.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-6U7GQNJT.js.map → chunk-PXLO3FOU.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-7DACDEY3.js.map → chunk-TO2AW5PW.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-NJ77ZFNJ.js.map → chunk-VURILHLY.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{chunk-2T2GU7NF.js.map → chunk-ZAYGSUHF.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{classDiagram-30eddba6-QSLMH4JW.js.map → classDiagram-30eddba6-CUYIJICN.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{classDiagram-v2-f2df5561-DY4DYQ5P.js.map → classDiagram-v2-f2df5561-K6WW6K73.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{en-TR4QLF5E.js.map → en-AZFA5HJJ.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{erDiagram-47591fe2-SOOJRTCB.js.map → erDiagram-47591fe2-XGAD7EEP.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{flowDiagram-5540d9b9-AHGL4KPK.js.map → flowDiagram-5540d9b9-B6EOVNNO.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{flowDiagram-v2-3b53844e-56LDZZWY.js.map → flowDiagram-v2-3b53844e-NUG24FJH.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{flowchart-elk-definition-5fe447d6-27LUKRI6.js.map → flowchart-elk-definition-5fe447d6-25Y7PCBL.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{ganttDiagram-9a3bba1f-EHGYGNG6.js.map → ganttDiagram-9a3bba1f-GNL6ZDTC.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{gitGraphDiagram-96e6b4ee-AJQNBDW5.js.map → gitGraphDiagram-96e6b4ee-HNW52NVO.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{image-OIPMBJGR.js.map → image-5XCR4WHS.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{infoDiagram-bcd20f53-SWLLQVES.js.map → infoDiagram-bcd20f53-FWEUVFLT.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{journeyDiagram-4fe6b3dc-7UAVCWOZ.js.map → journeyDiagram-4fe6b3dc-RZIUI7UG.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{mindmap-definition-f354de21-SROW5KGM.js.map → mindmap-definition-f354de21-GBVN45GU.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{pieDiagram-79897490-QKCI6NCB.js.map → pieDiagram-79897490-ECENNII6.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{quadrantDiagram-62f64e94-LNYJZFC5.js.map → quadrantDiagram-62f64e94-ZMEOFVNL.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{requirementDiagram-05bf5f74-ZZD7ZHFA.js.map → requirementDiagram-05bf5f74-FHZSFHCR.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{sankeyDiagram-97764748-L75ZZ4UM.js.map → sankeyDiagram-97764748-VDKIKTA6.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{sequenceDiagram-acc0e65c-6PCU7TDK.js.map → sequenceDiagram-acc0e65c-6JUSPVKX.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{stateDiagram-0ff1cf1a-WM76WOPR.js.map → stateDiagram-0ff1cf1a-L3AKWENF.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{stateDiagram-v2-9a9d610d-N4HZW3O2.js.map → stateDiagram-v2-9a9d610d-NU3GGMCH.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{timeline-definition-fea2a41d-ZHGCAXGP.js.map → timeline-definition-fea2a41d-JGP7XCHW.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{xychartDiagram-ab372869-2DLOVRAZ.js.map → xychartDiagram-ab372869-HLFHHF2I.js.map} +0 -0
|
@@ -10,20 +10,21 @@ 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";
|
|
23
24
|
import { hasBoundTextElement, isArrowElement, isBindingElement, isBindingElementType, isBoundToContainer, isFrameLikeElement, isImageElement, isEmbeddableElement, isInitializedImageElement, isLinearElement, isLinearElementType, isUsingAdaptiveRadius, isFrameElement, isIframeElement, isIframeLikeElement, isMagicFrameElement, isTextBindableContainer, } from "../element/typeChecks";
|
|
24
25
|
import { getCenter, getDistance } from "../gesture";
|
|
25
26
|
import { editGroupForSelectedElement, getElementsInGroup, getSelectedGroupIdForElement, getSelectedGroupIds, isElementInGroup, isSelectedViaGroup, selectGroupsForSelectedElements, } from "../groups";
|
|
26
|
-
import History from "../history";
|
|
27
|
+
import { History } from "../history";
|
|
27
28
|
import { defaultLang, getLanguage, languages, setLanguage, t } from "../i18n";
|
|
28
29
|
import { CODES, shouldResizeFromCenter, shouldMaintainAspectRatio, shouldRotateWithDiscreteAngle, isArrowKey, KEYS, } from "../keys";
|
|
29
30
|
import { isElementInViewport } from "../element/sizeHelpers";
|
|
@@ -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
|
-
import { debounce, distance, getFontString, getNearestScrollableContainer, isInputLike, isToolIcon, isWritableElement, sceneCoordsToViewportCoords, tupleToCoors, viewportCoordsToSceneCoords, wrapEvent, updateObject, updateActiveTool, getShortcutKey, isTransparent, easeToValuesRAF, muteFSAbortError, isTestEnv, easeOut,
|
|
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";
|
|
@@ -78,17 +79,21 @@ import { ElementCanvasButton } from "./MagicButton";
|
|
|
78
79
|
import { MagicIcon, copyIcon, fullscreenIcon } from "./icons";
|
|
79
80
|
import { EditorLocalStorage } from "../data/EditorLocalStorage";
|
|
80
81
|
import FollowMode from "./FollowMode/FollowMode";
|
|
82
|
+
import { Store, StoreAction } from "../store";
|
|
81
83
|
import { AnimationFrameHandler } from "../animation-frame-handler";
|
|
82
84
|
import { AnimatedTrail } from "../animated-trail";
|
|
83
85
|
import { LaserTrails } from "../laser-trails";
|
|
84
86
|
import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils";
|
|
85
87
|
import { getRenderOpacity } from "../renderer/renderElement";
|
|
86
|
-
import { hitElementBoundText,
|
|
88
|
+
import { hitElementBoundText, hitElementBoundingBoxOnly, hitElementItself, } from "../element/collision";
|
|
87
89
|
import { textWysiwyg } from "../element/textWysiwyg";
|
|
88
90
|
import { isOverScrollBars } from "../scene/scrollbars";
|
|
89
91
|
import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex";
|
|
90
92
|
import { isPointHittingLink, isPointHittingLinkIcon, } from "./hyperlink/helpers";
|
|
91
93
|
import { getShortcutFromShortcutName } from "../actions/shortcuts";
|
|
94
|
+
import { actionTextAutoResize } from "../actions/actionTextAutoResize";
|
|
95
|
+
import { getVisibleSceneBounds } from "../element/bounds";
|
|
96
|
+
import { isMaybeMermaidDefinition } from "../mermaid";
|
|
92
97
|
const AppContext = React.createContext(null);
|
|
93
98
|
const AppPropsContext = React.createContext(null);
|
|
94
99
|
const deviceContextInitialValue = {
|
|
@@ -168,6 +173,7 @@ class App extends React.Component {
|
|
|
168
173
|
library;
|
|
169
174
|
libraryItemsFromStorage;
|
|
170
175
|
id;
|
|
176
|
+
store;
|
|
171
177
|
history;
|
|
172
178
|
excalidrawContainerValue;
|
|
173
179
|
files = {};
|
|
@@ -239,6 +245,8 @@ class App extends React.Component {
|
|
|
239
245
|
this.canvas = document.createElement("canvas");
|
|
240
246
|
this.rc = rough.canvas(this.canvas);
|
|
241
247
|
this.renderer = new Renderer(this.scene);
|
|
248
|
+
this.store = new Store();
|
|
249
|
+
this.history = new History();
|
|
242
250
|
if (excalidrawAPI) {
|
|
243
251
|
const api = {
|
|
244
252
|
updateScene: this.updateScene,
|
|
@@ -282,14 +290,11 @@ class App extends React.Component {
|
|
|
282
290
|
container: this.excalidrawContainerRef.current,
|
|
283
291
|
id: this.id,
|
|
284
292
|
};
|
|
285
|
-
this.fonts = new Fonts({
|
|
286
|
-
scene: this.scene,
|
|
287
|
-
onSceneUpdated: this.onSceneUpdated,
|
|
288
|
-
});
|
|
293
|
+
this.fonts = new Fonts({ scene: this.scene });
|
|
289
294
|
this.history = new History();
|
|
290
295
|
this.actionManager.registerAll(actions);
|
|
291
|
-
this.actionManager.registerAction(createUndoAction(this.history));
|
|
292
|
-
this.actionManager.registerAction(createRedoAction(this.history));
|
|
296
|
+
this.actionManager.registerAction(createUndoAction(this.history, this.store));
|
|
297
|
+
this.actionManager.registerAction(createRedoAction(this.history, this.store));
|
|
293
298
|
}
|
|
294
299
|
onWindowMessage(event) {
|
|
295
300
|
if (event.origin !== "https://player.vimeo.com" &&
|
|
@@ -440,7 +445,7 @@ class App extends React.Component {
|
|
|
440
445
|
return false;
|
|
441
446
|
});
|
|
442
447
|
if (updated) {
|
|
443
|
-
this.scene.
|
|
448
|
+
this.scene.triggerUpdate();
|
|
444
449
|
}
|
|
445
450
|
// GC
|
|
446
451
|
this.iFrameRefs.forEach((ref, id) => {
|
|
@@ -799,9 +804,9 @@ class App extends React.Component {
|
|
|
799
804
|
render() {
|
|
800
805
|
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
801
806
|
const { renderTopRightUI, renderCustomStats } = this.props;
|
|
802
|
-
const
|
|
807
|
+
const sceneNonce = this.scene.getSceneNonce();
|
|
803
808
|
const { elementsMap, visibleElements } = this.renderer.getRenderableElements({
|
|
804
|
-
|
|
809
|
+
sceneNonce,
|
|
805
810
|
zoom: this.state.zoom,
|
|
806
811
|
offsetLeft: this.state.offsetLeft,
|
|
807
812
|
offsetTop: this.state.offsetTop,
|
|
@@ -870,14 +875,14 @@ class App extends React.Component {
|
|
|
870
875
|
this.focusContainer();
|
|
871
876
|
callback?.();
|
|
872
877
|
});
|
|
873
|
-
} })), _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: {
|
|
874
879
|
imageCache: this.imageCache,
|
|
875
880
|
isExporting: false,
|
|
876
881
|
renderGrid: true,
|
|
877
882
|
canvasBackgroundColor: this.state.viewBackgroundColor,
|
|
878
883
|
embedsValidationStatus: this.embedsValidationStatus,
|
|
879
884
|
elementsPendingErasure: this.elementsPendingErasure,
|
|
880
|
-
} }), _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()] }) }) }) }) }) }) }) }));
|
|
881
886
|
}
|
|
882
887
|
focusContainer = () => {
|
|
883
888
|
this.excalidrawContainerRef.current?.focus();
|
|
@@ -927,7 +932,7 @@ class App extends React.Component {
|
|
|
927
932
|
mutateElement(frameElement, { customData: { generationData: data } }, false);
|
|
928
933
|
}
|
|
929
934
|
this.magicGenerations.set(frameElement.id, data);
|
|
930
|
-
this.
|
|
935
|
+
this.triggerRender();
|
|
931
936
|
};
|
|
932
937
|
getTextFromElements(elements) {
|
|
933
938
|
const text = elements
|
|
@@ -1149,13 +1154,13 @@ class App extends React.Component {
|
|
|
1149
1154
|
if (shouldUpdateStrokeColor) {
|
|
1150
1155
|
this.syncActionResult({
|
|
1151
1156
|
appState: { ...this.state, currentItemStrokeColor: color },
|
|
1152
|
-
|
|
1157
|
+
storeAction: StoreAction.CAPTURE,
|
|
1153
1158
|
});
|
|
1154
1159
|
}
|
|
1155
1160
|
else {
|
|
1156
1161
|
this.syncActionResult({
|
|
1157
1162
|
appState: { ...this.state, currentItemBackgroundColor: color },
|
|
1158
|
-
|
|
1163
|
+
storeAction: StoreAction.CAPTURE,
|
|
1159
1164
|
});
|
|
1160
1165
|
}
|
|
1161
1166
|
}
|
|
@@ -1169,6 +1174,7 @@ class App extends React.Component {
|
|
|
1169
1174
|
}
|
|
1170
1175
|
return el;
|
|
1171
1176
|
}),
|
|
1177
|
+
storeAction: StoreAction.CAPTURE,
|
|
1172
1178
|
});
|
|
1173
1179
|
}
|
|
1174
1180
|
},
|
|
@@ -1179,6 +1185,13 @@ class App extends React.Component {
|
|
|
1179
1185
|
if (this.unmounted || actionResult === false) {
|
|
1180
1186
|
return;
|
|
1181
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;
|
|
1182
1195
|
let editingElement = null;
|
|
1183
1196
|
if (actionResult.elements) {
|
|
1184
1197
|
actionResult.elements.forEach((element) => {
|
|
@@ -1189,9 +1202,7 @@ class App extends React.Component {
|
|
|
1189
1202
|
}
|
|
1190
1203
|
});
|
|
1191
1204
|
this.scene.replaceAllElements(actionResult.elements);
|
|
1192
|
-
|
|
1193
|
-
this.history.resumeRecording();
|
|
1194
|
-
}
|
|
1205
|
+
didUpdate = true;
|
|
1195
1206
|
}
|
|
1196
1207
|
if (actionResult.files) {
|
|
1197
1208
|
this.files = actionResult.replaceFiles
|
|
@@ -1200,9 +1211,6 @@ class App extends React.Component {
|
|
|
1200
1211
|
this.addNewImagesToImageCache();
|
|
1201
1212
|
}
|
|
1202
1213
|
if (actionResult.appState || editingElement || this.state.contextMenu) {
|
|
1203
|
-
if (actionResult.commitToHistory) {
|
|
1204
|
-
this.history.resumeRecording();
|
|
1205
|
-
}
|
|
1206
1214
|
let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
|
|
1207
1215
|
let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
|
|
1208
1216
|
let gridSize = actionResult?.appState?.gridSize || null;
|
|
@@ -1240,11 +1248,11 @@ class App extends React.Component {
|
|
|
1240
1248
|
name,
|
|
1241
1249
|
errorMessage,
|
|
1242
1250
|
});
|
|
1243
|
-
}, () => {
|
|
1244
|
-
if (actionResult.syncHistory) {
|
|
1245
|
-
this.history.setCurrentState(this.state, this.scene.getElementsIncludingDeleted());
|
|
1246
|
-
}
|
|
1247
1251
|
});
|
|
1252
|
+
didUpdate = true;
|
|
1253
|
+
}
|
|
1254
|
+
if (!didUpdate && actionResult.storeAction !== StoreAction.NONE) {
|
|
1255
|
+
this.scene.triggerUpdate();
|
|
1248
1256
|
}
|
|
1249
1257
|
});
|
|
1250
1258
|
// Lifecycle
|
|
@@ -1261,6 +1269,9 @@ class App extends React.Component {
|
|
|
1261
1269
|
resetHistory = () => {
|
|
1262
1270
|
this.history.clear();
|
|
1263
1271
|
};
|
|
1272
|
+
resetStore = () => {
|
|
1273
|
+
this.store.clear();
|
|
1274
|
+
};
|
|
1264
1275
|
/**
|
|
1265
1276
|
* Resets scene & history.
|
|
1266
1277
|
* ! Do not use to clear scene user action !
|
|
@@ -1272,6 +1283,7 @@ class App extends React.Component {
|
|
|
1272
1283
|
isLoading: opts?.resetLoadingState ? false : state.isLoading,
|
|
1273
1284
|
theme: this.state.theme,
|
|
1274
1285
|
}));
|
|
1286
|
+
this.resetStore();
|
|
1275
1287
|
this.resetHistory();
|
|
1276
1288
|
});
|
|
1277
1289
|
initializeScene = async () => {
|
|
@@ -1293,7 +1305,12 @@ class App extends React.Component {
|
|
|
1293
1305
|
}
|
|
1294
1306
|
let initialData = null;
|
|
1295
1307
|
try {
|
|
1296
|
-
|
|
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
|
+
}
|
|
1297
1314
|
if (initialData?.libraryItems) {
|
|
1298
1315
|
this.library
|
|
1299
1316
|
.updateLibrary({
|
|
@@ -1346,10 +1363,11 @@ class App extends React.Component {
|
|
|
1346
1363
|
// text elements on canvas, and rerender them once done. This also
|
|
1347
1364
|
// seems faster even in browsers that do fire the loadingdone event.
|
|
1348
1365
|
this.fonts.loadFontsForElements(scene.elements);
|
|
1366
|
+
this.resetStore();
|
|
1349
1367
|
this.resetHistory();
|
|
1350
1368
|
this.syncActionResult({
|
|
1351
1369
|
...scene,
|
|
1352
|
-
|
|
1370
|
+
storeAction: StoreAction.UPDATE,
|
|
1353
1371
|
});
|
|
1354
1372
|
};
|
|
1355
1373
|
isMobileBreakpoint = (width, height) => {
|
|
@@ -1420,9 +1438,16 @@ class App extends React.Component {
|
|
|
1420
1438
|
configurable: true,
|
|
1421
1439
|
value: this.history,
|
|
1422
1440
|
},
|
|
1441
|
+
store: {
|
|
1442
|
+
configurable: true,
|
|
1443
|
+
value: this.store,
|
|
1444
|
+
},
|
|
1423
1445
|
});
|
|
1424
1446
|
}
|
|
1425
|
-
this.
|
|
1447
|
+
this.store.onStoreIncrementEmitter.on((increment) => {
|
|
1448
|
+
this.history.record(increment.elementsChange, increment.appStateChange);
|
|
1449
|
+
});
|
|
1450
|
+
this.scene.onUpdate(this.triggerRender);
|
|
1426
1451
|
this.addEventListeners();
|
|
1427
1452
|
if (this.props.autoFocus && this.excalidrawContainerRef.current) {
|
|
1428
1453
|
this.focusContainer();
|
|
@@ -1458,19 +1483,22 @@ class App extends React.Component {
|
|
|
1458
1483
|
}
|
|
1459
1484
|
}
|
|
1460
1485
|
componentWillUnmount() {
|
|
1486
|
+
window.launchQueue?.setConsumer(() => { });
|
|
1461
1487
|
this.renderer.destroy();
|
|
1488
|
+
this.scene.destroy();
|
|
1462
1489
|
this.scene = new Scene();
|
|
1490
|
+
this.fonts = new Fonts({ scene: this.scene });
|
|
1463
1491
|
this.renderer = new Renderer(this.scene);
|
|
1464
1492
|
this.files = {};
|
|
1465
1493
|
this.imageCache.clear();
|
|
1466
1494
|
this.resizeObserver?.disconnect();
|
|
1467
1495
|
this.unmounted = true;
|
|
1468
1496
|
this.removeEventListeners();
|
|
1469
|
-
this.scene.destroy();
|
|
1470
1497
|
this.library.destroy();
|
|
1471
1498
|
this.laserTrails.stop();
|
|
1472
1499
|
this.eraserTrail.stop();
|
|
1473
1500
|
this.onChangeEmitter.clear();
|
|
1501
|
+
this.store.onStoreIncrementEmitter.clear();
|
|
1474
1502
|
ShapeCache.destroy();
|
|
1475
1503
|
SnapCache.destroy();
|
|
1476
1504
|
clearTimeout(touchTimeout);
|
|
@@ -1514,7 +1542,7 @@ class App extends React.Component {
|
|
|
1514
1542
|
this.onRemoveEventListenersEmitter.once(addEventListener(document, EVENT.KEYDOWN, this.onKeyDown, false));
|
|
1515
1543
|
}
|
|
1516
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
|
|
1517
|
-
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),
|
|
1518
1546
|
// rerender text elements on font load to fix #637 && #1553
|
|
1519
1547
|
addEventListener(document.fonts, "loadingdone", (event) => {
|
|
1520
1548
|
const loadedFontFaces = event.fontfaces;
|
|
@@ -1523,6 +1551,9 @@ class App extends React.Component {
|
|
|
1523
1551
|
// Safari-only desktop pinch zoom
|
|
1524
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, () => {
|
|
1525
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);
|
|
1526
1557
|
}));
|
|
1527
1558
|
if (this.state.viewModeEnabled) {
|
|
1528
1559
|
return;
|
|
@@ -1538,7 +1569,8 @@ class App extends React.Component {
|
|
|
1538
1569
|
componentDidUpdate(prevProps, prevState) {
|
|
1539
1570
|
this.updateEmbeddables();
|
|
1540
1571
|
const elements = this.scene.getElementsIncludingDeleted();
|
|
1541
|
-
const elementsMap = this.scene.
|
|
1572
|
+
const elementsMap = this.scene.getElementsMapIncludingDeleted();
|
|
1573
|
+
const nonDeletedElementsMap = this.scene.getNonDeletedElementsMap();
|
|
1542
1574
|
if (!this.state.showWelcomeScreen && !elements.length) {
|
|
1543
1575
|
this.setState({ showWelcomeScreen: true });
|
|
1544
1576
|
}
|
|
@@ -1614,7 +1646,7 @@ class App extends React.Component {
|
|
|
1614
1646
|
this.excalidrawContainerRef.current?.classList.toggle("theme--dark", this.state.theme === THEME.DARK);
|
|
1615
1647
|
if (this.state.editingLinearElement &&
|
|
1616
1648
|
!this.state.selectedElementIds[this.state.editingLinearElement.elementId]) {
|
|
1617
|
-
// defer so that the
|
|
1649
|
+
// defer so that the storeAction flag isn't reset via current update
|
|
1618
1650
|
setTimeout(() => {
|
|
1619
1651
|
// execute only if the condition still holds when the deferred callback
|
|
1620
1652
|
// executes (it can be scheduled multiple times depending on how
|
|
@@ -1639,9 +1671,9 @@ class App extends React.Component {
|
|
|
1639
1671
|
multiElement != null &&
|
|
1640
1672
|
isBindingEnabled(this.state) &&
|
|
1641
1673
|
isBindingElement(multiElement, false)) {
|
|
1642
|
-
maybeBindLinearElement(multiElement, this.state, tupleToCoors(LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1,
|
|
1674
|
+
maybeBindLinearElement(multiElement, this.state, tupleToCoors(LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, nonDeletedElementsMap)), this.scene.getNonDeletedElementsMap());
|
|
1643
1675
|
}
|
|
1644
|
-
this.
|
|
1676
|
+
this.store.commit(elementsMap, this.state);
|
|
1645
1677
|
// Do not notify consumers if we're still loading the scene. Among other
|
|
1646
1678
|
// potential issues, this fixes a case where the tab isn't focused during
|
|
1647
1679
|
// init, which would trigger onChange with empty elements, which would then
|
|
@@ -1828,6 +1860,26 @@ class App extends React.Component {
|
|
|
1828
1860
|
});
|
|
1829
1861
|
}
|
|
1830
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
|
+
}
|
|
1831
1883
|
const nonEmptyLines = normalizeEOL(data.text)
|
|
1832
1884
|
.split(/\n+/)
|
|
1833
1885
|
.map((s) => s.trim())
|
|
@@ -1915,7 +1967,7 @@ class App extends React.Component {
|
|
|
1915
1967
|
if (opts.files) {
|
|
1916
1968
|
this.files = { ...this.files, ...opts.files };
|
|
1917
1969
|
}
|
|
1918
|
-
this.
|
|
1970
|
+
this.store.shouldCaptureIncrement();
|
|
1919
1971
|
const nextElementsToSelect = excludeElementsInFramesFromSelection(newElements);
|
|
1920
1972
|
this.setState({
|
|
1921
1973
|
...this.state,
|
|
@@ -2032,27 +2084,46 @@ class App extends React.Component {
|
|
|
2032
2084
|
text,
|
|
2033
2085
|
fontSize: this.state.currentItemFontSize,
|
|
2034
2086
|
fontFamily: this.state.currentItemFontFamily,
|
|
2035
|
-
textAlign:
|
|
2087
|
+
textAlign: DEFAULT_TEXT_ALIGN,
|
|
2036
2088
|
verticalAlign: DEFAULT_VERTICAL_ALIGN,
|
|
2037
2089
|
locked: false,
|
|
2038
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);
|
|
2039
2099
|
const LINE_GAP = 10;
|
|
2040
2100
|
let currentY = y;
|
|
2041
2101
|
const lines = isPlainPaste ? [text] : text.split("\n");
|
|
2042
2102
|
const textElements = lines.reduce((acc, line, idx) => {
|
|
2043
|
-
const
|
|
2044
|
-
|
|
2045
|
-
if (text.length) {
|
|
2103
|
+
const originalText = line.trim();
|
|
2104
|
+
if (originalText.length) {
|
|
2046
2105
|
const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
|
|
2047
2106
|
x,
|
|
2048
2107
|
y: currentY,
|
|
2049
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;
|
|
2050
2119
|
const element = newTextElement({
|
|
2051
2120
|
...textElementProps,
|
|
2052
|
-
x,
|
|
2053
|
-
y:
|
|
2121
|
+
x: startX,
|
|
2122
|
+
y: startY,
|
|
2054
2123
|
text,
|
|
2124
|
+
originalText,
|
|
2055
2125
|
lineHeight,
|
|
2126
|
+
autoResize: !isTextWrapped,
|
|
2056
2127
|
frameId: topLayerFrame ? topLayerFrame.id : null,
|
|
2057
2128
|
});
|
|
2058
2129
|
acc.push(element);
|
|
@@ -2089,7 +2160,7 @@ class App extends React.Component {
|
|
|
2089
2160
|
});
|
|
2090
2161
|
PLAIN_PASTE_TOAST_SHOWN = true;
|
|
2091
2162
|
}
|
|
2092
|
-
this.
|
|
2163
|
+
this.store.shouldCaptureIncrement();
|
|
2093
2164
|
}
|
|
2094
2165
|
setAppState = (state, callback) => {
|
|
2095
2166
|
this.setState(state, callback);
|
|
@@ -2271,25 +2342,49 @@ class App extends React.Component {
|
|
|
2271
2342
|
ShapeCache.delete(element);
|
|
2272
2343
|
}
|
|
2273
2344
|
});
|
|
2274
|
-
this.scene.
|
|
2345
|
+
this.scene.triggerUpdate();
|
|
2275
2346
|
this.addNewImagesToImageCache();
|
|
2276
2347
|
});
|
|
2277
2348
|
updateScene = withBatchedUpdates((sceneData) => {
|
|
2278
|
-
|
|
2279
|
-
|
|
2349
|
+
const nextElements = syncInvalidIndices(sceneData.elements ?? []);
|
|
2350
|
+
if (sceneData.storeAction && sceneData.storeAction !== StoreAction.NONE) {
|
|
2351
|
+
const prevCommittedAppState = this.store.snapshot.appState;
|
|
2352
|
+
const prevCommittedElements = this.store.snapshot.elements;
|
|
2353
|
+
const nextCommittedAppState = sceneData.appState
|
|
2354
|
+
? Object.assign({}, prevCommittedAppState, sceneData.appState) // new instance, with partial appstate applied to previously captured one, including hidden prop inside `prevCommittedAppState`
|
|
2355
|
+
: prevCommittedAppState;
|
|
2356
|
+
const nextCommittedElements = sceneData.elements
|
|
2357
|
+
? this.store.filterUncomittedElements(this.scene.getElementsMapIncludingDeleted(), // Only used to detect uncomitted local elements
|
|
2358
|
+
arrayToMap(nextElements))
|
|
2359
|
+
: prevCommittedElements;
|
|
2360
|
+
// WARN: store action always performs deep clone of changed elements, for ephemeral remote updates (i.e. remote dragging, resizing, drawing) we might consider doing something smarter
|
|
2361
|
+
// do NOT schedule store actions (execute after re-render), as it might cause unexpected concurrency issues if not handled well
|
|
2362
|
+
if (sceneData.storeAction === StoreAction.CAPTURE) {
|
|
2363
|
+
this.store.captureIncrement(nextCommittedElements, nextCommittedAppState);
|
|
2364
|
+
}
|
|
2365
|
+
else if (sceneData.storeAction === StoreAction.UPDATE) {
|
|
2366
|
+
this.store.updateSnapshot(nextCommittedElements, nextCommittedAppState);
|
|
2367
|
+
}
|
|
2280
2368
|
}
|
|
2281
2369
|
if (sceneData.appState) {
|
|
2282
2370
|
this.setState(sceneData.appState);
|
|
2283
2371
|
}
|
|
2284
2372
|
if (sceneData.elements) {
|
|
2285
|
-
this.scene.replaceAllElements(
|
|
2373
|
+
this.scene.replaceAllElements(nextElements);
|
|
2286
2374
|
}
|
|
2287
2375
|
if (sceneData.collaborators) {
|
|
2288
2376
|
this.setState({ collaborators: sceneData.collaborators });
|
|
2289
2377
|
}
|
|
2290
2378
|
});
|
|
2291
|
-
|
|
2292
|
-
|
|
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
|
+
}
|
|
2293
2388
|
};
|
|
2294
2389
|
/**
|
|
2295
2390
|
* @returns whether the menu was toggled on or off
|
|
@@ -2456,7 +2551,9 @@ class App extends React.Component {
|
|
|
2456
2551
|
simultaneouslyUpdated: selectedElements,
|
|
2457
2552
|
});
|
|
2458
2553
|
});
|
|
2459
|
-
this.
|
|
2554
|
+
this.setState({
|
|
2555
|
+
suggestedBindings: getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap()),
|
|
2556
|
+
});
|
|
2460
2557
|
event.preventDefault();
|
|
2461
2558
|
}
|
|
2462
2559
|
else if (event.key === KEYS.ENTER) {
|
|
@@ -2468,7 +2565,7 @@ class App extends React.Component {
|
|
|
2468
2565
|
if (!this.state.editingLinearElement ||
|
|
2469
2566
|
this.state.editingLinearElement.elementId !==
|
|
2470
2567
|
selectedElements[0].id) {
|
|
2471
|
-
this.
|
|
2568
|
+
this.store.shouldCaptureIncrement();
|
|
2472
2569
|
this.setState({
|
|
2473
2570
|
editingLinearElement: new LinearElementEditor(selectedElement),
|
|
2474
2571
|
});
|
|
@@ -2594,11 +2691,7 @@ class App extends React.Component {
|
|
|
2594
2691
|
this.setState({ isBindingEnabled: true });
|
|
2595
2692
|
}
|
|
2596
2693
|
if (isArrowKey(event.key)) {
|
|
2597
|
-
|
|
2598
|
-
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
2599
|
-
isBindingEnabled(this.state)
|
|
2600
|
-
? bindOrUnbindSelectedElements(selectedElements, this)
|
|
2601
|
-
: unbindLinearElements(selectedElements, elementsMap);
|
|
2694
|
+
bindOrUnbindLinearElements(this.scene.getSelectedElements(this.state).filter(isLinearElement), this.scene.getNonDeletedElementsMap(), isBindingEnabled(this.state), this.state.selectedLinearElement?.selectedPointsIndices ?? []);
|
|
2602
2695
|
this.setState({ suggestedBindings: [] });
|
|
2603
2696
|
}
|
|
2604
2697
|
});
|
|
@@ -2636,6 +2729,9 @@ class App extends React.Component {
|
|
|
2636
2729
|
originSnapOffset: null,
|
|
2637
2730
|
activeEmbeddable: null,
|
|
2638
2731
|
};
|
|
2732
|
+
if (nextActiveTool.type === "freedraw") {
|
|
2733
|
+
this.store.shouldCaptureIncrement();
|
|
2734
|
+
}
|
|
2639
2735
|
if (nextActiveTool.type !== "selection") {
|
|
2640
2736
|
return {
|
|
2641
2737
|
...prevState,
|
|
@@ -2733,15 +2829,16 @@ class App extends React.Component {
|
|
|
2733
2829
|
});
|
|
2734
2830
|
handleTextWysiwyg(element, { isExistingElement = false, }) {
|
|
2735
2831
|
const elementsMap = this.scene.getElementsMapIncludingDeleted();
|
|
2736
|
-
const updateElement = (
|
|
2832
|
+
const updateElement = (nextOriginalText, isDeleted) => {
|
|
2737
2833
|
this.scene.replaceAllElements([
|
|
2738
2834
|
// Not sure why we include deleted elements as well hence using deleted elements map
|
|
2739
2835
|
...this.scene.getElementsIncludingDeleted().map((_element) => {
|
|
2740
2836
|
if (_element.id === element.id && isTextElement(_element)) {
|
|
2741
|
-
return
|
|
2742
|
-
|
|
2743
|
-
isDeleted,
|
|
2744
|
-
|
|
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),
|
|
2745
2842
|
});
|
|
2746
2843
|
}
|
|
2747
2844
|
return _element;
|
|
@@ -2761,15 +2858,15 @@ class App extends React.Component {
|
|
|
2761
2858
|
viewportY - this.state.offsetTop,
|
|
2762
2859
|
];
|
|
2763
2860
|
},
|
|
2764
|
-
onChange: withBatchedUpdates((
|
|
2765
|
-
updateElement(
|
|
2861
|
+
onChange: withBatchedUpdates((nextOriginalText) => {
|
|
2862
|
+
updateElement(nextOriginalText, false);
|
|
2766
2863
|
if (isNonDeletedElement(element)) {
|
|
2767
2864
|
updateBoundElements(element, elementsMap);
|
|
2768
2865
|
}
|
|
2769
2866
|
}),
|
|
2770
|
-
onSubmit: withBatchedUpdates(({
|
|
2771
|
-
const isDeleted = !
|
|
2772
|
-
updateElement(
|
|
2867
|
+
onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
|
|
2868
|
+
const isDeleted = !nextOriginalText.trim();
|
|
2869
|
+
updateElement(nextOriginalText, isDeleted);
|
|
2773
2870
|
// select the created text element only if submitting via keyboard
|
|
2774
2871
|
// (when submitting via click it should act as signal to deselect)
|
|
2775
2872
|
if (!isDeleted && viaKeyboard) {
|
|
@@ -2789,7 +2886,7 @@ class App extends React.Component {
|
|
|
2789
2886
|
]);
|
|
2790
2887
|
}
|
|
2791
2888
|
if (!isDeleted || isExistingElement) {
|
|
2792
|
-
this.
|
|
2889
|
+
this.store.shouldCaptureIncrement();
|
|
2793
2890
|
}
|
|
2794
2891
|
this.setState({
|
|
2795
2892
|
draggingElement: null,
|
|
@@ -2803,12 +2900,17 @@ class App extends React.Component {
|
|
|
2803
2900
|
element,
|
|
2804
2901
|
excalidrawContainer: this.excalidrawContainerRef.current,
|
|
2805
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,
|
|
2806
2908
|
});
|
|
2807
2909
|
// deselect all other elements when inserting text
|
|
2808
2910
|
this.deselectElements();
|
|
2809
2911
|
// do an initial update to re-initialize element position since we were
|
|
2810
2912
|
// modifying element's x/y for sake of editor (case: syncing to remote)
|
|
2811
|
-
updateElement(element.
|
|
2913
|
+
updateElement(element.originalText, false);
|
|
2812
2914
|
}
|
|
2813
2915
|
deselectElements() {
|
|
2814
2916
|
this.setState({
|
|
@@ -2827,54 +2929,18 @@ class App extends React.Component {
|
|
|
2827
2929
|
}
|
|
2828
2930
|
return null;
|
|
2829
2931
|
}
|
|
2830
|
-
/**
|
|
2831
|
-
* get the pure geometric shape of an excalidraw element
|
|
2832
|
-
* which is then used for hit detection
|
|
2833
|
-
*/
|
|
2834
|
-
getElementShape(element) {
|
|
2835
|
-
switch (element.type) {
|
|
2836
|
-
case "rectangle":
|
|
2837
|
-
case "diamond":
|
|
2838
|
-
case "frame":
|
|
2839
|
-
case "magicframe":
|
|
2840
|
-
case "embeddable":
|
|
2841
|
-
case "image":
|
|
2842
|
-
case "iframe":
|
|
2843
|
-
case "text":
|
|
2844
|
-
case "selection":
|
|
2845
|
-
return getPolygonShape(element);
|
|
2846
|
-
case "arrow":
|
|
2847
|
-
case "line": {
|
|
2848
|
-
const roughShape = ShapeCache.get(element)?.[0] ??
|
|
2849
|
-
ShapeCache.generateElementShape(element, null)[0];
|
|
2850
|
-
const [, , , , cx, cy] = getElementAbsoluteCoords(element, this.scene.getNonDeletedElementsMap());
|
|
2851
|
-
return shouldTestInside(element)
|
|
2852
|
-
? getClosedCurveShape(element, roughShape, [element.x, element.y], element.angle, [cx, cy])
|
|
2853
|
-
: getCurveShape(roughShape, [element.x, element.y], element.angle, [
|
|
2854
|
-
cx,
|
|
2855
|
-
cy,
|
|
2856
|
-
]);
|
|
2857
|
-
}
|
|
2858
|
-
case "ellipse":
|
|
2859
|
-
return getEllipseShape(element);
|
|
2860
|
-
case "freedraw": {
|
|
2861
|
-
const [, , , , cx, cy] = getElementAbsoluteCoords(element, this.scene.getNonDeletedElementsMap());
|
|
2862
|
-
return getFreedrawShape(element, [cx, cy], shouldTestInside(element));
|
|
2863
|
-
}
|
|
2864
|
-
}
|
|
2865
|
-
}
|
|
2866
2932
|
getBoundTextShape(element) {
|
|
2867
2933
|
const boundTextElement = getBoundTextElement(element, this.scene.getNonDeletedElementsMap());
|
|
2868
2934
|
if (boundTextElement) {
|
|
2869
2935
|
if (element.type === "arrow") {
|
|
2870
|
-
return
|
|
2936
|
+
return getElementShape({
|
|
2871
2937
|
...boundTextElement,
|
|
2872
2938
|
// arrow's bound text accurate position is not stored in the element's property
|
|
2873
2939
|
// but rather calculated and returned from the following static method
|
|
2874
2940
|
...LinearElementEditor.getBoundTextElementPosition(element, boundTextElement, this.scene.getNonDeletedElementsMap()),
|
|
2875
|
-
});
|
|
2941
|
+
}, this.scene.getNonDeletedElementsMap());
|
|
2876
2942
|
}
|
|
2877
|
-
return this.
|
|
2943
|
+
return getElementShape(boundTextElement, this.scene.getNonDeletedElementsMap());
|
|
2878
2944
|
}
|
|
2879
2945
|
return null;
|
|
2880
2946
|
}
|
|
@@ -2891,7 +2957,18 @@ class App extends React.Component {
|
|
|
2891
2957
|
const elementWithHighestZIndex = allHitElements[allHitElements.length - 1];
|
|
2892
2958
|
// If we're hitting element with highest z-index only on its bounding box
|
|
2893
2959
|
// while also hitting other element figure, the latter should be considered.
|
|
2894
|
-
return
|
|
2960
|
+
return hitElementItself({
|
|
2961
|
+
x,
|
|
2962
|
+
y,
|
|
2963
|
+
element: elementWithHighestZIndex,
|
|
2964
|
+
shape: getElementShape(elementWithHighestZIndex, this.scene.getNonDeletedElementsMap()),
|
|
2965
|
+
// when overlapping, we would like to be more precise
|
|
2966
|
+
// this also avoids the need to update past tests
|
|
2967
|
+
threshold: this.getElementHitThreshold() / 2,
|
|
2968
|
+
frameNameBound: isFrameLikeElement(elementWithHighestZIndex)
|
|
2969
|
+
? this.frameNameBoundsCache.get(elementWithHighestZIndex)
|
|
2970
|
+
: null,
|
|
2971
|
+
})
|
|
2895
2972
|
? elementWithHighestZIndex
|
|
2896
2973
|
: allHitElements[allHitElements.length - 2];
|
|
2897
2974
|
}
|
|
@@ -2934,15 +3011,16 @@ class App extends React.Component {
|
|
|
2934
3011
|
.concat(iframeLikes);
|
|
2935
3012
|
return elements;
|
|
2936
3013
|
}
|
|
2937
|
-
|
|
2938
|
-
return
|
|
3014
|
+
getElementHitThreshold() {
|
|
3015
|
+
return DEFAULT_COLLISION_THRESHOLD / this.state.zoom.value;
|
|
2939
3016
|
}
|
|
2940
3017
|
hitElement(x, y, element, considerBoundingBox = true) {
|
|
2941
3018
|
// if the element is selected, then hit test is done against its bounding box
|
|
2942
3019
|
if (considerBoundingBox &&
|
|
2943
3020
|
this.state.selectedElementIds[element.id] &&
|
|
2944
3021
|
shouldShowBoundingBox([element], this.state)) {
|
|
2945
|
-
|
|
3022
|
+
const selectionShape = getSelectionBoxShape(element, this.scene.getNonDeletedElementsMap(), this.getElementHitThreshold());
|
|
3023
|
+
return isPointInShape([x, y], selectionShape);
|
|
2946
3024
|
}
|
|
2947
3025
|
// take bound text element into consideration for hit collision as well
|
|
2948
3026
|
const hitBoundTextOfElement = hitElementBoundText(x, y, this.getBoundTextShape(element));
|
|
@@ -2953,8 +3031,8 @@ class App extends React.Component {
|
|
|
2953
3031
|
x,
|
|
2954
3032
|
y,
|
|
2955
3033
|
element,
|
|
2956
|
-
shape: this.
|
|
2957
|
-
threshold: this.
|
|
3034
|
+
shape: getElementShape(element, this.scene.getNonDeletedElementsMap()),
|
|
3035
|
+
threshold: this.getElementHitThreshold(),
|
|
2958
3036
|
frameNameBound: isFrameLikeElement(element)
|
|
2959
3037
|
? this.frameNameBoundsCache.get(element)
|
|
2960
3038
|
: null,
|
|
@@ -2980,8 +3058,8 @@ class App extends React.Component {
|
|
|
2980
3058
|
x,
|
|
2981
3059
|
y,
|
|
2982
3060
|
element: elements[index],
|
|
2983
|
-
shape:
|
|
2984
|
-
threshold: this.
|
|
3061
|
+
shape: getElementShape(elements[index], this.scene.getNonDeletedElementsMap()),
|
|
3062
|
+
threshold: this.getElementHitThreshold(),
|
|
2985
3063
|
})) {
|
|
2986
3064
|
hitElement = elements[index];
|
|
2987
3065
|
break;
|
|
@@ -2993,7 +3071,7 @@ class App extends React.Component {
|
|
|
2993
3071
|
}
|
|
2994
3072
|
return isTextBindableContainer(hitElement, false) ? hitElement : null;
|
|
2995
3073
|
}
|
|
2996
|
-
startTextEditing = ({ sceneX, sceneY, insertAtParentCenter = true, container, }) => {
|
|
3074
|
+
startTextEditing = ({ sceneX, sceneY, insertAtParentCenter = true, container, autoEdit = true, }) => {
|
|
2997
3075
|
let shouldBindToContainer = false;
|
|
2998
3076
|
let parentCenterPosition = insertAtParentCenter &&
|
|
2999
3077
|
this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);
|
|
@@ -3094,12 +3172,17 @@ class App extends React.Component {
|
|
|
3094
3172
|
this.scene.insertElement(element);
|
|
3095
3173
|
}
|
|
3096
3174
|
}
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
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
|
+
}
|
|
3103
3186
|
};
|
|
3104
3187
|
handleCanvasDoubleClick = (event) => {
|
|
3105
3188
|
// case: double-clicking with arrow/line tool selected would both create
|
|
@@ -3116,7 +3199,7 @@ class App extends React.Component {
|
|
|
3116
3199
|
if (event[KEYS.CTRL_OR_CMD] &&
|
|
3117
3200
|
(!this.state.editingLinearElement ||
|
|
3118
3201
|
this.state.editingLinearElement.elementId !== selectedElements[0].id)) {
|
|
3119
|
-
this.
|
|
3202
|
+
this.store.shouldCaptureIncrement();
|
|
3120
3203
|
this.setState({
|
|
3121
3204
|
editingLinearElement: new LinearElementEditor(selectedElements[0]),
|
|
3122
3205
|
});
|
|
@@ -3131,6 +3214,7 @@ class App extends React.Component {
|
|
|
3131
3214
|
const selectedGroupId = hitElement &&
|
|
3132
3215
|
getSelectedGroupIdForElement(hitElement, this.state.selectedGroupIds);
|
|
3133
3216
|
if (selectedGroupId) {
|
|
3217
|
+
this.store.shouldCaptureIncrement();
|
|
3134
3218
|
this.setState((prevState) => ({
|
|
3135
3219
|
...prevState,
|
|
3136
3220
|
...selectGroupsForSelectedElements({
|
|
@@ -3158,8 +3242,8 @@ class App extends React.Component {
|
|
|
3158
3242
|
x: sceneX,
|
|
3159
3243
|
y: sceneY,
|
|
3160
3244
|
element: container,
|
|
3161
|
-
shape: this.
|
|
3162
|
-
threshold: this.
|
|
3245
|
+
shape: getElementShape(container, this.scene.getNonDeletedElementsMap()),
|
|
3246
|
+
threshold: this.getElementHitThreshold(),
|
|
3163
3247
|
})) {
|
|
3164
3248
|
const midPoint = getContainerCenter(container, this.state, this.scene.getNonDeletedElementsMap());
|
|
3165
3249
|
sceneX = midPoint.x;
|
|
@@ -3265,8 +3349,11 @@ class App extends React.Component {
|
|
|
3265
3349
|
}, state);
|
|
3266
3350
|
this.translateCanvas({
|
|
3267
3351
|
zoom: zoomState.zoom,
|
|
3268
|
-
|
|
3269
|
-
|
|
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),
|
|
3270
3357
|
shouldCacheIgnoreZoom: true,
|
|
3271
3358
|
});
|
|
3272
3359
|
});
|
|
@@ -3431,15 +3518,23 @@ class App extends React.Component {
|
|
|
3431
3518
|
if (selectedElements.length === 1 &&
|
|
3432
3519
|
!isOverScrollBar &&
|
|
3433
3520
|
!this.state.editingLinearElement) {
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3521
|
+
// for linear elements, we'd like to prioritize point dragging over edge resizing
|
|
3522
|
+
// therefore, we update and check hovered point index first
|
|
3523
|
+
if (this.state.selectedLinearElement) {
|
|
3524
|
+
this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);
|
|
3525
|
+
}
|
|
3526
|
+
if (!this.state.selectedLinearElement ||
|
|
3527
|
+
this.state.selectedLinearElement.hoverPointIndex === -1) {
|
|
3528
|
+
const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);
|
|
3529
|
+
if (elementWithTransformHandleType &&
|
|
3530
|
+
elementWithTransformHandleType.transformHandleType) {
|
|
3531
|
+
setCursor(this.interactiveCanvas, getCursorForResizingElement(elementWithTransformHandleType));
|
|
3532
|
+
return;
|
|
3533
|
+
}
|
|
3439
3534
|
}
|
|
3440
3535
|
}
|
|
3441
3536
|
else if (selectedElements.length > 1 && !isOverScrollBar) {
|
|
3442
|
-
const transformHandleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType);
|
|
3537
|
+
const transformHandleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.device);
|
|
3443
3538
|
if (transformHandleType) {
|
|
3444
3539
|
setCursor(this.interactiveCanvas, getCursorForResizingElement({
|
|
3445
3540
|
transformHandleType,
|
|
@@ -3543,7 +3638,7 @@ class App extends React.Component {
|
|
|
3543
3638
|
}
|
|
3544
3639
|
};
|
|
3545
3640
|
const distance = distance2d(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y, scenePointer.x, scenePointer.y);
|
|
3546
|
-
const threshold = this.
|
|
3641
|
+
const threshold = this.getElementHitThreshold();
|
|
3547
3642
|
const point = { ...pointerDownState.lastCoords };
|
|
3548
3643
|
let samplingInterval = 0;
|
|
3549
3644
|
while (samplingInterval <= distance) {
|
|
@@ -3579,7 +3674,7 @@ class App extends React.Component {
|
|
|
3579
3674
|
}
|
|
3580
3675
|
}
|
|
3581
3676
|
this.elementsPendingErasure = new Set(this.elementsPendingErasure);
|
|
3582
|
-
this.
|
|
3677
|
+
this.triggerRender();
|
|
3583
3678
|
}
|
|
3584
3679
|
};
|
|
3585
3680
|
// set touch moving for mobile context menu
|
|
@@ -3599,7 +3694,7 @@ class App extends React.Component {
|
|
|
3599
3694
|
x: scenePointerX,
|
|
3600
3695
|
y: scenePointerY,
|
|
3601
3696
|
element,
|
|
3602
|
-
shape: this.
|
|
3697
|
+
shape: getElementShape(element, this.scene.getNonDeletedElementsMap()),
|
|
3603
3698
|
})) {
|
|
3604
3699
|
hoverPointIndex = LinearElementEditor.getPointIndexUnderCursor(element, elementsMap, this.state.zoom, scenePointerX, scenePointerY);
|
|
3605
3700
|
segmentMidPointHoveredCoords =
|
|
@@ -3607,7 +3702,7 @@ class App extends React.Component {
|
|
|
3607
3702
|
if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {
|
|
3608
3703
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
|
3609
3704
|
}
|
|
3610
|
-
else {
|
|
3705
|
+
else if (this.hitElement(scenePointerX, scenePointerY, element)) {
|
|
3611
3706
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
|
3612
3707
|
}
|
|
3613
3708
|
}
|
|
@@ -3678,6 +3773,7 @@ class App extends React.Component {
|
|
|
3678
3773
|
return obj;
|
|
3679
3774
|
}, {}), this.state),
|
|
3680
3775
|
},
|
|
3776
|
+
storeAction: StoreAction.UPDATE,
|
|
3681
3777
|
});
|
|
3682
3778
|
return;
|
|
3683
3779
|
}
|
|
@@ -3789,7 +3885,6 @@ class App extends React.Component {
|
|
|
3789
3885
|
}
|
|
3790
3886
|
if (this.state.activeTool.type === "text") {
|
|
3791
3887
|
this.handleTextOnPointerDown(event, pointerDownState);
|
|
3792
|
-
return;
|
|
3793
3888
|
}
|
|
3794
3889
|
else if (this.state.activeTool.type === "arrow" ||
|
|
3795
3890
|
this.state.activeTool.type === "line") {
|
|
@@ -4117,8 +4212,11 @@ class App extends React.Component {
|
|
|
4117
4212
|
const elements = this.scene.getNonDeletedElements();
|
|
4118
4213
|
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
4119
4214
|
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
4120
|
-
if (selectedElements.length === 1 &&
|
|
4121
|
-
|
|
4215
|
+
if (selectedElements.length === 1 &&
|
|
4216
|
+
!this.state.editingLinearElement &&
|
|
4217
|
+
!(this.state.selectedLinearElement &&
|
|
4218
|
+
this.state.selectedLinearElement.hoverPointIndex !== -1)) {
|
|
4219
|
+
const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);
|
|
4122
4220
|
if (elementWithTransformHandleType != null) {
|
|
4123
4221
|
this.setState({
|
|
4124
4222
|
resizingElement: elementWithTransformHandleType.element,
|
|
@@ -4128,7 +4226,7 @@ class App extends React.Component {
|
|
|
4128
4226
|
}
|
|
4129
4227
|
}
|
|
4130
4228
|
else if (selectedElements.length > 1) {
|
|
4131
|
-
pointerDownState.resize.handleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType);
|
|
4229
|
+
pointerDownState.resize.handleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.device);
|
|
4132
4230
|
}
|
|
4133
4231
|
if (pointerDownState.resize.handleType) {
|
|
4134
4232
|
pointerDownState.resize.isResizing = true;
|
|
@@ -4142,7 +4240,7 @@ class App extends React.Component {
|
|
|
4142
4240
|
else {
|
|
4143
4241
|
if (this.state.selectedLinearElement) {
|
|
4144
4242
|
const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;
|
|
4145
|
-
const ret = LinearElementEditor.handlePointerDown(event, this.state, this.
|
|
4243
|
+
const ret = LinearElementEditor.handlePointerDown(event, this.state, this.store, pointerDownState.origin, linearElementEditor, this);
|
|
4146
4244
|
if (ret.hitElement) {
|
|
4147
4245
|
pointerDownState.hit.element = ret.hitElement;
|
|
4148
4246
|
}
|
|
@@ -4303,7 +4401,7 @@ class App extends React.Component {
|
|
|
4303
4401
|
return false;
|
|
4304
4402
|
}
|
|
4305
4403
|
// How many pixels off the shape boundary we still consider a hit
|
|
4306
|
-
const threshold = this.
|
|
4404
|
+
const threshold = this.getElementHitThreshold();
|
|
4307
4405
|
const [x1, y1, x2, y2] = getCommonBounds(selectedElements);
|
|
4308
4406
|
return (point.x > x1 - threshold &&
|
|
4309
4407
|
point.x < x2 + threshold &&
|
|
@@ -4334,6 +4432,7 @@ class App extends React.Component {
|
|
|
4334
4432
|
sceneY,
|
|
4335
4433
|
insertAtParentCenter: !event.altKey,
|
|
4336
4434
|
container,
|
|
4435
|
+
autoEdit: false,
|
|
4337
4436
|
});
|
|
4338
4437
|
resetCursor(this.interactiveCanvas);
|
|
4339
4438
|
if (!this.state.activeTool.locked) {
|
|
@@ -4381,7 +4480,7 @@ class App extends React.Component {
|
|
|
4381
4480
|
points: [[0, 0]],
|
|
4382
4481
|
pressures,
|
|
4383
4482
|
});
|
|
4384
|
-
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this);
|
|
4483
|
+
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.getNonDeletedElementsMap());
|
|
4385
4484
|
this.scene.insertElement(element);
|
|
4386
4485
|
this.setState({
|
|
4387
4486
|
draggingElement: element,
|
|
@@ -4553,7 +4652,7 @@ class App extends React.Component {
|
|
|
4553
4652
|
mutateElement(element, {
|
|
4554
4653
|
points: [...element.points, [0, 0]],
|
|
4555
4654
|
});
|
|
4556
|
-
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this);
|
|
4655
|
+
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.getNonDeletedElementsMap());
|
|
4557
4656
|
this.scene.insertElement(element);
|
|
4558
4657
|
this.setState({
|
|
4559
4658
|
draggingElement: element,
|
|
@@ -4850,7 +4949,9 @@ class App extends React.Component {
|
|
|
4850
4949
|
// able to select and interact with the text input
|
|
4851
4950
|
!this.state.editingFrame &&
|
|
4852
4951
|
dragSelectedElements(pointerDownState, selectedElements, dragOffset, this.state, this.scene, snapOffset, event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);
|
|
4853
|
-
this.
|
|
4952
|
+
this.setState({
|
|
4953
|
+
suggestedBindings: getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap()),
|
|
4954
|
+
});
|
|
4854
4955
|
// We duplicate the selected element if alt is pressed on pointer move
|
|
4855
4956
|
if (event.altKey && !pointerDownState.hit.hasBeenDuplicated) {
|
|
4856
4957
|
// Move the currently selected elements to the top of the z index stack, and
|
|
@@ -5174,7 +5275,7 @@ class App extends React.Component {
|
|
|
5174
5275
|
}
|
|
5175
5276
|
if (isLinearElement(draggingElement)) {
|
|
5176
5277
|
if (draggingElement.points.length > 1) {
|
|
5177
|
-
this.
|
|
5278
|
+
this.store.shouldCaptureIncrement();
|
|
5178
5279
|
}
|
|
5179
5280
|
const pointerCoords = viewportCoordsToSceneCoords(childEvent, this.state);
|
|
5180
5281
|
if (!pointerDownState.drag.hasOccurred &&
|
|
@@ -5197,7 +5298,7 @@ class App extends React.Component {
|
|
|
5197
5298
|
else if (pointerDownState.drag.hasOccurred && !multiElement) {
|
|
5198
5299
|
if (isBindingEnabled(this.state) &&
|
|
5199
5300
|
isBindingElement(draggingElement, false)) {
|
|
5200
|
-
maybeBindLinearElement(draggingElement, this.state, pointerCoords, this);
|
|
5301
|
+
maybeBindLinearElement(draggingElement, this.state, pointerCoords, this.scene.getNonDeletedElementsMap());
|
|
5201
5302
|
}
|
|
5202
5303
|
this.setState({ suggestedBindings: [], startBoundElement: null });
|
|
5203
5304
|
if (!activeTool.locked) {
|
|
@@ -5222,15 +5323,34 @@ class App extends React.Component {
|
|
|
5222
5323
|
}
|
|
5223
5324
|
return;
|
|
5224
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
|
+
}
|
|
5225
5341
|
if (activeTool.type !== "selection" &&
|
|
5226
5342
|
draggingElement &&
|
|
5227
5343
|
isInvisiblySmallElement(draggingElement)) {
|
|
5228
5344
|
// remove invisible element which was added in onPointerDown
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5345
|
+
// update the store snapshot, so that invisible elements are not captured by the store
|
|
5346
|
+
this.updateScene({
|
|
5347
|
+
elements: this.scene
|
|
5348
|
+
.getElementsIncludingDeleted()
|
|
5349
|
+
.filter((el) => el.id !== draggingElement.id),
|
|
5350
|
+
appState: {
|
|
5351
|
+
draggingElement: null,
|
|
5352
|
+
},
|
|
5353
|
+
storeAction: StoreAction.UPDATE,
|
|
5234
5354
|
});
|
|
5235
5355
|
return;
|
|
5236
5356
|
}
|
|
@@ -5253,7 +5373,7 @@ class App extends React.Component {
|
|
|
5253
5373
|
groupIds: [],
|
|
5254
5374
|
});
|
|
5255
5375
|
removeElementsFromFrame([linearElement], this.scene.getNonDeletedElementsMap());
|
|
5256
|
-
this.scene.
|
|
5376
|
+
this.scene.triggerUpdate();
|
|
5257
5377
|
}
|
|
5258
5378
|
}
|
|
5259
5379
|
}
|
|
@@ -5311,12 +5431,16 @@ class App extends React.Component {
|
|
|
5311
5431
|
mutateElement(draggingElement, getNormalizedDimensions(draggingElement));
|
|
5312
5432
|
}
|
|
5313
5433
|
if (resizingElement) {
|
|
5314
|
-
this.
|
|
5434
|
+
this.store.shouldCaptureIncrement();
|
|
5315
5435
|
}
|
|
5316
5436
|
if (resizingElement && isInvisiblySmallElement(resizingElement)) {
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5437
|
+
// update the store snapshot, so that invisible elements are not captured by the store
|
|
5438
|
+
this.updateScene({
|
|
5439
|
+
elements: this.scene
|
|
5440
|
+
.getElementsIncludingDeleted()
|
|
5441
|
+
.filter((el) => el.id !== resizingElement.id),
|
|
5442
|
+
storeAction: StoreAction.UPDATE,
|
|
5443
|
+
});
|
|
5320
5444
|
}
|
|
5321
5445
|
// handle frame membership for resizing frames and/or selected elements
|
|
5322
5446
|
if (pointerDownState.resize.isResizing) {
|
|
@@ -5482,8 +5606,8 @@ class App extends React.Component {
|
|
|
5482
5606
|
x: pointerDownState.origin.x,
|
|
5483
5607
|
y: pointerDownState.origin.y,
|
|
5484
5608
|
element: hitElement,
|
|
5485
|
-
shape: this.
|
|
5486
|
-
threshold: this.
|
|
5609
|
+
shape: getElementShape(hitElement, this.scene.getNonDeletedElementsMap()),
|
|
5610
|
+
threshold: this.getElementHitThreshold(),
|
|
5487
5611
|
frameNameBound: isFrameLikeElement(hitElement)
|
|
5488
5612
|
? this.frameNameBoundsCache.get(hitElement)
|
|
5489
5613
|
: null,
|
|
@@ -5521,13 +5645,17 @@ class App extends React.Component {
|
|
|
5521
5645
|
}));
|
|
5522
5646
|
}
|
|
5523
5647
|
if (activeTool.type !== "selection" ||
|
|
5524
|
-
isSomeElementSelected(this.scene.getNonDeletedElements(), this.state)
|
|
5525
|
-
this.
|
|
5648
|
+
isSomeElementSelected(this.scene.getNonDeletedElements(), this.state) ||
|
|
5649
|
+
!isShallowEqual(this.state.previousSelectedElementIds, this.state.selectedElementIds)) {
|
|
5650
|
+
this.store.shouldCaptureIncrement();
|
|
5526
5651
|
}
|
|
5527
5652
|
if (pointerDownState.drag.hasOccurred || isResizing || isRotating) {
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
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 ?? []);
|
|
5531
5659
|
}
|
|
5532
5660
|
if (activeTool.type === "laser") {
|
|
5533
5661
|
this.laserTrails.endPath();
|
|
@@ -5562,7 +5690,7 @@ class App extends React.Component {
|
|
|
5562
5690
|
}
|
|
5563
5691
|
restoreReadyToEraseElements = () => {
|
|
5564
5692
|
this.elementsPendingErasure = new Set();
|
|
5565
|
-
this.
|
|
5693
|
+
this.triggerRender();
|
|
5566
5694
|
};
|
|
5567
5695
|
eraseElements = () => {
|
|
5568
5696
|
let didChange = false;
|
|
@@ -5578,7 +5706,7 @@ class App extends React.Component {
|
|
|
5578
5706
|
});
|
|
5579
5707
|
this.elementsPendingErasure = new Set();
|
|
5580
5708
|
if (didChange) {
|
|
5581
|
-
this.
|
|
5709
|
+
this.store.shouldCaptureIncrement();
|
|
5582
5710
|
this.scene.replaceAllElements(elements);
|
|
5583
5711
|
}
|
|
5584
5712
|
};
|
|
@@ -5854,7 +5982,7 @@ class App extends React.Component {
|
|
|
5854
5982
|
if (uncachedImageElements.length) {
|
|
5855
5983
|
const { updatedFiles } = await this.updateImageCache(uncachedImageElements, files);
|
|
5856
5984
|
if (updatedFiles.size) {
|
|
5857
|
-
this.scene.
|
|
5985
|
+
this.scene.triggerUpdate();
|
|
5858
5986
|
}
|
|
5859
5987
|
}
|
|
5860
5988
|
};
|
|
@@ -5870,7 +5998,7 @@ class App extends React.Component {
|
|
|
5870
5998
|
}
|
|
5871
5999
|
};
|
|
5872
6000
|
maybeSuggestBindingAtCursor = (pointerCoords) => {
|
|
5873
|
-
const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this);
|
|
6001
|
+
const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this.scene.getNonDeletedElementsMap());
|
|
5874
6002
|
this.setState({
|
|
5875
6003
|
suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : [],
|
|
5876
6004
|
});
|
|
@@ -5885,7 +6013,7 @@ class App extends React.Component {
|
|
|
5885
6013
|
return;
|
|
5886
6014
|
}
|
|
5887
6015
|
const suggestedBindings = pointerCoords.reduce((acc, coords) => {
|
|
5888
|
-
const hoveredBindableElement = getHoveredElementForBinding(coords, this);
|
|
6016
|
+
const hoveredBindableElement = getHoveredElementForBinding(coords, this.scene.getNonDeletedElementsMap());
|
|
5889
6017
|
if (hoveredBindableElement != null &&
|
|
5890
6018
|
!isLinearElementSimpleAndAlreadyBound(linearElement, oppositeBindingBoundElement?.id, hoveredBindableElement)) {
|
|
5891
6019
|
acc.push(hoveredBindableElement);
|
|
@@ -5894,13 +6022,6 @@ class App extends React.Component {
|
|
|
5894
6022
|
}, []);
|
|
5895
6023
|
this.setState({ suggestedBindings });
|
|
5896
6024
|
};
|
|
5897
|
-
maybeSuggestBindingForAll(selectedElements) {
|
|
5898
|
-
if (selectedElements.length > 50) {
|
|
5899
|
-
return;
|
|
5900
|
-
}
|
|
5901
|
-
const suggestedBindings = getEligibleElementsForBinding(selectedElements, this);
|
|
5902
|
-
this.setState({ suggestedBindings });
|
|
5903
|
-
}
|
|
5904
6025
|
clearSelection(hitElement) {
|
|
5905
6026
|
this.setState((prevState) => ({
|
|
5906
6027
|
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
|
@@ -5960,7 +6081,7 @@ class App extends React.Component {
|
|
|
5960
6081
|
isLoading: false,
|
|
5961
6082
|
},
|
|
5962
6083
|
replaceFiles: true,
|
|
5963
|
-
|
|
6084
|
+
storeAction: StoreAction.CAPTURE,
|
|
5964
6085
|
});
|
|
5965
6086
|
return;
|
|
5966
6087
|
}
|
|
@@ -6028,9 +6149,10 @@ class App extends React.Component {
|
|
|
6028
6149
|
loadFileToCanvas = async (file, fileHandle) => {
|
|
6029
6150
|
file = await normalizeFile(file);
|
|
6030
6151
|
try {
|
|
6152
|
+
const elements = this.scene.getElementsIncludingDeleted();
|
|
6031
6153
|
let ret;
|
|
6032
6154
|
try {
|
|
6033
|
-
ret = await loadSceneOrLibraryFromBlob(file, this.state,
|
|
6155
|
+
ret = await loadSceneOrLibraryFromBlob(file, this.state, elements, fileHandle);
|
|
6034
6156
|
}
|
|
6035
6157
|
catch (error) {
|
|
6036
6158
|
const imageSceneDataError = error instanceof ImageSceneDataError;
|
|
@@ -6055,6 +6177,10 @@ class App extends React.Component {
|
|
|
6055
6177
|
return;
|
|
6056
6178
|
}
|
|
6057
6179
|
if (ret.type === MIME_TYPES.excalidraw) {
|
|
6180
|
+
// restore the fractional indices by mutating elements
|
|
6181
|
+
syncInvalidIndices(elements.concat(ret.data.elements));
|
|
6182
|
+
// update the store snapshot for old elements, otherwise we would end up with duplicated fractional indices on undo
|
|
6183
|
+
this.store.updateSnapshot(arrayToMap(elements), this.state);
|
|
6058
6184
|
this.setState({ isLoading: true });
|
|
6059
6185
|
this.syncActionResult({
|
|
6060
6186
|
...ret.data,
|
|
@@ -6063,7 +6189,7 @@ class App extends React.Component {
|
|
|
6063
6189
|
isLoading: false,
|
|
6064
6190
|
},
|
|
6065
6191
|
replaceFiles: true,
|
|
6066
|
-
|
|
6192
|
+
storeAction: StoreAction.CAPTURE,
|
|
6067
6193
|
});
|
|
6068
6194
|
}
|
|
6069
6195
|
else if (ret.type === MIME_TYPES.excalidrawlib) {
|
|
@@ -6135,7 +6261,7 @@ class App extends React.Component {
|
|
|
6135
6261
|
}
|
|
6136
6262
|
if (draggingElement.type === "selection" &&
|
|
6137
6263
|
this.state.activeTool.type !== "eraser") {
|
|
6138
|
-
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);
|
|
6139
6265
|
}
|
|
6140
6266
|
else {
|
|
6141
6267
|
let [gridX, gridY] = getGridPoint(pointerCoords.x, pointerCoords.y, event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);
|
|
@@ -6161,8 +6287,7 @@ class App extends React.Component {
|
|
|
6161
6287
|
});
|
|
6162
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)
|
|
6163
6289
|
? !shouldMaintainAspectRatio(event)
|
|
6164
|
-
: shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), aspectRatio, this.state.originSnapOffset);
|
|
6165
|
-
this.maybeSuggestBindingForAll([draggingElement]);
|
|
6290
|
+
: shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), this.state.zoom.value, aspectRatio, this.state.originSnapOffset);
|
|
6166
6291
|
// highlight elements that are to be added to frames on frames creation
|
|
6167
6292
|
if (this.state.activeTool.type === TOOL_TYPE.frame ||
|
|
6168
6293
|
this.state.activeTool.type === TOOL_TYPE.magicframe) {
|
|
@@ -6216,16 +6341,17 @@ class App extends React.Component {
|
|
|
6216
6341
|
snapLines,
|
|
6217
6342
|
});
|
|
6218
6343
|
}
|
|
6219
|
-
if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.
|
|
6344
|
+
if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.some((element) => isImageElement(element))
|
|
6220
6345
|
? !shouldMaintainAspectRatio(event)
|
|
6221
6346
|
: shouldMaintainAspectRatio(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {
|
|
6222
|
-
this.
|
|
6347
|
+
const suggestedBindings = getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap());
|
|
6223
6348
|
const elementsToHighlight = new Set();
|
|
6224
6349
|
selectedFrames.forEach((frame) => {
|
|
6225
6350
|
getElementsInResizingFrame(this.scene.getNonDeletedElements(), frame, this.state, this.scene.getNonDeletedElementsMap()).forEach((element) => elementsToHighlight.add(element));
|
|
6226
6351
|
});
|
|
6227
6352
|
this.setState({
|
|
6228
6353
|
elementsToHighlight: [...elementsToHighlight],
|
|
6354
|
+
suggestedBindings,
|
|
6229
6355
|
});
|
|
6230
6356
|
return true;
|
|
6231
6357
|
}
|
|
@@ -6270,6 +6396,7 @@ class App extends React.Component {
|
|
|
6270
6396
|
return [actionCopy, ...options];
|
|
6271
6397
|
}
|
|
6272
6398
|
return [
|
|
6399
|
+
CONTEXT_MENU_SEPARATOR,
|
|
6273
6400
|
actionCut,
|
|
6274
6401
|
actionCopy,
|
|
6275
6402
|
actionPaste,
|
|
@@ -6282,6 +6409,7 @@ class App extends React.Component {
|
|
|
6282
6409
|
actionPasteStyles,
|
|
6283
6410
|
CONTEXT_MENU_SEPARATOR,
|
|
6284
6411
|
actionGroup,
|
|
6412
|
+
actionTextAutoResize,
|
|
6285
6413
|
actionUnbindText,
|
|
6286
6414
|
actionBindText,
|
|
6287
6415
|
actionWrapTextInContainer,
|