@excalidraw/excalidraw 0.17.1-1d71f84 → 0.17.1-2f9526d
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 +14 -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-IX4V72YG.js → chunk-EFLPX7NE.js} +6 -6
- 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-AK7SWNLN.js → chunk-Q6A4M3MN.js} +9 -5
- package/dist/browser/dev/excalidraw-assets-dev/chunk-Q6A4M3MN.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-RWZVJAQU.js → chunk-Q6NFAEKN.js} +4597 -2668
- package/dist/browser/dev/excalidraw-assets-dev/chunk-Q6NFAEKN.js.map +7 -0
- 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-5TCZHGGJ.js → en-Y27YPU72.js} +2 -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-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/{image-EDKQZH7Z.js → image-Y5X7K6KW.js} +2 -2
- 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 +72 -28
- package/dist/browser/dev/index.css.map +3 -3
- package/dist/browser/dev/index.js +2211 -1904
- 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-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-CTYINSWT.js → chunk-IZMZ6RPD.js} +2 -2
- package/dist/browser/prod/excalidraw-assets/{chunk-AHLLBBVJ.js → chunk-L5DS24G6.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/chunk-MDMKPHYD.js +55 -0
- package/dist/browser/prod/excalidraw-assets/{chunk-CQJF3C6G.js → chunk-MUNOKHUD.js} +1 -1
- 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-LROPV2RN.js → en-GSUSWMSH.js} +1 -1
- 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-7MVXYJUE.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 +24 -24
- package/dist/dev/{en-II4GK66F.json → en-OIPCBIOA.json} +8 -4
- package/dist/dev/index.css +72 -28
- package/dist/dev/index.css.map +3 -3
- package/dist/dev/index.js +5626 -3465
- package/dist/dev/index.js.map +4 -4
- package/dist/excalidraw/actions/actionAddToLibrary.d.ts +4 -4
- 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 +10 -10
- package/dist/excalidraw/actions/actionBoundText.js +11 -5
- package/dist/excalidraw/actions/actionCanvas.d.ts +52 -52
- package/dist/excalidraw/actions/actionCanvas.js +19 -14
- package/dist/excalidraw/actions/actionClipboard.d.ts +24 -24
- package/dist/excalidraw/actions/actionClipboard.js +14 -13
- package/dist/excalidraw/actions/actionDeleteSelected.d.ts +10 -10
- 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 +7 -3
- package/dist/excalidraw/actions/actionElementLock.d.ts +9 -9
- package/dist/excalidraw/actions/actionElementLock.js +3 -2
- package/dist/excalidraw/actions/actionExport.d.ts +33 -33
- package/dist/excalidraw/actions/actionExport.js +15 -11
- package/dist/excalidraw/actions/actionFinalize.d.ts +9 -9
- package/dist/excalidraw/actions/actionFinalize.js +9 -5
- package/dist/excalidraw/actions/actionFlip.d.ts +10 -10
- package/dist/excalidraw/actions/actionFlip.js +12 -12
- package/dist/excalidraw/actions/actionFrame.d.ts +16 -171
- package/dist/excalidraw/actions/actionFrame.js +7 -6
- package/dist/excalidraw/actions/actionGroup.d.ts +12 -322
- package/dist/excalidraw/actions/actionGroup.js +9 -11
- package/dist/excalidraw/actions/actionHistory.d.ts +4 -3
- package/dist/excalidraw/actions/actionHistory.js +27 -28
- package/dist/excalidraw/actions/actionLinearEditor.d.ts +6 -4
- package/dist/excalidraw/actions/actionLinearEditor.js +21 -5
- package/dist/excalidraw/actions/actionLink.d.ts +5 -5
- package/dist/excalidraw/actions/actionLink.js +2 -1
- package/dist/excalidraw/actions/actionMenu.d.ts +8 -8
- package/dist/excalidraw/actions/actionMenu.js +4 -3
- package/dist/excalidraw/actions/actionNavigate.d.ts +4 -4
- package/dist/excalidraw/actions/actionNavigate.js +3 -2
- package/dist/excalidraw/actions/actionProperties.d.ts +34 -34
- package/dist/excalidraw/actions/actionProperties.js +19 -14
- package/dist/excalidraw/actions/actionSelectAll.d.ts +5 -5
- package/dist/excalidraw/actions/actionSelectAll.js +2 -1
- package/dist/excalidraw/actions/actionStyles.d.ts +9 -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 +7 -5
- package/dist/excalidraw/actions/actionToggleGridMode.js +6 -2
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +4 -4
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.js +2 -1
- package/dist/excalidraw/actions/actionToggleStats.d.ts +4 -4
- package/dist/excalidraw/actions/actionToggleStats.js +2 -1
- package/dist/excalidraw/actions/actionToggleViewMode.d.ts +4 -4
- package/dist/excalidraw/actions/actionToggleViewMode.js +2 -1
- package/dist/excalidraw/actions/actionToggleZenMode.d.ts +4 -4
- package/dist/excalidraw/actions/actionToggleZenMode.js +2 -1
- package/dist/excalidraw/actions/actionZindex.d.ts +23 -19
- 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/shortcuts.js +1 -1
- package/dist/excalidraw/actions/types.d.ts +8 -8
- package/dist/excalidraw/align.d.ts +1 -1
- package/dist/excalidraw/analytics.js +1 -1
- package/dist/excalidraw/animated-trail.d.ts +2 -2
- package/dist/excalidraw/appState.d.ts +5 -5
- package/dist/excalidraw/change.d.ts +191 -0
- package/dist/excalidraw/change.js +894 -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 +28 -14
- package/dist/excalidraw/components/App.js +407 -187
- 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 +30 -15
- 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/DarkModeToggle.js +3 -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 +8 -6
- 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 +2 -2
- 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 +1 -1
- 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/RadioGroup.d.ts +2 -1
- package/dist/excalidraw/components/RadioGroup.js +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.d.ts +2 -2
- package/dist/excalidraw/components/TTDDialog/MermaidToExcalidraw.d.ts +1 -1
- package/dist/excalidraw/components/TTDDialog/MermaidToExcalidraw.js +6 -2
- 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 +3 -2
- package/dist/excalidraw/components/canvases/InteractiveCanvas.js +3 -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/dropdownMenu/DropdownMenuItemContentRadio.d.ts +18 -0
- package/dist/excalidraw/components/dropdownMenu/DropdownMenuItemContentRadio.js +9 -0
- 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/Hyperlink.js +3 -3
- package/dist/excalidraw/components/hyperlink/helpers.d.ts +3 -3
- package/dist/excalidraw/components/hyperlink/helpers.js +2 -3
- package/dist/excalidraw/components/icons.d.ts +6 -1
- package/dist/excalidraw/components/icons.js +23 -5
- package/dist/excalidraw/components/main-menu/DefaultItems.d.ts +12 -2
- package/dist/excalidraw/components/main-menu/DefaultItems.js +38 -7
- package/dist/excalidraw/constants.d.ts +5 -5
- package/dist/excalidraw/constants.js +6 -3
- 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/magic.js +2 -1
- package/dist/excalidraw/data/reconcile.d.ts +6 -0
- package/dist/excalidraw/data/reconcile.js +49 -0
- package/dist/excalidraw/data/resave.d.ts +2 -2
- package/dist/excalidraw/data/restore.d.ts +5 -5
- package/dist/excalidraw/data/restore.js +7 -7
- package/dist/excalidraw/data/transform.d.ts +4 -4
- package/dist/excalidraw/data/transform.js +12 -3
- package/dist/excalidraw/data/types.d.ts +3 -3
- package/dist/excalidraw/data/url.d.ts +1 -0
- package/dist/excalidraw/data/url.js +4 -1
- package/dist/excalidraw/element/ElementCanvasButtons.d.ts +1 -1
- package/dist/excalidraw/element/binding.d.ts +50 -9
- package/dist/excalidraw/element/binding.js +712 -155
- package/dist/excalidraw/element/bounds.d.ts +3 -4
- package/dist/excalidraw/element/bounds.js +0 -3
- package/dist/excalidraw/element/collision.d.ts +14 -19
- package/dist/excalidraw/element/collision.js +36 -713
- package/dist/excalidraw/element/containerCache.d.ts +1 -1
- package/dist/excalidraw/element/dragElements.d.ts +3 -3
- package/dist/excalidraw/element/embeddable.d.ts +9 -6
- package/dist/excalidraw/element/embeddable.js +98 -62
- package/dist/excalidraw/element/image.d.ts +2 -2
- package/dist/excalidraw/element/index.d.ts +2 -3
- package/dist/excalidraw/element/index.js +1 -2
- package/dist/excalidraw/element/linearElementEditor.d.ts +12 -12
- package/dist/excalidraw/element/linearElementEditor.js +7 -5
- package/dist/excalidraw/element/mutateElement.d.ts +4 -5
- package/dist/excalidraw/element/mutateElement.js +5 -3
- package/dist/excalidraw/element/newElement.d.ts +4 -9
- package/dist/excalidraw/element/newElement.js +17 -14
- package/dist/excalidraw/element/resizeElements.d.ts +4 -4
- package/dist/excalidraw/element/resizeElements.js +170 -97
- 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 +5 -6
- package/dist/excalidraw/element/textElement.js +13 -37
- package/dist/excalidraw/element/textWysiwyg.d.ts +10 -5
- package/dist/excalidraw/element/textWysiwyg.js +6 -8
- package/dist/excalidraw/element/transformHandles.d.ts +24 -6
- package/dist/excalidraw/element/transformHandles.js +22 -11
- package/dist/excalidraw/element/typeChecks.d.ts +4 -4
- package/dist/excalidraw/element/types.d.ts +33 -10
- package/dist/excalidraw/emitter.d.ts +1 -1
- package/dist/excalidraw/errors.d.ts +3 -0
- package/dist/excalidraw/errors.js +3 -0
- package/dist/excalidraw/fractionalIndex.d.ts +40 -0
- package/dist/excalidraw/fractionalIndex.js +241 -0
- package/dist/excalidraw/frame.d.ts +4 -4
- package/dist/excalidraw/gatransforms.d.ts +1 -1
- package/dist/excalidraw/gesture.d.ts +1 -1
- package/dist/excalidraw/groups.d.ts +5 -3
- 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/useCreatePortalContainer.js +2 -1
- 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 +8 -4
- package/dist/excalidraw/math.d.ts +2 -2
- 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/helpers.js +2 -2
- package/dist/excalidraw/renderer/interactiveScene.d.ts +2 -2
- package/dist/excalidraw/renderer/interactiveScene.js +8 -7
- package/dist/excalidraw/renderer/renderElement.d.ts +3 -3
- package/dist/excalidraw/renderer/renderElement.js +5 -5
- package/dist/excalidraw/renderer/renderSnaps.d.ts +1 -1
- package/dist/excalidraw/renderer/renderSnaps.js +2 -1
- package/dist/excalidraw/renderer/staticScene.d.ts +1 -1
- package/dist/excalidraw/renderer/staticScene.js +14 -3
- package/dist/excalidraw/renderer/staticSvgScene.d.ts +4 -4
- package/dist/excalidraw/renderer/staticSvgScene.js +10 -0
- package/dist/excalidraw/scene/Fonts.d.ts +2 -4
- package/dist/excalidraw/scene/Fonts.js +6 -12
- package/dist/excalidraw/scene/Renderer.d.ts +4 -4
- package/dist/excalidraw/scene/Renderer.js +2 -3
- package/dist/excalidraw/scene/Scene.d.ts +19 -12
- package/dist/excalidraw/scene/Scene.js +44 -23
- 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 +6 -5
- 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 +5 -4
- package/dist/excalidraw/scene/zoom.d.ts +1 -1
- package/dist/excalidraw/snapping.d.ts +4 -4
- package/dist/excalidraw/store.d.ts +99 -0
- package/dist/excalidraw/store.js +269 -0
- package/dist/excalidraw/types.d.ts +33 -19
- package/dist/excalidraw/utils.d.ts +11 -4
- package/dist/excalidraw/utils.js +8 -0
- package/dist/excalidraw/zindex.d.ts +4 -4
- package/dist/excalidraw/zindex.js +9 -13
- package/dist/prod/{en-II4GK66F.json → en-OIPCBIOA.json} +8 -4
- package/dist/prod/index.css +1 -1
- package/dist/prod/index.js +44 -44
- package/dist/utils/bbox.d.ts +2 -2
- package/dist/utils/collision.d.ts +4 -0
- package/dist/utils/collision.js +48 -0
- package/dist/utils/export.d.ts +2 -2
- package/dist/utils/geometry/geometry.d.ts +71 -0
- package/dist/utils/geometry/geometry.js +674 -0
- package/dist/utils/geometry/shape.d.ts +56 -0
- package/dist/utils/geometry/shape.js +168 -0
- package/dist/utils/withinBounds.d.ts +1 -1
- package/history.ts +163 -218
- package/package.json +3 -2
- package/dist/browser/dev/excalidraw-assets-dev/chunk-AK7SWNLN.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/chunk-RWZVJAQU.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-LL4GORAM.js +0 -55
- package/dist/browser/prod/excalidraw-assets/dist-PIPZXALV.js +0 -6
- package/dist/browser/prod/excalidraw-assets/image-EFCJDJH3.js +0 -1
- /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-5TCZHGGJ.js.map → en-Y27YPU72.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-EDKQZH7Z.js.map → image-Y5X7K6KW.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,31 +10,33 @@ 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 { 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, } from "../constants";
|
|
13
|
+
import { copyTextToSystemClipboard, parseClipboard } from "../clipboard";
|
|
14
|
+
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, } from "../constants";
|
|
15
15
|
import { exportCanvas, loadFromBlob } from "../data";
|
|
16
16
|
import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library";
|
|
17
17
|
import { restore, restoreElements } from "../data/restore";
|
|
18
|
-
import { dragNewElement, dragSelectedElements, duplicateElement, getCommonBounds, getCursorForResizingElement, getDragOffsetXY, getElementWithTransformHandleType, getNormalizedDimensions, getResizeArrowDirection, getResizeOffsetXY, getLockedLinearCursorAlignSize, getTransformHandleTypeFromCoords,
|
|
19
|
-
import { bindOrUnbindLinearElement,
|
|
18
|
+
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";
|
|
19
|
+
import { bindOrUnbindLinearElement, bindOrUnbindLinearElements, fixBindingsAfterDeletion, fixBindingsAfterDuplication, getHoveredElementForBinding, isBindingEnabled, isLinearElementSimpleAndAlreadyBound, maybeBindLinearElement, shouldEnableBindingForPointerEvent, updateBoundElements, getSuggestedBindingsForArrows, } from "../element/binding";
|
|
20
20
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
|
21
21
|
import { mutateElement, newElementWith } from "../element/mutateElement";
|
|
22
22
|
import { deepCopyElement, duplicateElements, newFrameElement, newFreeDrawElement, newEmbeddableElement, newMagicFrameElement, newIframeElement, } from "../element/newElement";
|
|
23
|
-
import { hasBoundTextElement, isArrowElement, isBindingElement, isBindingElementType, isBoundToContainer, isFrameLikeElement, isImageElement, isEmbeddableElement, isInitializedImageElement, isLinearElement, isLinearElementType, isUsingAdaptiveRadius, isFrameElement, isIframeElement, isIframeLikeElement, isMagicFrameElement, } from "../element/typeChecks";
|
|
23
|
+
import { hasBoundTextElement, isArrowElement, isBindingElement, isBindingElementType, isBoundToContainer, isFrameLikeElement, isImageElement, isEmbeddableElement, isInitializedImageElement, isLinearElement, isLinearElementType, isUsingAdaptiveRadius, isFrameElement, isIframeElement, isIframeLikeElement, isMagicFrameElement, isTextBindableContainer, } from "../element/typeChecks";
|
|
24
24
|
import { getCenter, getDistance } from "../gesture";
|
|
25
25
|
import { editGroupForSelectedElement, getElementsInGroup, getSelectedGroupIdForElement, getSelectedGroupIds, isElementInGroup, isSelectedViaGroup, selectGroupsForSelectedElements, } from "../groups";
|
|
26
|
-
import History from "../history";
|
|
26
|
+
import { History } from "../history";
|
|
27
27
|
import { defaultLang, getLanguage, languages, setLanguage, t } from "../i18n";
|
|
28
28
|
import { CODES, shouldResizeFromCenter, shouldMaintainAspectRatio, shouldRotateWithDiscreteAngle, isArrowKey, KEYS, } from "../keys";
|
|
29
29
|
import { isElementInViewport } from "../element/sizeHelpers";
|
|
30
30
|
import { distance2d, getCornerRadius, getGridPoint, isPathALoop, } from "../math";
|
|
31
|
-
import { calculateScrollCenter,
|
|
31
|
+
import { calculateScrollCenter, getElementsWithinSelection, getNormalizedZoom, getSelectedElements, hasBackground, isSomeElementSelected, } from "../scene";
|
|
32
32
|
import Scene from "../scene/Scene";
|
|
33
33
|
import { getStateForZoom } from "../scene/zoom";
|
|
34
34
|
import { findShapeByKey } from "../shapes";
|
|
35
|
-
import {
|
|
35
|
+
import { getClosedCurveShape, getCurveShape, getEllipseShape, getFreedrawShape, getPolygonShape, getSelectionBoxShape, } from "../../utils/geometry/shape";
|
|
36
|
+
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, updateStable, addEventListener, normalizeEOL, getDateTime, isShallowEqual, arrayToMap, } from "../utils";
|
|
36
38
|
import { createSrcDoc, embeddableURLValidator, maybeParseEmbedSrc, getEmbedLink, } from "../element/embeddable";
|
|
37
|
-
import { ContextMenu, CONTEXT_MENU_SEPARATOR
|
|
39
|
+
import { ContextMenu, CONTEXT_MENU_SEPARATOR } from "./ContextMenu";
|
|
38
40
|
import LayerUI from "./LayerUI";
|
|
39
41
|
import { Toast } from "./Toast";
|
|
40
42
|
import { actionToggleViewMode } from "../actions/actionToggleViewMode";
|
|
@@ -42,8 +44,7 @@ import { dataURLToFile, generateIdFromFile, getDataURL, getFileFromEvent, ImageU
|
|
|
42
44
|
import { getInitializedImageElements, loadHTMLImageElement, normalizeSVG, updateImageCache as _updateImageCache, } from "../element/image";
|
|
43
45
|
import throttle from "lodash.throttle";
|
|
44
46
|
import { fileOpen } from "../data/filesystem";
|
|
45
|
-
import { bindTextToShapeAfterDuplication, getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getContainerCenter, getContainerElement, getDefaultLineHeight, getLineHeightInPx,
|
|
46
|
-
import { isHittingElementNotConsideringBoundingBox } from "../element/collision";
|
|
47
|
+
import { bindTextToShapeAfterDuplication, getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getContainerCenter, getContainerElement, getDefaultLineHeight, getLineHeightInPx, isMeasureTextSupported, isValidTextContainer, } from "../element/textElement";
|
|
47
48
|
import { showHyperlinkTooltip, hideHyperlinkToolip, Hyperlink, } from "../components/hyperlink/Hyperlink";
|
|
48
49
|
import { isLocalLink, normalizeLink, toValidURL } from "../data/url";
|
|
49
50
|
import { shouldShowBoundingBox } from "../element/transformHandles";
|
|
@@ -61,7 +62,7 @@ import { getSnapLinesAtPointer, snapDraggedElements, isActiveToolNonLinearSnappa
|
|
|
61
62
|
import { actionWrapTextInContainer } from "../actions/actionBoundText";
|
|
62
63
|
import BraveMeasureTextError from "./BraveMeasureTextError";
|
|
63
64
|
import { activeEyeDropperAtom } from "./EyeDropper";
|
|
64
|
-
import { convertToExcalidrawElements
|
|
65
|
+
import { convertToExcalidrawElements } from "../data/transform";
|
|
65
66
|
import { isSidebarDockedAtom } from "./Sidebar/Sidebar";
|
|
66
67
|
import { StaticCanvas, InteractiveCanvas } from "./canvases";
|
|
67
68
|
import { Renderer } from "../scene/Renderer";
|
|
@@ -77,15 +78,19 @@ import { ElementCanvasButton } from "./MagicButton";
|
|
|
77
78
|
import { MagicIcon, copyIcon, fullscreenIcon } from "./icons";
|
|
78
79
|
import { EditorLocalStorage } from "../data/EditorLocalStorage";
|
|
79
80
|
import FollowMode from "./FollowMode/FollowMode";
|
|
81
|
+
import { Store, StoreAction } from "../store";
|
|
80
82
|
import { AnimationFrameHandler } from "../animation-frame-handler";
|
|
81
83
|
import { AnimatedTrail } from "../animated-trail";
|
|
82
84
|
import { LaserTrails } from "../laser-trails";
|
|
83
85
|
import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils";
|
|
84
86
|
import { getRenderOpacity } from "../renderer/renderElement";
|
|
87
|
+
import { hitElementBoundText, hitElementBoundingBoxOnly, hitElementItself, shouldTestInside, } from "../element/collision";
|
|
85
88
|
import { textWysiwyg } from "../element/textWysiwyg";
|
|
86
89
|
import { isOverScrollBars } from "../scene/scrollbars";
|
|
90
|
+
import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex";
|
|
87
91
|
import { isPointHittingLink, isPointHittingLinkIcon, } from "./hyperlink/helpers";
|
|
88
92
|
import { getShortcutFromShortcutName } from "../actions/shortcuts";
|
|
93
|
+
import { actionTextAutoResize } from "../actions/actionTextAutoResize";
|
|
89
94
|
const AppContext = React.createContext(null);
|
|
90
95
|
const AppPropsContext = React.createContext(null);
|
|
91
96
|
const deviceContextInitialValue = {
|
|
@@ -165,6 +170,7 @@ class App extends React.Component {
|
|
|
165
170
|
library;
|
|
166
171
|
libraryItemsFromStorage;
|
|
167
172
|
id;
|
|
173
|
+
store;
|
|
168
174
|
history;
|
|
169
175
|
excalidrawContainerValue;
|
|
170
176
|
files = {};
|
|
@@ -236,6 +242,8 @@ class App extends React.Component {
|
|
|
236
242
|
this.canvas = document.createElement("canvas");
|
|
237
243
|
this.rc = rough.canvas(this.canvas);
|
|
238
244
|
this.renderer = new Renderer(this.scene);
|
|
245
|
+
this.store = new Store();
|
|
246
|
+
this.history = new History();
|
|
239
247
|
if (excalidrawAPI) {
|
|
240
248
|
const api = {
|
|
241
249
|
updateScene: this.updateScene,
|
|
@@ -279,14 +287,11 @@ class App extends React.Component {
|
|
|
279
287
|
container: this.excalidrawContainerRef.current,
|
|
280
288
|
id: this.id,
|
|
281
289
|
};
|
|
282
|
-
this.fonts = new Fonts({
|
|
283
|
-
scene: this.scene,
|
|
284
|
-
onSceneUpdated: this.onSceneUpdated,
|
|
285
|
-
});
|
|
290
|
+
this.fonts = new Fonts({ scene: this.scene });
|
|
286
291
|
this.history = new History();
|
|
287
292
|
this.actionManager.registerAll(actions);
|
|
288
|
-
this.actionManager.registerAction(createUndoAction(this.history));
|
|
289
|
-
this.actionManager.registerAction(createRedoAction(this.history));
|
|
293
|
+
this.actionManager.registerAction(createUndoAction(this.history, this.store));
|
|
294
|
+
this.actionManager.registerAction(createRedoAction(this.history, this.store));
|
|
290
295
|
}
|
|
291
296
|
onWindowMessage(event) {
|
|
292
297
|
if (event.origin !== "https://player.vimeo.com" &&
|
|
@@ -437,7 +442,7 @@ class App extends React.Component {
|
|
|
437
442
|
return false;
|
|
438
443
|
});
|
|
439
444
|
if (updated) {
|
|
440
|
-
this.scene.
|
|
445
|
+
this.scene.triggerUpdate();
|
|
441
446
|
}
|
|
442
447
|
// GC
|
|
443
448
|
this.iFrameRefs.forEach((ref, id) => {
|
|
@@ -495,7 +500,7 @@ class App extends React.Component {
|
|
|
495
500
|
html, body {
|
|
496
501
|
width: 100%;
|
|
497
502
|
height: 100%;
|
|
498
|
-
color: ${this.state.theme ===
|
|
503
|
+
color: ${this.state.theme === THEME.DARK ? "white" : "black"};
|
|
499
504
|
}
|
|
500
505
|
body {
|
|
501
506
|
display: flex;
|
|
@@ -650,7 +655,7 @@ class App extends React.Component {
|
|
|
650
655
|
? src.srcdoc(this.state.theme)
|
|
651
656
|
: undefined, src: src?.type !== "document" ? src?.link ?? "" : undefined,
|
|
652
657
|
// https://stackoverflow.com/q/18470015
|
|
653
|
-
scrolling: "no", referrerPolicy: "no-referrer-when-downgrade", title: "Excalidraw Embedded Content", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture", allowFullScreen: true, sandbox: "allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads
|
|
658
|
+
scrolling: "no", referrerPolicy: "no-referrer-when-downgrade", title: "Excalidraw Embedded Content", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture", allowFullScreen: true, sandbox: `${src?.sandbox?.allowSameOrigin ? "allow-same-origin" : ""} allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads` })) })] }) }, el.id));
|
|
654
659
|
}) }));
|
|
655
660
|
}
|
|
656
661
|
getFrameNameDOMId = (frameElement) => {
|
|
@@ -692,7 +697,7 @@ class App extends React.Component {
|
|
|
692
697
|
if (!this.state.frameRendering.enabled || !this.state.frameRendering.name) {
|
|
693
698
|
return null;
|
|
694
699
|
}
|
|
695
|
-
const isDarkTheme = this.state.theme ===
|
|
700
|
+
const isDarkTheme = this.state.theme === THEME.DARK;
|
|
696
701
|
let frameIndex = 0;
|
|
697
702
|
let magicFrameIndex = 0;
|
|
698
703
|
return this.scene.getNonDeletedFramesLikes().map((f) => {
|
|
@@ -796,9 +801,9 @@ class App extends React.Component {
|
|
|
796
801
|
render() {
|
|
797
802
|
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
798
803
|
const { renderTopRightUI, renderCustomStats } = this.props;
|
|
799
|
-
const
|
|
804
|
+
const sceneNonce = this.scene.getSceneNonce();
|
|
800
805
|
const { elementsMap, visibleElements } = this.renderer.getRenderableElements({
|
|
801
|
-
|
|
806
|
+
sceneNonce,
|
|
802
807
|
zoom: this.state.zoom,
|
|
803
808
|
offsetLeft: this.state.offsetLeft,
|
|
804
809
|
offsetTop: this.state.offsetTop,
|
|
@@ -867,14 +872,14 @@ class App extends React.Component {
|
|
|
867
872
|
this.focusContainer();
|
|
868
873
|
callback?.();
|
|
869
874
|
});
|
|
870
|
-
} })), _jsx(StaticCanvas, { canvas: this.canvas, rc: this.rc, elementsMap: elementsMap, allElementsMap: allElementsMap, visibleElements: visibleElements,
|
|
875
|
+
} })), _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: {
|
|
871
876
|
imageCache: this.imageCache,
|
|
872
877
|
isExporting: false,
|
|
873
878
|
renderGrid: true,
|
|
874
879
|
canvasBackgroundColor: this.state.viewBackgroundColor,
|
|
875
880
|
embedsValidationStatus: this.embedsValidationStatus,
|
|
876
881
|
elementsPendingErasure: this.elementsPendingErasure,
|
|
877
|
-
} }), _jsx(InteractiveCanvas, { containerRef: this.excalidrawContainerRef, canvas: this.interactiveCanvas, elementsMap: elementsMap, visibleElements: visibleElements, selectedElements: selectedElements,
|
|
882
|
+
} }), _jsx(InteractiveCanvas, { containerRef: this.excalidrawContainerRef, canvas: this.interactiveCanvas, elementsMap: elementsMap, visibleElements: visibleElements, 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()] }) }) }) }) }) }) }) }));
|
|
878
883
|
}
|
|
879
884
|
focusContainer = () => {
|
|
880
885
|
this.excalidrawContainerRef.current?.focus();
|
|
@@ -924,7 +929,7 @@ class App extends React.Component {
|
|
|
924
929
|
mutateElement(frameElement, { customData: { generationData: data } }, false);
|
|
925
930
|
}
|
|
926
931
|
this.magicGenerations.set(frameElement.id, data);
|
|
927
|
-
this.
|
|
932
|
+
this.triggerRender();
|
|
928
933
|
};
|
|
929
934
|
getTextFromElements(elements) {
|
|
930
935
|
const text = elements
|
|
@@ -1122,7 +1127,7 @@ class App extends React.Component {
|
|
|
1122
1127
|
opacity: 100,
|
|
1123
1128
|
locked: false,
|
|
1124
1129
|
});
|
|
1125
|
-
this.scene.
|
|
1130
|
+
this.scene.insertElement(frame);
|
|
1126
1131
|
for (const child of selectedElements) {
|
|
1127
1132
|
mutateElement(child, { frameId: frame.id });
|
|
1128
1133
|
}
|
|
@@ -1146,13 +1151,13 @@ class App extends React.Component {
|
|
|
1146
1151
|
if (shouldUpdateStrokeColor) {
|
|
1147
1152
|
this.syncActionResult({
|
|
1148
1153
|
appState: { ...this.state, currentItemStrokeColor: color },
|
|
1149
|
-
|
|
1154
|
+
storeAction: StoreAction.CAPTURE,
|
|
1150
1155
|
});
|
|
1151
1156
|
}
|
|
1152
1157
|
else {
|
|
1153
1158
|
this.syncActionResult({
|
|
1154
1159
|
appState: { ...this.state, currentItemBackgroundColor: color },
|
|
1155
|
-
|
|
1160
|
+
storeAction: StoreAction.CAPTURE,
|
|
1156
1161
|
});
|
|
1157
1162
|
}
|
|
1158
1163
|
}
|
|
@@ -1166,6 +1171,7 @@ class App extends React.Component {
|
|
|
1166
1171
|
}
|
|
1167
1172
|
return el;
|
|
1168
1173
|
}),
|
|
1174
|
+
storeAction: StoreAction.CAPTURE,
|
|
1169
1175
|
});
|
|
1170
1176
|
}
|
|
1171
1177
|
},
|
|
@@ -1185,10 +1191,13 @@ class App extends React.Component {
|
|
|
1185
1191
|
editingElement = element;
|
|
1186
1192
|
}
|
|
1187
1193
|
});
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1194
|
+
if (actionResult.storeAction === StoreAction.UPDATE) {
|
|
1195
|
+
this.store.shouldUpdateSnapshot();
|
|
1196
|
+
}
|
|
1197
|
+
else if (actionResult.storeAction === StoreAction.CAPTURE) {
|
|
1198
|
+
this.store.shouldCaptureIncrement();
|
|
1191
1199
|
}
|
|
1200
|
+
this.scene.replaceAllElements(actionResult.elements);
|
|
1192
1201
|
}
|
|
1193
1202
|
if (actionResult.files) {
|
|
1194
1203
|
this.files = actionResult.replaceFiles
|
|
@@ -1197,8 +1206,11 @@ class App extends React.Component {
|
|
|
1197
1206
|
this.addNewImagesToImageCache();
|
|
1198
1207
|
}
|
|
1199
1208
|
if (actionResult.appState || editingElement || this.state.contextMenu) {
|
|
1200
|
-
if (actionResult.
|
|
1201
|
-
this.
|
|
1209
|
+
if (actionResult.storeAction === StoreAction.UPDATE) {
|
|
1210
|
+
this.store.shouldUpdateSnapshot();
|
|
1211
|
+
}
|
|
1212
|
+
else if (actionResult.storeAction === StoreAction.CAPTURE) {
|
|
1213
|
+
this.store.shouldCaptureIncrement();
|
|
1202
1214
|
}
|
|
1203
1215
|
let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
|
|
1204
1216
|
let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
|
|
@@ -1237,10 +1249,6 @@ class App extends React.Component {
|
|
|
1237
1249
|
name,
|
|
1238
1250
|
errorMessage,
|
|
1239
1251
|
});
|
|
1240
|
-
}, () => {
|
|
1241
|
-
if (actionResult.syncHistory) {
|
|
1242
|
-
this.history.setCurrentState(this.state, this.scene.getElementsIncludingDeleted());
|
|
1243
|
-
}
|
|
1244
1252
|
});
|
|
1245
1253
|
}
|
|
1246
1254
|
});
|
|
@@ -1258,6 +1266,9 @@ class App extends React.Component {
|
|
|
1258
1266
|
resetHistory = () => {
|
|
1259
1267
|
this.history.clear();
|
|
1260
1268
|
};
|
|
1269
|
+
resetStore = () => {
|
|
1270
|
+
this.store.clear();
|
|
1271
|
+
};
|
|
1261
1272
|
/**
|
|
1262
1273
|
* Resets scene & history.
|
|
1263
1274
|
* ! Do not use to clear scene user action !
|
|
@@ -1269,6 +1280,7 @@ class App extends React.Component {
|
|
|
1269
1280
|
isLoading: opts?.resetLoadingState ? false : state.isLoading,
|
|
1270
1281
|
theme: this.state.theme,
|
|
1271
1282
|
}));
|
|
1283
|
+
this.resetStore();
|
|
1272
1284
|
this.resetHistory();
|
|
1273
1285
|
});
|
|
1274
1286
|
initializeScene = async () => {
|
|
@@ -1343,10 +1355,11 @@ class App extends React.Component {
|
|
|
1343
1355
|
// text elements on canvas, and rerender them once done. This also
|
|
1344
1356
|
// seems faster even in browsers that do fire the loadingdone event.
|
|
1345
1357
|
this.fonts.loadFontsForElements(scene.elements);
|
|
1358
|
+
this.resetStore();
|
|
1346
1359
|
this.resetHistory();
|
|
1347
1360
|
this.syncActionResult({
|
|
1348
1361
|
...scene,
|
|
1349
|
-
|
|
1362
|
+
storeAction: StoreAction.UPDATE,
|
|
1350
1363
|
});
|
|
1351
1364
|
};
|
|
1352
1365
|
isMobileBreakpoint = (width, height) => {
|
|
@@ -1417,9 +1430,16 @@ class App extends React.Component {
|
|
|
1417
1430
|
configurable: true,
|
|
1418
1431
|
value: this.history,
|
|
1419
1432
|
},
|
|
1433
|
+
store: {
|
|
1434
|
+
configurable: true,
|
|
1435
|
+
value: this.store,
|
|
1436
|
+
},
|
|
1420
1437
|
});
|
|
1421
1438
|
}
|
|
1422
|
-
this.
|
|
1439
|
+
this.store.onStoreIncrementEmitter.on((increment) => {
|
|
1440
|
+
this.history.record(increment.elementsChange, increment.appStateChange);
|
|
1441
|
+
});
|
|
1442
|
+
this.scene.onUpdate(this.triggerRender);
|
|
1423
1443
|
this.addEventListeners();
|
|
1424
1444
|
if (this.props.autoFocus && this.excalidrawContainerRef.current) {
|
|
1425
1445
|
this.focusContainer();
|
|
@@ -1457,6 +1477,7 @@ class App extends React.Component {
|
|
|
1457
1477
|
componentWillUnmount() {
|
|
1458
1478
|
this.renderer.destroy();
|
|
1459
1479
|
this.scene = new Scene();
|
|
1480
|
+
this.fonts = new Fonts({ scene: this.scene });
|
|
1460
1481
|
this.renderer = new Renderer(this.scene);
|
|
1461
1482
|
this.files = {};
|
|
1462
1483
|
this.imageCache.clear();
|
|
@@ -1468,6 +1489,7 @@ class App extends React.Component {
|
|
|
1468
1489
|
this.laserTrails.stop();
|
|
1469
1490
|
this.eraserTrail.stop();
|
|
1470
1491
|
this.onChangeEmitter.clear();
|
|
1492
|
+
this.store.onStoreIncrementEmitter.clear();
|
|
1471
1493
|
ShapeCache.destroy();
|
|
1472
1494
|
SnapCache.destroy();
|
|
1473
1495
|
clearTimeout(touchTimeout);
|
|
@@ -1520,6 +1542,9 @@ class App extends React.Component {
|
|
|
1520
1542
|
// Safari-only desktop pinch zoom
|
|
1521
1543
|
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, () => {
|
|
1522
1544
|
this.maybeCleanupAfterMissingPointerUp(null);
|
|
1545
|
+
// browsers (chrome?) tend to free up memory a lot, which results
|
|
1546
|
+
// in canvas context being cleared. Thus re-render on focus.
|
|
1547
|
+
this.triggerRender(true);
|
|
1523
1548
|
}));
|
|
1524
1549
|
if (this.state.viewModeEnabled) {
|
|
1525
1550
|
return;
|
|
@@ -1535,7 +1560,8 @@ class App extends React.Component {
|
|
|
1535
1560
|
componentDidUpdate(prevProps, prevState) {
|
|
1536
1561
|
this.updateEmbeddables();
|
|
1537
1562
|
const elements = this.scene.getElementsIncludingDeleted();
|
|
1538
|
-
const elementsMap = this.scene.
|
|
1563
|
+
const elementsMap = this.scene.getElementsMapIncludingDeleted();
|
|
1564
|
+
const nonDeletedElementsMap = this.scene.getNonDeletedElementsMap();
|
|
1539
1565
|
if (!this.state.showWelcomeScreen && !elements.length) {
|
|
1540
1566
|
this.setState({ showWelcomeScreen: true });
|
|
1541
1567
|
}
|
|
@@ -1608,10 +1634,10 @@ class App extends React.Component {
|
|
|
1608
1634
|
gridSize: this.props.gridModeEnabled ? GRID_SIZE : null,
|
|
1609
1635
|
});
|
|
1610
1636
|
}
|
|
1611
|
-
this.excalidrawContainerRef.current?.classList.toggle("theme--dark", this.state.theme ===
|
|
1637
|
+
this.excalidrawContainerRef.current?.classList.toggle("theme--dark", this.state.theme === THEME.DARK);
|
|
1612
1638
|
if (this.state.editingLinearElement &&
|
|
1613
1639
|
!this.state.selectedElementIds[this.state.editingLinearElement.elementId]) {
|
|
1614
|
-
// defer so that the
|
|
1640
|
+
// defer so that the storeAction flag isn't reset via current update
|
|
1615
1641
|
setTimeout(() => {
|
|
1616
1642
|
// execute only if the condition still holds when the deferred callback
|
|
1617
1643
|
// executes (it can be scheduled multiple times depending on how
|
|
@@ -1636,9 +1662,9 @@ class App extends React.Component {
|
|
|
1636
1662
|
multiElement != null &&
|
|
1637
1663
|
isBindingEnabled(this.state) &&
|
|
1638
1664
|
isBindingElement(multiElement, false)) {
|
|
1639
|
-
maybeBindLinearElement(multiElement, this.state,
|
|
1665
|
+
maybeBindLinearElement(multiElement, this.state, tupleToCoors(LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, nonDeletedElementsMap)), this);
|
|
1640
1666
|
}
|
|
1641
|
-
this.
|
|
1667
|
+
this.store.commit(elementsMap, this.state);
|
|
1642
1668
|
// Do not notify consumers if we're still loading the scene. Among other
|
|
1643
1669
|
// potential issues, this fixes a case where the tab isn't focused during
|
|
1644
1670
|
// init, which would trigger onChange with empty elements, which would then
|
|
@@ -1894,16 +1920,15 @@ class App extends React.Component {
|
|
|
1894
1920
|
}), {
|
|
1895
1921
|
randomizeSeed: !opts.retainSeed,
|
|
1896
1922
|
});
|
|
1897
|
-
const
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
];
|
|
1923
|
+
const prevElements = this.scene.getElementsIncludingDeleted();
|
|
1924
|
+
const nextElements = [...prevElements, ...newElements];
|
|
1925
|
+
syncMovedIndices(nextElements, arrayToMap(newElements));
|
|
1901
1926
|
const topLayerFrame = this.getTopLayerFrameAtSceneCoords({ x, y });
|
|
1902
1927
|
if (topLayerFrame) {
|
|
1903
1928
|
const eligibleElements = filterElementsEligibleAsFrameChildren(newElements, topLayerFrame);
|
|
1904
|
-
addElementsToFrame(
|
|
1929
|
+
addElementsToFrame(nextElements, eligibleElements, topLayerFrame);
|
|
1905
1930
|
}
|
|
1906
|
-
this.scene.replaceAllElements(
|
|
1931
|
+
this.scene.replaceAllElements(nextElements);
|
|
1907
1932
|
newElements.forEach((newElement) => {
|
|
1908
1933
|
if (isTextElement(newElement) && isBoundToContainer(newElement)) {
|
|
1909
1934
|
const container = getContainerElement(newElement, this.scene.getElementsMapIncludingDeleted());
|
|
@@ -1913,7 +1938,7 @@ class App extends React.Component {
|
|
|
1913
1938
|
if (opts.files) {
|
|
1914
1939
|
this.files = { ...this.files, ...opts.files };
|
|
1915
1940
|
}
|
|
1916
|
-
this.
|
|
1941
|
+
this.store.shouldCaptureIncrement();
|
|
1917
1942
|
const nextElementsToSelect = excludeElementsInFramesFromSelection(newElements);
|
|
1918
1943
|
this.setState({
|
|
1919
1944
|
...this.state,
|
|
@@ -2071,16 +2096,7 @@ class App extends React.Component {
|
|
|
2071
2096
|
if (textElements.length === 0) {
|
|
2072
2097
|
return;
|
|
2073
2098
|
}
|
|
2074
|
-
|
|
2075
|
-
if (frameId) {
|
|
2076
|
-
this.scene.insertElementsAtIndex(textElements, this.scene.getElementIndex(frameId));
|
|
2077
|
-
}
|
|
2078
|
-
else {
|
|
2079
|
-
this.scene.replaceAllElements([
|
|
2080
|
-
...this.scene.getElementsIncludingDeleted(),
|
|
2081
|
-
...textElements,
|
|
2082
|
-
]);
|
|
2083
|
-
}
|
|
2099
|
+
this.scene.insertElements(textElements);
|
|
2084
2100
|
this.setState({
|
|
2085
2101
|
selectedElementIds: makeNextSelectedElementIds(Object.fromEntries(textElements.map((el) => [el.id, true])), this.state),
|
|
2086
2102
|
});
|
|
@@ -2096,7 +2112,7 @@ class App extends React.Component {
|
|
|
2096
2112
|
});
|
|
2097
2113
|
PLAIN_PASTE_TOAST_SHOWN = true;
|
|
2098
2114
|
}
|
|
2099
|
-
this.
|
|
2115
|
+
this.store.shouldCaptureIncrement();
|
|
2100
2116
|
}
|
|
2101
2117
|
setAppState = (state, callback) => {
|
|
2102
2118
|
this.setState(state, callback);
|
|
@@ -2278,25 +2294,49 @@ class App extends React.Component {
|
|
|
2278
2294
|
ShapeCache.delete(element);
|
|
2279
2295
|
}
|
|
2280
2296
|
});
|
|
2281
|
-
this.scene.
|
|
2297
|
+
this.scene.triggerUpdate();
|
|
2282
2298
|
this.addNewImagesToImageCache();
|
|
2283
2299
|
});
|
|
2284
2300
|
updateScene = withBatchedUpdates((sceneData) => {
|
|
2285
|
-
|
|
2286
|
-
|
|
2301
|
+
const nextElements = syncInvalidIndices(sceneData.elements ?? []);
|
|
2302
|
+
if (sceneData.storeAction && sceneData.storeAction !== StoreAction.NONE) {
|
|
2303
|
+
const prevCommittedAppState = this.store.snapshot.appState;
|
|
2304
|
+
const prevCommittedElements = this.store.snapshot.elements;
|
|
2305
|
+
const nextCommittedAppState = sceneData.appState
|
|
2306
|
+
? Object.assign({}, prevCommittedAppState, sceneData.appState) // new instance, with partial appstate applied to previously captured one, including hidden prop inside `prevCommittedAppState`
|
|
2307
|
+
: prevCommittedAppState;
|
|
2308
|
+
const nextCommittedElements = sceneData.elements
|
|
2309
|
+
? this.store.filterUncomittedElements(this.scene.getElementsMapIncludingDeleted(), // Only used to detect uncomitted local elements
|
|
2310
|
+
arrayToMap(nextElements))
|
|
2311
|
+
: prevCommittedElements;
|
|
2312
|
+
// 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
|
|
2313
|
+
// do NOT schedule store actions (execute after re-render), as it might cause unexpected concurrency issues if not handled well
|
|
2314
|
+
if (sceneData.storeAction === StoreAction.CAPTURE) {
|
|
2315
|
+
this.store.captureIncrement(nextCommittedElements, nextCommittedAppState);
|
|
2316
|
+
}
|
|
2317
|
+
else if (sceneData.storeAction === StoreAction.UPDATE) {
|
|
2318
|
+
this.store.updateSnapshot(nextCommittedElements, nextCommittedAppState);
|
|
2319
|
+
}
|
|
2287
2320
|
}
|
|
2288
2321
|
if (sceneData.appState) {
|
|
2289
2322
|
this.setState(sceneData.appState);
|
|
2290
2323
|
}
|
|
2291
2324
|
if (sceneData.elements) {
|
|
2292
|
-
this.scene.replaceAllElements(
|
|
2325
|
+
this.scene.replaceAllElements(nextElements);
|
|
2293
2326
|
}
|
|
2294
2327
|
if (sceneData.collaborators) {
|
|
2295
2328
|
this.setState({ collaborators: sceneData.collaborators });
|
|
2296
2329
|
}
|
|
2297
2330
|
});
|
|
2298
|
-
|
|
2299
|
-
|
|
2331
|
+
triggerRender = (
|
|
2332
|
+
/** force always re-renders canvas even if no change */
|
|
2333
|
+
force) => {
|
|
2334
|
+
if (force === true) {
|
|
2335
|
+
this.scene.triggerUpdate();
|
|
2336
|
+
}
|
|
2337
|
+
else {
|
|
2338
|
+
this.setState({});
|
|
2339
|
+
}
|
|
2300
2340
|
};
|
|
2301
2341
|
/**
|
|
2302
2342
|
* @returns whether the menu was toggled on or off
|
|
@@ -2355,8 +2395,7 @@ class App extends React.Component {
|
|
|
2355
2395
|
!event.altKey) {
|
|
2356
2396
|
this.setToast({
|
|
2357
2397
|
message: t("commandPalette.shortcutHint", {
|
|
2358
|
-
|
|
2359
|
-
shortcutTwo: getShortcutFromShortcutName("commandPalette", 1),
|
|
2398
|
+
shortcut: getShortcutFromShortcutName("commandPalette"),
|
|
2360
2399
|
}),
|
|
2361
2400
|
});
|
|
2362
2401
|
event.preventDefault();
|
|
@@ -2464,7 +2503,9 @@ class App extends React.Component {
|
|
|
2464
2503
|
simultaneouslyUpdated: selectedElements,
|
|
2465
2504
|
});
|
|
2466
2505
|
});
|
|
2467
|
-
this.
|
|
2506
|
+
this.setState({
|
|
2507
|
+
suggestedBindings: getSuggestedBindingsForArrows(selectedElements, this),
|
|
2508
|
+
});
|
|
2468
2509
|
event.preventDefault();
|
|
2469
2510
|
}
|
|
2470
2511
|
else if (event.key === KEYS.ENTER) {
|
|
@@ -2476,7 +2517,7 @@ class App extends React.Component {
|
|
|
2476
2517
|
if (!this.state.editingLinearElement ||
|
|
2477
2518
|
this.state.editingLinearElement.elementId !==
|
|
2478
2519
|
selectedElements[0].id) {
|
|
2479
|
-
this.
|
|
2520
|
+
this.store.shouldCaptureIncrement();
|
|
2480
2521
|
this.setState({
|
|
2481
2522
|
editingLinearElement: new LinearElementEditor(selectedElement),
|
|
2482
2523
|
});
|
|
@@ -2602,11 +2643,7 @@ class App extends React.Component {
|
|
|
2602
2643
|
this.setState({ isBindingEnabled: true });
|
|
2603
2644
|
}
|
|
2604
2645
|
if (isArrowKey(event.key)) {
|
|
2605
|
-
|
|
2606
|
-
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
2607
|
-
isBindingEnabled(this.state)
|
|
2608
|
-
? bindOrUnbindSelectedElements(selectedElements, this.scene.getNonDeletedElements(), elementsMap)
|
|
2609
|
-
: unbindLinearElements(selectedElements, elementsMap);
|
|
2646
|
+
bindOrUnbindLinearElements(this.scene.getSelectedElements(this.state).filter(isLinearElement), this, isBindingEnabled(this.state), this.state.selectedLinearElement?.selectedPointsIndices ?? []);
|
|
2610
2647
|
this.setState({ suggestedBindings: [] });
|
|
2611
2648
|
}
|
|
2612
2649
|
});
|
|
@@ -2644,6 +2681,9 @@ class App extends React.Component {
|
|
|
2644
2681
|
originSnapOffset: null,
|
|
2645
2682
|
activeEmbeddable: null,
|
|
2646
2683
|
};
|
|
2684
|
+
if (nextActiveTool.type === "freedraw") {
|
|
2685
|
+
this.store.shouldCaptureIncrement();
|
|
2686
|
+
}
|
|
2647
2687
|
if (nextActiveTool.type !== "selection") {
|
|
2648
2688
|
return {
|
|
2649
2689
|
...prevState,
|
|
@@ -2741,15 +2781,16 @@ class App extends React.Component {
|
|
|
2741
2781
|
});
|
|
2742
2782
|
handleTextWysiwyg(element, { isExistingElement = false, }) {
|
|
2743
2783
|
const elementsMap = this.scene.getElementsMapIncludingDeleted();
|
|
2744
|
-
const updateElement = (
|
|
2784
|
+
const updateElement = (nextOriginalText, isDeleted) => {
|
|
2745
2785
|
this.scene.replaceAllElements([
|
|
2746
2786
|
// Not sure why we include deleted elements as well hence using deleted elements map
|
|
2747
2787
|
...this.scene.getElementsIncludingDeleted().map((_element) => {
|
|
2748
2788
|
if (_element.id === element.id && isTextElement(_element)) {
|
|
2749
|
-
return
|
|
2750
|
-
|
|
2751
|
-
isDeleted,
|
|
2752
|
-
|
|
2789
|
+
return newElementWith(_element, {
|
|
2790
|
+
originalText: nextOriginalText,
|
|
2791
|
+
isDeleted: isDeleted ?? _element.isDeleted,
|
|
2792
|
+
// returns (wrapped) text and new dimensions
|
|
2793
|
+
...refreshTextDimensions(_element, getContainerElement(_element, elementsMap), elementsMap, nextOriginalText),
|
|
2753
2794
|
});
|
|
2754
2795
|
}
|
|
2755
2796
|
return _element;
|
|
@@ -2769,15 +2810,15 @@ class App extends React.Component {
|
|
|
2769
2810
|
viewportY - this.state.offsetTop,
|
|
2770
2811
|
];
|
|
2771
2812
|
},
|
|
2772
|
-
onChange: withBatchedUpdates((
|
|
2773
|
-
updateElement(
|
|
2813
|
+
onChange: withBatchedUpdates((nextOriginalText) => {
|
|
2814
|
+
updateElement(nextOriginalText, false);
|
|
2774
2815
|
if (isNonDeletedElement(element)) {
|
|
2775
2816
|
updateBoundElements(element, elementsMap);
|
|
2776
2817
|
}
|
|
2777
2818
|
}),
|
|
2778
|
-
onSubmit: withBatchedUpdates(({
|
|
2779
|
-
const isDeleted = !
|
|
2780
|
-
updateElement(
|
|
2819
|
+
onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
|
|
2820
|
+
const isDeleted = !nextOriginalText.trim();
|
|
2821
|
+
updateElement(nextOriginalText, isDeleted);
|
|
2781
2822
|
// select the created text element only if submitting via keyboard
|
|
2782
2823
|
// (when submitting via click it should act as signal to deselect)
|
|
2783
2824
|
if (!isDeleted && viaKeyboard) {
|
|
@@ -2797,7 +2838,7 @@ class App extends React.Component {
|
|
|
2797
2838
|
]);
|
|
2798
2839
|
}
|
|
2799
2840
|
if (!isDeleted || isExistingElement) {
|
|
2800
|
-
this.
|
|
2841
|
+
this.store.shouldCaptureIncrement();
|
|
2801
2842
|
}
|
|
2802
2843
|
this.setState({
|
|
2803
2844
|
draggingElement: null,
|
|
@@ -2816,7 +2857,7 @@ class App extends React.Component {
|
|
|
2816
2857
|
this.deselectElements();
|
|
2817
2858
|
// do an initial update to re-initialize element position since we were
|
|
2818
2859
|
// modifying element's x/y for sake of editor (case: syncing to remote)
|
|
2819
|
-
updateElement(element.
|
|
2860
|
+
updateElement(element.originalText, false);
|
|
2820
2861
|
}
|
|
2821
2862
|
deselectElements() {
|
|
2822
2863
|
this.setState({
|
|
@@ -2835,6 +2876,57 @@ class App extends React.Component {
|
|
|
2835
2876
|
}
|
|
2836
2877
|
return null;
|
|
2837
2878
|
}
|
|
2879
|
+
/**
|
|
2880
|
+
* get the pure geometric shape of an excalidraw element
|
|
2881
|
+
* which is then used for hit detection
|
|
2882
|
+
*/
|
|
2883
|
+
getElementShape(element) {
|
|
2884
|
+
switch (element.type) {
|
|
2885
|
+
case "rectangle":
|
|
2886
|
+
case "diamond":
|
|
2887
|
+
case "frame":
|
|
2888
|
+
case "magicframe":
|
|
2889
|
+
case "embeddable":
|
|
2890
|
+
case "image":
|
|
2891
|
+
case "iframe":
|
|
2892
|
+
case "text":
|
|
2893
|
+
case "selection":
|
|
2894
|
+
return getPolygonShape(element);
|
|
2895
|
+
case "arrow":
|
|
2896
|
+
case "line": {
|
|
2897
|
+
const roughShape = ShapeCache.get(element)?.[0] ??
|
|
2898
|
+
ShapeCache.generateElementShape(element, null)[0];
|
|
2899
|
+
const [, , , , cx, cy] = getElementAbsoluteCoords(element, this.scene.getNonDeletedElementsMap());
|
|
2900
|
+
return shouldTestInside(element)
|
|
2901
|
+
? getClosedCurveShape(element, roughShape, [element.x, element.y], element.angle, [cx, cy])
|
|
2902
|
+
: getCurveShape(roughShape, [element.x, element.y], element.angle, [
|
|
2903
|
+
cx,
|
|
2904
|
+
cy,
|
|
2905
|
+
]);
|
|
2906
|
+
}
|
|
2907
|
+
case "ellipse":
|
|
2908
|
+
return getEllipseShape(element);
|
|
2909
|
+
case "freedraw": {
|
|
2910
|
+
const [, , , , cx, cy] = getElementAbsoluteCoords(element, this.scene.getNonDeletedElementsMap());
|
|
2911
|
+
return getFreedrawShape(element, [cx, cy], shouldTestInside(element));
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
getBoundTextShape(element) {
|
|
2916
|
+
const boundTextElement = getBoundTextElement(element, this.scene.getNonDeletedElementsMap());
|
|
2917
|
+
if (boundTextElement) {
|
|
2918
|
+
if (element.type === "arrow") {
|
|
2919
|
+
return this.getElementShape({
|
|
2920
|
+
...boundTextElement,
|
|
2921
|
+
// arrow's bound text accurate position is not stored in the element's property
|
|
2922
|
+
// but rather calculated and returned from the following static method
|
|
2923
|
+
...LinearElementEditor.getBoundTextElementPosition(element, boundTextElement, this.scene.getNonDeletedElementsMap()),
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
return this.getElementShape(boundTextElement);
|
|
2927
|
+
}
|
|
2928
|
+
return null;
|
|
2929
|
+
}
|
|
2838
2930
|
getElementAtPosition(x, y, opts) {
|
|
2839
2931
|
const allHitElements = this.getElementsAtPosition(x, y, opts?.includeBoundTextElement, opts?.includeLockedElements);
|
|
2840
2932
|
if (allHitElements.length > 1) {
|
|
@@ -2848,9 +2940,20 @@ class App extends React.Component {
|
|
|
2848
2940
|
const elementWithHighestZIndex = allHitElements[allHitElements.length - 1];
|
|
2849
2941
|
// If we're hitting element with highest z-index only on its bounding box
|
|
2850
2942
|
// while also hitting other element figure, the latter should be considered.
|
|
2851
|
-
return
|
|
2852
|
-
|
|
2853
|
-
|
|
2943
|
+
return hitElementItself({
|
|
2944
|
+
x,
|
|
2945
|
+
y,
|
|
2946
|
+
element: elementWithHighestZIndex,
|
|
2947
|
+
shape: this.getElementShape(elementWithHighestZIndex),
|
|
2948
|
+
// when overlapping, we would like to be more precise
|
|
2949
|
+
// this also avoids the need to update past tests
|
|
2950
|
+
threshold: this.getElementHitThreshold() / 2,
|
|
2951
|
+
frameNameBound: isFrameLikeElement(elementWithHighestZIndex)
|
|
2952
|
+
? this.frameNameBoundsCache.get(elementWithHighestZIndex)
|
|
2953
|
+
: null,
|
|
2954
|
+
})
|
|
2955
|
+
? elementWithHighestZIndex
|
|
2956
|
+
: allHitElements[allHitElements.length - 2];
|
|
2854
2957
|
}
|
|
2855
2958
|
if (allHitElements.length === 1) {
|
|
2856
2959
|
return allHitElements[0];
|
|
@@ -2858,15 +2961,17 @@ class App extends React.Component {
|
|
|
2858
2961
|
return null;
|
|
2859
2962
|
}
|
|
2860
2963
|
getElementsAtPosition(x, y, includeBoundTextElement = false, includeLockedElements = false) {
|
|
2861
|
-
const
|
|
2964
|
+
const iframeLikes = [];
|
|
2965
|
+
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
2966
|
+
const elements = (includeBoundTextElement && includeLockedElements
|
|
2862
2967
|
? this.scene.getNonDeletedElements()
|
|
2863
2968
|
: this.scene
|
|
2864
2969
|
.getNonDeletedElements()
|
|
2865
2970
|
.filter((element) => (includeLockedElements || !element.locked) &&
|
|
2866
2971
|
(includeBoundTextElement ||
|
|
2867
|
-
!(isTextElement(element) && element.containerId)))
|
|
2868
|
-
|
|
2869
|
-
|
|
2972
|
+
!(isTextElement(element) && element.containerId))))
|
|
2973
|
+
.filter((el) => this.hitElement(x, y, el))
|
|
2974
|
+
.filter((element) => {
|
|
2870
2975
|
// hitting a frame's element from outside the frame is not considered a hit
|
|
2871
2976
|
const containingFrame = getContainingFrame(element, elementsMap);
|
|
2872
2977
|
return containingFrame &&
|
|
@@ -2874,8 +2979,81 @@ class App extends React.Component {
|
|
|
2874
2979
|
this.state.frameRendering.clip
|
|
2875
2980
|
? isCursorInFrame({ x, y }, containingFrame, elementsMap)
|
|
2876
2981
|
: true;
|
|
2982
|
+
})
|
|
2983
|
+
.filter((el) => {
|
|
2984
|
+
// The parameter elements comes ordered from lower z-index to higher.
|
|
2985
|
+
// We want to preserve that order on the returned array.
|
|
2986
|
+
// Exception being embeddables which should be on top of everything else in
|
|
2987
|
+
// terms of hit testing.
|
|
2988
|
+
if (isIframeElement(el)) {
|
|
2989
|
+
iframeLikes.push(el);
|
|
2990
|
+
return false;
|
|
2991
|
+
}
|
|
2992
|
+
return true;
|
|
2993
|
+
})
|
|
2994
|
+
.concat(iframeLikes);
|
|
2995
|
+
return elements;
|
|
2996
|
+
}
|
|
2997
|
+
getElementHitThreshold() {
|
|
2998
|
+
return DEFAULT_COLLISION_THRESHOLD / this.state.zoom.value;
|
|
2999
|
+
}
|
|
3000
|
+
hitElement(x, y, element, considerBoundingBox = true) {
|
|
3001
|
+
// if the element is selected, then hit test is done against its bounding box
|
|
3002
|
+
if (considerBoundingBox &&
|
|
3003
|
+
this.state.selectedElementIds[element.id] &&
|
|
3004
|
+
shouldShowBoundingBox([element], this.state)) {
|
|
3005
|
+
const selectionShape = getSelectionBoxShape(element, this.scene.getNonDeletedElementsMap(), this.getElementHitThreshold());
|
|
3006
|
+
return isPointInShape([x, y], selectionShape);
|
|
3007
|
+
}
|
|
3008
|
+
// take bound text element into consideration for hit collision as well
|
|
3009
|
+
const hitBoundTextOfElement = hitElementBoundText(x, y, this.getBoundTextShape(element));
|
|
3010
|
+
if (hitBoundTextOfElement) {
|
|
3011
|
+
return true;
|
|
3012
|
+
}
|
|
3013
|
+
return hitElementItself({
|
|
3014
|
+
x,
|
|
3015
|
+
y,
|
|
3016
|
+
element,
|
|
3017
|
+
shape: this.getElementShape(element),
|
|
3018
|
+
threshold: this.getElementHitThreshold(),
|
|
3019
|
+
frameNameBound: isFrameLikeElement(element)
|
|
3020
|
+
? this.frameNameBoundsCache.get(element)
|
|
3021
|
+
: null,
|
|
2877
3022
|
});
|
|
2878
3023
|
}
|
|
3024
|
+
getTextBindableContainerAtPosition(x, y) {
|
|
3025
|
+
const elements = this.scene.getNonDeletedElements();
|
|
3026
|
+
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
3027
|
+
if (selectedElements.length === 1) {
|
|
3028
|
+
return isTextBindableContainer(selectedElements[0], false)
|
|
3029
|
+
? selectedElements[0]
|
|
3030
|
+
: null;
|
|
3031
|
+
}
|
|
3032
|
+
let hitElement = null;
|
|
3033
|
+
// We need to do hit testing from front (end of the array) to back (beginning of the array)
|
|
3034
|
+
for (let index = elements.length - 1; index >= 0; --index) {
|
|
3035
|
+
if (elements[index].isDeleted) {
|
|
3036
|
+
continue;
|
|
3037
|
+
}
|
|
3038
|
+
const [x1, y1, x2, y2] = getElementAbsoluteCoords(elements[index], this.scene.getNonDeletedElementsMap());
|
|
3039
|
+
if (isArrowElement(elements[index]) &&
|
|
3040
|
+
hitElementItself({
|
|
3041
|
+
x,
|
|
3042
|
+
y,
|
|
3043
|
+
element: elements[index],
|
|
3044
|
+
shape: this.getElementShape(elements[index]),
|
|
3045
|
+
threshold: this.getElementHitThreshold(),
|
|
3046
|
+
})) {
|
|
3047
|
+
hitElement = elements[index];
|
|
3048
|
+
break;
|
|
3049
|
+
}
|
|
3050
|
+
else if (x1 < x && x < x2 && y1 < y && y < y2) {
|
|
3051
|
+
hitElement = elements[index];
|
|
3052
|
+
break;
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
return isTextBindableContainer(hitElement, false) ? hitElement : null;
|
|
3056
|
+
}
|
|
2879
3057
|
startTextEditing = ({ sceneX, sceneY, insertAtParentCenter = true, container, }) => {
|
|
2880
3058
|
let shouldBindToContainer = false;
|
|
2881
3059
|
let parentCenterPosition = insertAtParentCenter &&
|
|
@@ -2974,7 +3152,7 @@ class App extends React.Component {
|
|
|
2974
3152
|
this.scene.insertElementAtIndex(element, containerIndex + 1);
|
|
2975
3153
|
}
|
|
2976
3154
|
else {
|
|
2977
|
-
this.scene.
|
|
3155
|
+
this.scene.insertElement(element);
|
|
2978
3156
|
}
|
|
2979
3157
|
}
|
|
2980
3158
|
this.setState({
|
|
@@ -2999,7 +3177,7 @@ class App extends React.Component {
|
|
|
2999
3177
|
if (event[KEYS.CTRL_OR_CMD] &&
|
|
3000
3178
|
(!this.state.editingLinearElement ||
|
|
3001
3179
|
this.state.editingLinearElement.elementId !== selectedElements[0].id)) {
|
|
3002
|
-
this.
|
|
3180
|
+
this.store.shouldCaptureIncrement();
|
|
3003
3181
|
this.setState({
|
|
3004
3182
|
editingLinearElement: new LinearElementEditor(selectedElements[0]),
|
|
3005
3183
|
});
|
|
@@ -3014,6 +3192,7 @@ class App extends React.Component {
|
|
|
3014
3192
|
const selectedGroupId = hitElement &&
|
|
3015
3193
|
getSelectedGroupIdForElement(hitElement, this.state.selectedGroupIds);
|
|
3016
3194
|
if (selectedGroupId) {
|
|
3195
|
+
this.store.shouldCaptureIncrement();
|
|
3017
3196
|
this.setState((prevState) => ({
|
|
3018
3197
|
...prevState,
|
|
3019
3198
|
...selectGroupsForSelectedElements({
|
|
@@ -3033,11 +3212,17 @@ class App extends React.Component {
|
|
|
3033
3212
|
});
|
|
3034
3213
|
return;
|
|
3035
3214
|
}
|
|
3036
|
-
const container =
|
|
3215
|
+
const container = this.getTextBindableContainerAtPosition(sceneX, sceneY);
|
|
3037
3216
|
if (container) {
|
|
3038
3217
|
if (hasBoundTextElement(container) ||
|
|
3039
3218
|
!isTransparent(container.backgroundColor) ||
|
|
3040
|
-
|
|
3219
|
+
hitElementItself({
|
|
3220
|
+
x: sceneX,
|
|
3221
|
+
y: sceneY,
|
|
3222
|
+
element: container,
|
|
3223
|
+
shape: this.getElementShape(container),
|
|
3224
|
+
threshold: this.getElementHitThreshold(),
|
|
3225
|
+
})) {
|
|
3041
3226
|
const midPoint = getContainerCenter(container, this.state, this.scene.getNonDeletedElementsMap());
|
|
3042
3227
|
sceneX = midPoint.x;
|
|
3043
3228
|
sceneY = midPoint.y;
|
|
@@ -3092,7 +3277,7 @@ class App extends React.Component {
|
|
|
3092
3277
|
}
|
|
3093
3278
|
if (!customEvent?.defaultPrevented) {
|
|
3094
3279
|
const target = isLocalLink(url) ? "_self" : "_blank";
|
|
3095
|
-
const newWindow = window.open(undefined, target
|
|
3280
|
+
const newWindow = window.open(undefined, target);
|
|
3096
3281
|
// https://mathiasbynens.github.io/rel-noopener/
|
|
3097
3282
|
if (newWindow) {
|
|
3098
3283
|
newWindow.opener = null;
|
|
@@ -3142,8 +3327,11 @@ class App extends React.Component {
|
|
|
3142
3327
|
}, state);
|
|
3143
3328
|
this.translateCanvas({
|
|
3144
3329
|
zoom: zoomState.zoom,
|
|
3145
|
-
|
|
3146
|
-
|
|
3330
|
+
// 2x multiplier is just a magic number that makes this work correctly
|
|
3331
|
+
// on touchscreen devices (note: if we get report that panning is slower/faster
|
|
3332
|
+
// than actual movement, consider swapping with devicePixelRatio)
|
|
3333
|
+
scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),
|
|
3334
|
+
scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),
|
|
3147
3335
|
shouldCacheIgnoreZoom: true,
|
|
3148
3336
|
});
|
|
3149
3337
|
});
|
|
@@ -3308,15 +3496,23 @@ class App extends React.Component {
|
|
|
3308
3496
|
if (selectedElements.length === 1 &&
|
|
3309
3497
|
!isOverScrollBar &&
|
|
3310
3498
|
!this.state.editingLinearElement) {
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3499
|
+
// for linear elements, we'd like to prioritize point dragging over edge resizing
|
|
3500
|
+
// therefore, we update and check hovered point index first
|
|
3501
|
+
if (this.state.selectedLinearElement) {
|
|
3502
|
+
this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);
|
|
3503
|
+
}
|
|
3504
|
+
if (!this.state.selectedLinearElement ||
|
|
3505
|
+
this.state.selectedLinearElement.hoverPointIndex === -1) {
|
|
3506
|
+
const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);
|
|
3507
|
+
if (elementWithTransformHandleType &&
|
|
3508
|
+
elementWithTransformHandleType.transformHandleType) {
|
|
3509
|
+
setCursor(this.interactiveCanvas, getCursorForResizingElement(elementWithTransformHandleType));
|
|
3510
|
+
return;
|
|
3511
|
+
}
|
|
3316
3512
|
}
|
|
3317
3513
|
}
|
|
3318
3514
|
else if (selectedElements.length > 1 && !isOverScrollBar) {
|
|
3319
|
-
const transformHandleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType);
|
|
3515
|
+
const transformHandleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.device);
|
|
3320
3516
|
if (transformHandleType) {
|
|
3321
3517
|
setCursor(this.interactiveCanvas, getCursorForResizingElement({
|
|
3322
3518
|
transformHandleType,
|
|
@@ -3420,7 +3616,7 @@ class App extends React.Component {
|
|
|
3420
3616
|
}
|
|
3421
3617
|
};
|
|
3422
3618
|
const distance = distance2d(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y, scenePointer.x, scenePointer.y);
|
|
3423
|
-
const threshold =
|
|
3619
|
+
const threshold = this.getElementHitThreshold();
|
|
3424
3620
|
const point = { ...pointerDownState.lastCoords };
|
|
3425
3621
|
let samplingInterval = 0;
|
|
3426
3622
|
while (samplingInterval <= distance) {
|
|
@@ -3456,7 +3652,7 @@ class App extends React.Component {
|
|
|
3456
3652
|
}
|
|
3457
3653
|
}
|
|
3458
3654
|
this.elementsPendingErasure = new Set(this.elementsPendingErasure);
|
|
3459
|
-
this.
|
|
3655
|
+
this.triggerRender();
|
|
3460
3656
|
}
|
|
3461
3657
|
};
|
|
3462
3658
|
// set touch moving for mobile context menu
|
|
@@ -3466,30 +3662,29 @@ class App extends React.Component {
|
|
|
3466
3662
|
handleHoverSelectedLinearElement(linearElementEditor, scenePointerX, scenePointerY) {
|
|
3467
3663
|
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
3468
3664
|
const element = LinearElementEditor.getElement(linearElementEditor.elementId, elementsMap);
|
|
3469
|
-
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
3470
3665
|
if (!element) {
|
|
3471
3666
|
return;
|
|
3472
3667
|
}
|
|
3473
3668
|
if (this.state.selectedLinearElement) {
|
|
3474
3669
|
let hoverPointIndex = -1;
|
|
3475
3670
|
let segmentMidPointHoveredCoords = null;
|
|
3476
|
-
if (
|
|
3671
|
+
if (hitElementItself({
|
|
3672
|
+
x: scenePointerX,
|
|
3673
|
+
y: scenePointerY,
|
|
3674
|
+
element,
|
|
3675
|
+
shape: this.getElementShape(element),
|
|
3676
|
+
})) {
|
|
3477
3677
|
hoverPointIndex = LinearElementEditor.getPointIndexUnderCursor(element, elementsMap, this.state.zoom, scenePointerX, scenePointerY);
|
|
3478
3678
|
segmentMidPointHoveredCoords =
|
|
3479
3679
|
LinearElementEditor.getSegmentMidpointHitCoords(linearElementEditor, { x: scenePointerX, y: scenePointerY }, this.state, this.scene.getNonDeletedElementsMap());
|
|
3480
3680
|
if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {
|
|
3481
3681
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
|
3482
3682
|
}
|
|
3483
|
-
else {
|
|
3683
|
+
else if (this.hitElement(scenePointerX, scenePointerY, element)) {
|
|
3484
3684
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
|
3485
3685
|
}
|
|
3486
3686
|
}
|
|
3487
|
-
else if (
|
|
3488
|
-
isHittingElementBoundingBoxWithoutHittingElement(element, this.state, this.frameNameBoundsCache, scenePointerX, scenePointerY, elementsMap)) {
|
|
3489
|
-
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
|
3490
|
-
}
|
|
3491
|
-
else if (boundTextElement &&
|
|
3492
|
-
hitTest(boundTextElement, this.state, this.frameNameBoundsCache, scenePointerX, scenePointerY, this.scene.getNonDeletedElementsMap())) {
|
|
3687
|
+
else if (this.hitElement(scenePointerX, scenePointerY, element)) {
|
|
3493
3688
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
|
3494
3689
|
}
|
|
3495
3690
|
if (this.state.selectedLinearElement.hoverPointIndex !== hoverPointIndex) {
|
|
@@ -3556,6 +3751,7 @@ class App extends React.Component {
|
|
|
3556
3751
|
return obj;
|
|
3557
3752
|
}, {}), this.state),
|
|
3558
3753
|
},
|
|
3754
|
+
storeAction: StoreAction.UPDATE,
|
|
3559
3755
|
});
|
|
3560
3756
|
return;
|
|
3561
3757
|
}
|
|
@@ -3995,8 +4191,11 @@ class App extends React.Component {
|
|
|
3995
4191
|
const elements = this.scene.getNonDeletedElements();
|
|
3996
4192
|
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
3997
4193
|
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
3998
|
-
if (selectedElements.length === 1 &&
|
|
3999
|
-
|
|
4194
|
+
if (selectedElements.length === 1 &&
|
|
4195
|
+
!this.state.editingLinearElement &&
|
|
4196
|
+
!(this.state.selectedLinearElement &&
|
|
4197
|
+
this.state.selectedLinearElement.hoverPointIndex !== -1)) {
|
|
4198
|
+
const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);
|
|
4000
4199
|
if (elementWithTransformHandleType != null) {
|
|
4001
4200
|
this.setState({
|
|
4002
4201
|
resizingElement: elementWithTransformHandleType.element,
|
|
@@ -4006,7 +4205,7 @@ class App extends React.Component {
|
|
|
4006
4205
|
}
|
|
4007
4206
|
}
|
|
4008
4207
|
else if (selectedElements.length > 1) {
|
|
4009
|
-
pointerDownState.resize.handleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType);
|
|
4208
|
+
pointerDownState.resize.handleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.device);
|
|
4010
4209
|
}
|
|
4011
4210
|
if (pointerDownState.resize.handleType) {
|
|
4012
4211
|
pointerDownState.resize.isResizing = true;
|
|
@@ -4020,7 +4219,7 @@ class App extends React.Component {
|
|
|
4020
4219
|
else {
|
|
4021
4220
|
if (this.state.selectedLinearElement) {
|
|
4022
4221
|
const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;
|
|
4023
|
-
const ret = LinearElementEditor.handlePointerDown(event, this.state, this.
|
|
4222
|
+
const ret = LinearElementEditor.handlePointerDown(event, this.state, this.store, pointerDownState.origin, linearElementEditor, this);
|
|
4024
4223
|
if (ret.hitElement) {
|
|
4025
4224
|
pointerDownState.hit.element = ret.hitElement;
|
|
4026
4225
|
}
|
|
@@ -4181,7 +4380,7 @@ class App extends React.Component {
|
|
|
4181
4380
|
return false;
|
|
4182
4381
|
}
|
|
4183
4382
|
// How many pixels off the shape boundary we still consider a hit
|
|
4184
|
-
const threshold =
|
|
4383
|
+
const threshold = this.getElementHitThreshold();
|
|
4185
4384
|
const [x1, y1, x2, y2] = getCommonBounds(selectedElements);
|
|
4186
4385
|
return (point.x > x1 - threshold &&
|
|
4187
4386
|
point.x < x2 + threshold &&
|
|
@@ -4201,7 +4400,7 @@ class App extends React.Component {
|
|
|
4201
4400
|
includeBoundTextElement: true,
|
|
4202
4401
|
});
|
|
4203
4402
|
// FIXME
|
|
4204
|
-
let container =
|
|
4403
|
+
let container = this.getTextBindableContainerAtPosition(sceneX, sceneY);
|
|
4205
4404
|
if (hasBoundTextElement(element)) {
|
|
4206
4405
|
container = element;
|
|
4207
4406
|
sceneX = element.x + element.width / 2;
|
|
@@ -4259,8 +4458,8 @@ class App extends React.Component {
|
|
|
4259
4458
|
points: [[0, 0]],
|
|
4260
4459
|
pressures,
|
|
4261
4460
|
});
|
|
4262
|
-
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this
|
|
4263
|
-
this.scene.
|
|
4461
|
+
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this);
|
|
4462
|
+
this.scene.insertElement(element);
|
|
4264
4463
|
this.setState({
|
|
4265
4464
|
draggingElement: element,
|
|
4266
4465
|
editingElement: element,
|
|
@@ -4288,10 +4487,7 @@ class App extends React.Component {
|
|
|
4288
4487
|
width,
|
|
4289
4488
|
height,
|
|
4290
4489
|
});
|
|
4291
|
-
this.scene.
|
|
4292
|
-
...this.scene.getElementsIncludingDeleted(),
|
|
4293
|
-
element,
|
|
4294
|
-
]);
|
|
4490
|
+
this.scene.insertElement(element);
|
|
4295
4491
|
return element;
|
|
4296
4492
|
};
|
|
4297
4493
|
//create rectangle element with youtube top left on nearest grid point width / hight 640/360
|
|
@@ -4326,10 +4522,7 @@ class App extends React.Component {
|
|
|
4326
4522
|
height: embedLink.intrinsicSize.h,
|
|
4327
4523
|
link,
|
|
4328
4524
|
});
|
|
4329
|
-
this.scene.
|
|
4330
|
-
...this.scene.getElementsIncludingDeleted(),
|
|
4331
|
-
element,
|
|
4332
|
-
]);
|
|
4525
|
+
this.scene.insertElement(element);
|
|
4333
4526
|
return element;
|
|
4334
4527
|
};
|
|
4335
4528
|
createImageElement = ({ sceneX, sceneY, addToFrameUnderCursor = true, }) => {
|
|
@@ -4437,8 +4630,8 @@ class App extends React.Component {
|
|
|
4437
4630
|
mutateElement(element, {
|
|
4438
4631
|
points: [...element.points, [0, 0]],
|
|
4439
4632
|
});
|
|
4440
|
-
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this
|
|
4441
|
-
this.scene.
|
|
4633
|
+
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this);
|
|
4634
|
+
this.scene.insertElement(element);
|
|
4442
4635
|
this.setState({
|
|
4443
4636
|
draggingElement: element,
|
|
4444
4637
|
editingElement: element,
|
|
@@ -4498,7 +4691,7 @@ class App extends React.Component {
|
|
|
4498
4691
|
});
|
|
4499
4692
|
}
|
|
4500
4693
|
else {
|
|
4501
|
-
this.scene.
|
|
4694
|
+
this.scene.insertElement(element);
|
|
4502
4695
|
this.setState({
|
|
4503
4696
|
multiElement: null,
|
|
4504
4697
|
draggingElement: element,
|
|
@@ -4520,10 +4713,7 @@ class App extends React.Component {
|
|
|
4520
4713
|
const frame = type === TOOL_TYPE.magicframe
|
|
4521
4714
|
? newMagicFrameElement(constructorOpts)
|
|
4522
4715
|
: newFrameElement(constructorOpts);
|
|
4523
|
-
this.scene.
|
|
4524
|
-
...this.scene.getElementsIncludingDeleted(),
|
|
4525
|
-
frame,
|
|
4526
|
-
]);
|
|
4716
|
+
this.scene.insertElement(frame);
|
|
4527
4717
|
this.setState({
|
|
4528
4718
|
multiElement: null,
|
|
4529
4719
|
draggingElement: frame,
|
|
@@ -4737,7 +4927,9 @@ class App extends React.Component {
|
|
|
4737
4927
|
// able to select and interact with the text input
|
|
4738
4928
|
!this.state.editingFrame &&
|
|
4739
4929
|
dragSelectedElements(pointerDownState, selectedElements, dragOffset, this.state, this.scene, snapOffset, event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);
|
|
4740
|
-
this.
|
|
4930
|
+
this.setState({
|
|
4931
|
+
suggestedBindings: getSuggestedBindingsForArrows(selectedElements, this),
|
|
4932
|
+
});
|
|
4741
4933
|
// We duplicate the selected element if alt is pressed on pointer move
|
|
4742
4934
|
if (event.altKey && !pointerDownState.hit.hasBeenDuplicated) {
|
|
4743
4935
|
// Move the currently selected elements to the top of the z index stack, and
|
|
@@ -4781,6 +4973,7 @@ class App extends React.Component {
|
|
|
4781
4973
|
}
|
|
4782
4974
|
}
|
|
4783
4975
|
const nextSceneElements = [...nextElements, ...elementsToAppend];
|
|
4976
|
+
syncMovedIndices(nextSceneElements, arrayToMap(elementsToAppend));
|
|
4784
4977
|
bindTextToShapeAfterDuplication(nextElements, elementsToAppend, oldIdToDuplicatedId);
|
|
4785
4978
|
fixBindingsAfterDuplication(nextSceneElements, elementsToAppend, oldIdToDuplicatedId, "duplicatesServeAsOld");
|
|
4786
4979
|
bindElementsToFramesAfterDuplication(nextSceneElements, elementsToAppend, oldIdToDuplicatedId);
|
|
@@ -4972,7 +5165,7 @@ class App extends React.Component {
|
|
|
4972
5165
|
this.actionManager.executeAction(actionFinalize);
|
|
4973
5166
|
}
|
|
4974
5167
|
else {
|
|
4975
|
-
const editingLinearElement = LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state, this
|
|
5168
|
+
const editingLinearElement = LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state, this);
|
|
4976
5169
|
if (editingLinearElement !== this.state.editingLinearElement) {
|
|
4977
5170
|
this.setState({
|
|
4978
5171
|
editingLinearElement,
|
|
@@ -4991,7 +5184,7 @@ class App extends React.Component {
|
|
|
4991
5184
|
}
|
|
4992
5185
|
}
|
|
4993
5186
|
else {
|
|
4994
|
-
const linearElementEditor = LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state, this
|
|
5187
|
+
const linearElementEditor = LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state, this);
|
|
4995
5188
|
const { startBindingElement, endBindingElement } = linearElementEditor;
|
|
4996
5189
|
const element = this.scene.getElement(linearElementEditor.elementId);
|
|
4997
5190
|
if (isBindingElement(element)) {
|
|
@@ -5060,7 +5253,7 @@ class App extends React.Component {
|
|
|
5060
5253
|
}
|
|
5061
5254
|
if (isLinearElement(draggingElement)) {
|
|
5062
5255
|
if (draggingElement.points.length > 1) {
|
|
5063
|
-
this.
|
|
5256
|
+
this.store.shouldCaptureIncrement();
|
|
5064
5257
|
}
|
|
5065
5258
|
const pointerCoords = viewportCoordsToSceneCoords(childEvent, this.state);
|
|
5066
5259
|
if (!pointerDownState.drag.hasOccurred &&
|
|
@@ -5083,7 +5276,7 @@ class App extends React.Component {
|
|
|
5083
5276
|
else if (pointerDownState.drag.hasOccurred && !multiElement) {
|
|
5084
5277
|
if (isBindingEnabled(this.state) &&
|
|
5085
5278
|
isBindingElement(draggingElement, false)) {
|
|
5086
|
-
maybeBindLinearElement(draggingElement, this.state,
|
|
5279
|
+
maybeBindLinearElement(draggingElement, this.state, pointerCoords, this);
|
|
5087
5280
|
}
|
|
5088
5281
|
this.setState({ suggestedBindings: [], startBoundElement: null });
|
|
5089
5282
|
if (!activeTool.locked) {
|
|
@@ -5112,11 +5305,15 @@ class App extends React.Component {
|
|
|
5112
5305
|
draggingElement &&
|
|
5113
5306
|
isInvisiblySmallElement(draggingElement)) {
|
|
5114
5307
|
// remove invisible element which was added in onPointerDown
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5308
|
+
// update the store snapshot, so that invisible elements are not captured by the store
|
|
5309
|
+
this.updateScene({
|
|
5310
|
+
elements: this.scene
|
|
5311
|
+
.getElementsIncludingDeleted()
|
|
5312
|
+
.filter((el) => el.id !== draggingElement.id),
|
|
5313
|
+
appState: {
|
|
5314
|
+
draggingElement: null,
|
|
5315
|
+
},
|
|
5316
|
+
storeAction: StoreAction.UPDATE,
|
|
5120
5317
|
});
|
|
5121
5318
|
return;
|
|
5122
5319
|
}
|
|
@@ -5139,7 +5336,7 @@ class App extends React.Component {
|
|
|
5139
5336
|
groupIds: [],
|
|
5140
5337
|
});
|
|
5141
5338
|
removeElementsFromFrame([linearElement], this.scene.getNonDeletedElementsMap());
|
|
5142
|
-
this.scene.
|
|
5339
|
+
this.scene.triggerUpdate();
|
|
5143
5340
|
}
|
|
5144
5341
|
}
|
|
5145
5342
|
}
|
|
@@ -5197,12 +5394,16 @@ class App extends React.Component {
|
|
|
5197
5394
|
mutateElement(draggingElement, getNormalizedDimensions(draggingElement));
|
|
5198
5395
|
}
|
|
5199
5396
|
if (resizingElement) {
|
|
5200
|
-
this.
|
|
5397
|
+
this.store.shouldCaptureIncrement();
|
|
5201
5398
|
}
|
|
5202
5399
|
if (resizingElement && isInvisiblySmallElement(resizingElement)) {
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5400
|
+
// update the store snapshot, so that invisible elements are not captured by the store
|
|
5401
|
+
this.updateScene({
|
|
5402
|
+
elements: this.scene
|
|
5403
|
+
.getElementsIncludingDeleted()
|
|
5404
|
+
.filter((el) => el.id !== resizingElement.id),
|
|
5405
|
+
storeAction: StoreAction.UPDATE,
|
|
5406
|
+
});
|
|
5206
5407
|
}
|
|
5207
5408
|
// handle frame membership for resizing frames and/or selected elements
|
|
5208
5409
|
if (pointerDownState.resize.isResizing) {
|
|
@@ -5357,10 +5558,23 @@ class App extends React.Component {
|
|
|
5357
5558
|
}));
|
|
5358
5559
|
}
|
|
5359
5560
|
}
|
|
5360
|
-
if (
|
|
5561
|
+
if (
|
|
5562
|
+
// not dragged
|
|
5563
|
+
!pointerDownState.drag.hasOccurred &&
|
|
5564
|
+
// not resized
|
|
5361
5565
|
!this.state.isResizing &&
|
|
5566
|
+
// only hitting the bounding box of the previous hit element
|
|
5362
5567
|
((hitElement &&
|
|
5363
|
-
|
|
5568
|
+
hitElementBoundingBoxOnly({
|
|
5569
|
+
x: pointerDownState.origin.x,
|
|
5570
|
+
y: pointerDownState.origin.y,
|
|
5571
|
+
element: hitElement,
|
|
5572
|
+
shape: this.getElementShape(hitElement),
|
|
5573
|
+
threshold: this.getElementHitThreshold(),
|
|
5574
|
+
frameNameBound: isFrameLikeElement(hitElement)
|
|
5575
|
+
? this.frameNameBoundsCache.get(hitElement)
|
|
5576
|
+
: null,
|
|
5577
|
+
}, elementsMap)) ||
|
|
5364
5578
|
(!hitElement &&
|
|
5365
5579
|
pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements))) {
|
|
5366
5580
|
if (this.state.editingLinearElement) {
|
|
@@ -5375,6 +5589,8 @@ class App extends React.Component {
|
|
|
5375
5589
|
activeEmbeddable: null,
|
|
5376
5590
|
});
|
|
5377
5591
|
}
|
|
5592
|
+
// reset cursor
|
|
5593
|
+
setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO);
|
|
5378
5594
|
return;
|
|
5379
5595
|
}
|
|
5380
5596
|
if (!activeTool.locked &&
|
|
@@ -5392,13 +5608,17 @@ class App extends React.Component {
|
|
|
5392
5608
|
}));
|
|
5393
5609
|
}
|
|
5394
5610
|
if (activeTool.type !== "selection" ||
|
|
5395
|
-
isSomeElementSelected(this.scene.getNonDeletedElements(), this.state)
|
|
5396
|
-
this.
|
|
5611
|
+
isSomeElementSelected(this.scene.getNonDeletedElements(), this.state) ||
|
|
5612
|
+
!isShallowEqual(this.state.previousSelectedElementIds, this.state.selectedElementIds)) {
|
|
5613
|
+
this.store.shouldCaptureIncrement();
|
|
5397
5614
|
}
|
|
5398
5615
|
if (pointerDownState.drag.hasOccurred || isResizing || isRotating) {
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5616
|
+
// We only allow binding via linear elements, specifically via dragging
|
|
5617
|
+
// the endpoints ("start" or "end").
|
|
5618
|
+
const linearElements = this.scene
|
|
5619
|
+
.getSelectedElements(this.state)
|
|
5620
|
+
.filter(isLinearElement);
|
|
5621
|
+
bindOrUnbindLinearElements(linearElements, this, isBindingEnabled(this.state), this.state.selectedLinearElement?.selectedPointsIndices ?? []);
|
|
5402
5622
|
}
|
|
5403
5623
|
if (activeTool.type === "laser") {
|
|
5404
5624
|
this.laserTrails.endPath();
|
|
@@ -5433,7 +5653,7 @@ class App extends React.Component {
|
|
|
5433
5653
|
}
|
|
5434
5654
|
restoreReadyToEraseElements = () => {
|
|
5435
5655
|
this.elementsPendingErasure = new Set();
|
|
5436
|
-
this.
|
|
5656
|
+
this.triggerRender();
|
|
5437
5657
|
};
|
|
5438
5658
|
eraseElements = () => {
|
|
5439
5659
|
let didChange = false;
|
|
@@ -5449,7 +5669,7 @@ class App extends React.Component {
|
|
|
5449
5669
|
});
|
|
5450
5670
|
this.elementsPendingErasure = new Set();
|
|
5451
5671
|
if (didChange) {
|
|
5452
|
-
this.
|
|
5672
|
+
this.store.shouldCaptureIncrement();
|
|
5453
5673
|
this.scene.replaceAllElements(elements);
|
|
5454
5674
|
}
|
|
5455
5675
|
};
|
|
@@ -5552,7 +5772,7 @@ class App extends React.Component {
|
|
|
5552
5772
|
this.setState({ errorMessage: t("errors.imageToolNotSupported") });
|
|
5553
5773
|
return;
|
|
5554
5774
|
}
|
|
5555
|
-
this.scene.
|
|
5775
|
+
this.scene.insertElement(imageElement);
|
|
5556
5776
|
try {
|
|
5557
5777
|
return await this.initializeImage({
|
|
5558
5778
|
imageFile,
|
|
@@ -5725,7 +5945,7 @@ class App extends React.Component {
|
|
|
5725
5945
|
if (uncachedImageElements.length) {
|
|
5726
5946
|
const { updatedFiles } = await this.updateImageCache(uncachedImageElements, files);
|
|
5727
5947
|
if (updatedFiles.size) {
|
|
5728
|
-
this.scene.
|
|
5948
|
+
this.scene.triggerUpdate();
|
|
5729
5949
|
}
|
|
5730
5950
|
}
|
|
5731
5951
|
};
|
|
@@ -5741,7 +5961,7 @@ class App extends React.Component {
|
|
|
5741
5961
|
}
|
|
5742
5962
|
};
|
|
5743
5963
|
maybeSuggestBindingAtCursor = (pointerCoords) => {
|
|
5744
|
-
const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this
|
|
5964
|
+
const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this);
|
|
5745
5965
|
this.setState({
|
|
5746
5966
|
suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : [],
|
|
5747
5967
|
});
|
|
@@ -5756,7 +5976,7 @@ class App extends React.Component {
|
|
|
5756
5976
|
return;
|
|
5757
5977
|
}
|
|
5758
5978
|
const suggestedBindings = pointerCoords.reduce((acc, coords) => {
|
|
5759
|
-
const hoveredBindableElement = getHoveredElementForBinding(coords, this
|
|
5979
|
+
const hoveredBindableElement = getHoveredElementForBinding(coords, this);
|
|
5760
5980
|
if (hoveredBindableElement != null &&
|
|
5761
5981
|
!isLinearElementSimpleAndAlreadyBound(linearElement, oppositeBindingBoundElement?.id, hoveredBindableElement)) {
|
|
5762
5982
|
acc.push(hoveredBindableElement);
|
|
@@ -5765,13 +5985,6 @@ class App extends React.Component {
|
|
|
5765
5985
|
}, []);
|
|
5766
5986
|
this.setState({ suggestedBindings });
|
|
5767
5987
|
};
|
|
5768
|
-
maybeSuggestBindingForAll(selectedElements) {
|
|
5769
|
-
if (selectedElements.length > 50) {
|
|
5770
|
-
return;
|
|
5771
|
-
}
|
|
5772
|
-
const suggestedBindings = getEligibleElementsForBinding(selectedElements, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());
|
|
5773
|
-
this.setState({ suggestedBindings });
|
|
5774
|
-
}
|
|
5775
5988
|
clearSelection(hitElement) {
|
|
5776
5989
|
this.setState((prevState) => ({
|
|
5777
5990
|
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
|
@@ -5831,7 +6044,7 @@ class App extends React.Component {
|
|
|
5831
6044
|
isLoading: false,
|
|
5832
6045
|
},
|
|
5833
6046
|
replaceFiles: true,
|
|
5834
|
-
|
|
6047
|
+
storeAction: StoreAction.CAPTURE,
|
|
5835
6048
|
});
|
|
5836
6049
|
return;
|
|
5837
6050
|
}
|
|
@@ -5899,9 +6112,10 @@ class App extends React.Component {
|
|
|
5899
6112
|
loadFileToCanvas = async (file, fileHandle) => {
|
|
5900
6113
|
file = await normalizeFile(file);
|
|
5901
6114
|
try {
|
|
6115
|
+
const elements = this.scene.getElementsIncludingDeleted();
|
|
5902
6116
|
let ret;
|
|
5903
6117
|
try {
|
|
5904
|
-
ret = await loadSceneOrLibraryFromBlob(file, this.state,
|
|
6118
|
+
ret = await loadSceneOrLibraryFromBlob(file, this.state, elements, fileHandle);
|
|
5905
6119
|
}
|
|
5906
6120
|
catch (error) {
|
|
5907
6121
|
const imageSceneDataError = error instanceof ImageSceneDataError;
|
|
@@ -5926,6 +6140,10 @@ class App extends React.Component {
|
|
|
5926
6140
|
return;
|
|
5927
6141
|
}
|
|
5928
6142
|
if (ret.type === MIME_TYPES.excalidraw) {
|
|
6143
|
+
// restore the fractional indices by mutating elements
|
|
6144
|
+
syncInvalidIndices(elements.concat(ret.data.elements));
|
|
6145
|
+
// update the store snapshot for old elements, otherwise we would end up with duplicated fractional indices on undo
|
|
6146
|
+
this.store.updateSnapshot(arrayToMap(elements), this.state);
|
|
5929
6147
|
this.setState({ isLoading: true });
|
|
5930
6148
|
this.syncActionResult({
|
|
5931
6149
|
...ret.data,
|
|
@@ -5934,7 +6152,7 @@ class App extends React.Component {
|
|
|
5934
6152
|
isLoading: false,
|
|
5935
6153
|
},
|
|
5936
6154
|
replaceFiles: true,
|
|
5937
|
-
|
|
6155
|
+
storeAction: StoreAction.CAPTURE,
|
|
5938
6156
|
});
|
|
5939
6157
|
}
|
|
5940
6158
|
else if (ret.type === MIME_TYPES.excalidrawlib) {
|
|
@@ -6033,7 +6251,6 @@ class App extends React.Component {
|
|
|
6033
6251
|
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)
|
|
6034
6252
|
? !shouldMaintainAspectRatio(event)
|
|
6035
6253
|
: shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), aspectRatio, this.state.originSnapOffset);
|
|
6036
|
-
this.maybeSuggestBindingForAll([draggingElement]);
|
|
6037
6254
|
// highlight elements that are to be added to frames on frames creation
|
|
6038
6255
|
if (this.state.activeTool.type === TOOL_TYPE.frame ||
|
|
6039
6256
|
this.state.activeTool.type === TOOL_TYPE.magicframe) {
|
|
@@ -6087,16 +6304,17 @@ class App extends React.Component {
|
|
|
6087
6304
|
snapLines,
|
|
6088
6305
|
});
|
|
6089
6306
|
}
|
|
6090
|
-
if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.
|
|
6307
|
+
if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.some((element) => isImageElement(element))
|
|
6091
6308
|
? !shouldMaintainAspectRatio(event)
|
|
6092
6309
|
: shouldMaintainAspectRatio(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {
|
|
6093
|
-
|
|
6310
|
+
const suggestedBindings = getSuggestedBindingsForArrows(selectedElements, this);
|
|
6094
6311
|
const elementsToHighlight = new Set();
|
|
6095
6312
|
selectedFrames.forEach((frame) => {
|
|
6096
6313
|
getElementsInResizingFrame(this.scene.getNonDeletedElements(), frame, this.state, this.scene.getNonDeletedElementsMap()).forEach((element) => elementsToHighlight.add(element));
|
|
6097
6314
|
});
|
|
6098
6315
|
this.setState({
|
|
6099
6316
|
elementsToHighlight: [...elementsToHighlight],
|
|
6317
|
+
suggestedBindings,
|
|
6100
6318
|
});
|
|
6101
6319
|
return true;
|
|
6102
6320
|
}
|
|
@@ -6141,6 +6359,7 @@ class App extends React.Component {
|
|
|
6141
6359
|
return [actionCopy, ...options];
|
|
6142
6360
|
}
|
|
6143
6361
|
return [
|
|
6362
|
+
CONTEXT_MENU_SEPARATOR,
|
|
6144
6363
|
actionCut,
|
|
6145
6364
|
actionCopy,
|
|
6146
6365
|
actionPaste,
|
|
@@ -6153,6 +6372,7 @@ class App extends React.Component {
|
|
|
6153
6372
|
actionPasteStyles,
|
|
6154
6373
|
CONTEXT_MENU_SEPARATOR,
|
|
6155
6374
|
actionGroup,
|
|
6375
|
+
actionTextAutoResize,
|
|
6156
6376
|
actionUnbindText,
|
|
6157
6377
|
actionBindText,
|
|
6158
6378
|
actionWrapTextInContainer,
|
|
@@ -6321,7 +6541,7 @@ export const createTestHook = () => {
|
|
|
6321
6541
|
return this.app?.scene.getElementsIncludingDeleted();
|
|
6322
6542
|
},
|
|
6323
6543
|
set(elements) {
|
|
6324
|
-
return this.app?.scene.replaceAllElements(elements);
|
|
6544
|
+
return this.app?.scene.replaceAllElements(syncInvalidIndices(elements));
|
|
6325
6545
|
},
|
|
6326
6546
|
},
|
|
6327
6547
|
});
|