@excalidraw/excalidraw 0.17.1-550a388 → 0.17.1-62228e0
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 +18 -2
- package/dist/browser/dev/excalidraw-assets-dev/CascadiaMono-Regular-NWCXRPUG.woff2 +0 -0
- package/dist/browser/dev/excalidraw-assets-dev/ComicShanns-Regular-6TOETDFT.woff2 +0 -0
- package/dist/browser/dev/excalidraw-assets-dev/Excalifont-Regular-CPKEUDVM.woff2 +0 -0
- package/dist/browser/dev/excalidraw-assets-dev/LiberationSans-Regular-ZQD73GJM.woff2 +0 -0
- package/dist/browser/dev/excalidraw-assets-dev/Virgil-Regular-YHAB2VGJ.woff2 +0 -0
- 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-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-AK7SWNLN.js → chunk-XDYNNNIZ.js} +48 -10
- package/dist/browser/dev/excalidraw-assets-dev/chunk-XDYNNNIZ.js.map +7 -0
- 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/{chunk-RWZVJAQU.js → chunk-ZYC7SDAJ.js} +13172 -7476
- package/dist/browser/dev/excalidraw-assets-dev/chunk-ZYC7SDAJ.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-DNSPZDOZ.js} +67 -33
- package/dist/browser/dev/excalidraw-assets-dev/dist-DNSPZDOZ.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{en-5TCZHGGJ.js → en-RAFN4KPD.js} +8 -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-WDHYGKKP.css} +1 -1
- package/dist/browser/dev/excalidraw-assets-dev/image-WDHYGKKP.css.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{image-EDKQZH7Z.js → image-ZNLDWTK3.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 +668 -191
- package/dist/browser/dev/index.css.map +3 -3
- package/dist/browser/dev/index.js +14529 -9273
- package/dist/browser/dev/index.js.map +4 -4
- package/dist/browser/prod/excalidraw-assets/CascadiaMono-Regular-NWCXRPUG.woff2 +0 -0
- package/dist/browser/prod/excalidraw-assets/ComicShanns-Regular-6TOETDFT.woff2 +0 -0
- package/dist/browser/prod/excalidraw-assets/Excalifont-Regular-CPKEUDVM.woff2 +0 -0
- package/dist/browser/prod/excalidraw-assets/LiberationSans-Regular-ZQD73GJM.woff2 +0 -0
- package/dist/browser/prod/excalidraw-assets/Virgil-Regular-YHAB2VGJ.woff2 +0 -0
- 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-F3JN4YS2.js +61 -0
- package/dist/browser/prod/excalidraw-assets/{chunk-WEYK4A2L.js → chunk-FFF2CSVG.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-R3HAIP6R.js → chunk-G4WDCSPE.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-HFOXJM22.js → chunk-HKZSHFLX.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-XIMFFJTE.js → chunk-IKCDYWMW.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-AHLLBBVJ.js → chunk-L5DS24G6.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-CQJF3C6G.js → chunk-MUNOKHUD.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{chunk-CTYINSWT.js → chunk-MXFM2KIK.js} +5 -5
- 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-NLUQPPQQ.js +7 -0
- package/dist/browser/prod/excalidraw-assets/en-SQSS4H2K.js +1 -0
- package/dist/browser/prod/excalidraw-assets/{erDiagram-47591fe2-E5V666CF.js → erDiagram-47591fe2-RE6HB7RM.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{flowDiagram-5540d9b9-GMBRCYVF.js → flowDiagram-5540d9b9-ZNJZBERW.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{flowDiagram-v2-3b53844e-Z4HUWP6B.js → flowDiagram-v2-3b53844e-LY44JLQJ.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{flowchart-elk-definition-5fe447d6-5ZCYTX5N.js → flowchart-elk-definition-5fe447d6-TMTJ6Z7O.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{ganttDiagram-9a3bba1f-WM32OMT5.js → ganttDiagram-9a3bba1f-5O6EA6LX.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/{gitGraphDiagram-96e6b4ee-CAKZ2U6E.js → gitGraphDiagram-96e6b4ee-UHYNM5DI.js} +1 -1
- package/dist/browser/prod/excalidraw-assets/image-CMH7O36X.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 +70 -51
- package/dist/dev/CascadiaMono-Regular-NWCXRPUG.woff2 +0 -0
- package/dist/dev/ComicShanns-Regular-6TOETDFT.woff2 +0 -0
- package/dist/dev/Excalifont-Regular-CPKEUDVM.woff2 +0 -0
- package/dist/dev/LiberationSans-Regular-ZQD73GJM.woff2 +0 -0
- package/dist/dev/Virgil-Regular-YHAB2VGJ.woff2 +0 -0
- package/dist/{prod/en-II4GK66F.json → dev/en-HDAPS7XK.json} +41 -9
- package/dist/dev/index.css +668 -191
- package/dist/dev/index.css.map +3 -3
- package/dist/dev/index.js +22026 -16675
- package/dist/dev/index.js.map +4 -4
- package/dist/excalidraw/actions/actionAddToLibrary.d.ts +22 -10
- 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 +22 -14
- package/dist/excalidraw/actions/actionBoundText.js +11 -5
- package/dist/excalidraw/actions/actionCanvas.d.ts +124 -76
- package/dist/excalidraw/actions/actionCanvas.js +20 -15
- package/dist/excalidraw/actions/actionClipboard.d.ts +66 -38
- package/dist/excalidraw/actions/actionClipboard.js +14 -13
- package/dist/excalidraw/actions/actionDeleteSelected.d.ts +28 -16
- 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 +21 -13
- package/dist/excalidraw/actions/actionElementLock.js +3 -2
- package/dist/excalidraw/actions/actionExport.d.ts +87 -51
- package/dist/excalidraw/actions/actionExport.js +15 -11
- package/dist/excalidraw/actions/actionFinalize.d.ts +21 -13
- 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 +193 -24
- package/dist/excalidraw/actions/actionFrame.js +7 -6
- package/dist/excalidraw/actions/actionGroup.d.ts +28 -20
- 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 +12 -6
- package/dist/excalidraw/actions/actionLinearEditor.js +21 -5
- package/dist/excalidraw/actions/actionLink.d.ts +11 -7
- package/dist/excalidraw/actions/actionLink.js +2 -1
- package/dist/excalidraw/actions/actionMenu.d.ts +26 -14
- package/dist/excalidraw/actions/actionMenu.js +4 -3
- package/dist/excalidraw/actions/actionNavigate.d.ts +16 -8
- package/dist/excalidraw/actions/actionNavigate.js +3 -2
- package/dist/excalidraw/actions/actionProperties.d.ts +272 -62
- package/dist/excalidraw/actions/actionProperties.js +261 -59
- package/dist/excalidraw/actions/actionSelectAll.d.ts +11 -7
- package/dist/excalidraw/actions/actionSelectAll.js +2 -1
- package/dist/excalidraw/actions/actionStyles.d.ts +17 -13
- package/dist/excalidraw/actions/actionStyles.js +7 -5
- package/dist/excalidraw/actions/actionTextAutoResize.d.ts +17 -0
- package/dist/excalidraw/actions/actionTextAutoResize.js +38 -0
- package/dist/excalidraw/actions/actionToggleGridMode.d.ts +13 -7
- package/dist/excalidraw/actions/actionToggleGridMode.js +6 -2
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +10 -6
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.js +2 -1
- package/dist/excalidraw/actions/actionToggleStats.d.ts +11 -6
- package/dist/excalidraw/actions/actionToggleStats.js +6 -4
- package/dist/excalidraw/actions/actionToggleViewMode.d.ts +10 -6
- package/dist/excalidraw/actions/actionToggleViewMode.js +2 -1
- package/dist/excalidraw/actions/actionToggleZenMode.d.ts +10 -6
- 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 +9 -7
- package/dist/excalidraw/animated-trail.d.ts +2 -2
- package/dist/excalidraw/appState.d.ts +9 -6
- package/dist/excalidraw/appState.js +8 -3
- package/dist/excalidraw/change.d.ts +191 -0
- package/dist/excalidraw/change.js +901 -0
- package/dist/excalidraw/charts.d.ts +1 -1
- package/dist/excalidraw/clients.d.ts +2 -2
- package/dist/excalidraw/clients.js +1 -1
- package/dist/excalidraw/clipboard.d.ts +3 -3
- package/dist/excalidraw/colors.d.ts +1 -1
- package/dist/excalidraw/components/Actions.d.ts +3 -3
- package/dist/excalidraw/components/Actions.js +10 -7
- package/dist/excalidraw/components/App.d.ts +26 -16
- package/dist/excalidraw/components/App.js +490 -217
- package/dist/excalidraw/components/ButtonIcon.d.ts +15 -0
- package/dist/excalidraw/components/ButtonIcon.js +8 -0
- package/dist/excalidraw/components/ButtonIconSelect.js +2 -3
- package/dist/excalidraw/components/ButtonSeparator.d.ts +2 -0
- package/dist/excalidraw/components/ButtonSeparator.js +7 -0
- 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 +48 -80
- package/dist/excalidraw/components/ColorPicker/Picker.d.ts +3 -3
- package/dist/excalidraw/components/ColorPicker/Picker.js +1 -1
- 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 +33 -18
- 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/FontPicker/FontPicker.d.ts +21 -0
- package/dist/excalidraw/components/FontPicker/FontPicker.js +49 -0
- package/dist/excalidraw/components/FontPicker/FontPickerList.d.ts +25 -0
- package/dist/excalidraw/components/FontPicker/FontPickerList.js +119 -0
- package/dist/excalidraw/components/FontPicker/FontPickerTrigger.d.ts +7 -0
- package/dist/excalidraw/components/FontPicker/FontPickerTrigger.js +13 -0
- package/dist/excalidraw/components/FontPicker/keyboardNavHandlers.d.ts +14 -0
- package/dist/excalidraw/components/FontPicker/keyboardNavHandlers.js +38 -0
- package/dist/excalidraw/components/HelpDialog.js +9 -7
- package/dist/excalidraw/components/HintViewer.d.ts +1 -1
- package/dist/excalidraw/components/IconPicker.js +2 -2
- package/dist/excalidraw/components/ImageExportDialog.d.ts +1 -1
- package/dist/excalidraw/components/InitializeApp.d.ts +2 -2
- package/dist/excalidraw/components/JSONExportDialog.d.ts +3 -3
- package/dist/excalidraw/components/LayerUI.d.ts +4 -4
- package/dist/excalidraw/components/LayerUI.js +10 -7
- package/dist/excalidraw/components/LibraryMenu.d.ts +2 -2
- package/dist/excalidraw/components/LibraryMenuBrowseButton.d.ts +1 -1
- package/dist/excalidraw/components/LibraryMenuControlButtons.d.ts +1 -1
- package/dist/excalidraw/components/LibraryMenuHeaderContent.d.ts +2 -2
- package/dist/excalidraw/components/LibraryMenuItems.d.ts +1 -1
- package/dist/excalidraw/components/LibraryMenuSection.d.ts +5 -4
- package/dist/excalidraw/components/LibraryUnit.d.ts +2 -2
- package/dist/excalidraw/components/LoadingMessage.d.ts +1 -1
- package/dist/excalidraw/components/MagicSettings.js +2 -2
- package/dist/excalidraw/components/MobileMenu.d.ts +3 -3
- package/dist/excalidraw/components/MobileMenu.js +2 -6
- package/dist/excalidraw/components/Modal.d.ts +1 -1
- package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
- package/dist/excalidraw/components/PasteChartDialog.d.ts +1 -1
- package/dist/excalidraw/components/PasteChartDialog.js +1 -1
- package/dist/excalidraw/components/PropertiesPopover.d.ts +15 -0
- package/dist/excalidraw/components/PropertiesPopover.js +31 -0
- package/dist/excalidraw/components/PublishLibrary.d.ts +1 -1
- package/dist/excalidraw/components/QuickSearch.d.ts +9 -0
- package/dist/excalidraw/components/QuickSearch.js +8 -0
- 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/ScrollableList.d.ts +9 -0
- package/dist/excalidraw/components/ScrollableList.js +8 -0
- package/dist/excalidraw/components/Sidebar/Sidebar.d.ts +2 -2
- package/dist/excalidraw/components/Sidebar/Sidebar.js +1 -1
- package/dist/excalidraw/components/Sidebar/SidebarTab.d.ts +1 -1
- package/dist/excalidraw/components/Sidebar/SidebarTabTrigger.d.ts +1 -1
- package/dist/excalidraw/components/Sidebar/SidebarTrigger.d.ts +1 -1
- package/dist/excalidraw/components/Sidebar/common.d.ts +1 -1
- package/dist/excalidraw/components/Stack.d.ts +2 -2
- package/dist/excalidraw/components/Stats/Angle.d.ts +12 -0
- package/dist/excalidraw/components/Stats/Angle.js +52 -0
- package/dist/excalidraw/components/Stats/Collapsible.d.ts +9 -0
- package/dist/excalidraw/components/Stats/Collapsible.js +12 -0
- package/dist/excalidraw/components/Stats/Dimension.d.ts +12 -0
- package/dist/excalidraw/components/Stats/Dimension.js +67 -0
- package/dist/excalidraw/components/Stats/DragInput.d.ts +32 -0
- package/dist/excalidraw/components/Stats/DragInput.js +174 -0
- package/dist/excalidraw/components/Stats/FontSize.d.ts +12 -0
- package/dist/excalidraw/components/Stats/FontSize.js +50 -0
- package/dist/excalidraw/components/Stats/MultiAngle.d.ts +12 -0
- package/dist/excalidraw/components/Stats/MultiAngle.js +66 -0
- package/dist/excalidraw/components/Stats/MultiDimension.d.ts +15 -0
- package/dist/excalidraw/components/Stats/MultiDimension.js +197 -0
- package/dist/excalidraw/components/Stats/MultiFontSize.d.ts +13 -0
- package/dist/excalidraw/components/Stats/MultiFontSize.js +72 -0
- package/dist/excalidraw/components/Stats/MultiPosition.d.ts +15 -0
- package/dist/excalidraw/components/Stats/MultiPosition.js +100 -0
- package/dist/excalidraw/components/Stats/Position.d.ts +13 -0
- package/dist/excalidraw/components/Stats/Position.js +39 -0
- package/dist/excalidraw/components/Stats/index.d.ts +16 -0
- package/dist/excalidraw/components/Stats/index.js +78 -0
- package/dist/excalidraw/components/Stats/utils.d.ts +25 -0
- package/dist/excalidraw/components/Stats/utils.js +158 -0
- package/dist/excalidraw/components/TTDDialog/MermaidToExcalidraw.d.ts +1 -1
- package/dist/excalidraw/components/TTDDialog/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 +5 -5
- package/dist/excalidraw/components/TTDDialog/common.js +3 -7
- 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/UserList.js +22 -22
- package/dist/excalidraw/components/canvases/InteractiveCanvas.d.ts +5 -3
- package/dist/excalidraw/components/canvases/InteractiveCanvas.js +5 -2
- package/dist/excalidraw/components/canvases/StaticCanvas.d.ts +2 -2
- package/dist/excalidraw/components/canvases/StaticCanvas.js +3 -2
- package/dist/excalidraw/components/dropdownMenu/DropdownMenu.d.ts +12 -3
- package/dist/excalidraw/components/dropdownMenu/DropdownMenuItem.d.ts +24 -4
- package/dist/excalidraw/components/dropdownMenu/DropdownMenuItem.js +55 -14
- package/dist/excalidraw/components/dropdownMenu/DropdownMenuItemContent.d.ts +2 -1
- package/dist/excalidraw/components/dropdownMenu/DropdownMenuItemContent.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/dropdownMenu/common.d.ts +1 -1
- package/dist/excalidraw/components/dropdownMenu/common.js +3 -2
- package/dist/excalidraw/components/footer/Footer.d.ts +2 -2
- package/dist/excalidraw/components/hyperlink/Hyperlink.d.ts +2 -2
- package/dist/excalidraw/components/hyperlink/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 +10 -1
- package/dist/excalidraw/components/icons.js +27 -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/components/main-menu/MainMenu.d.ts +12 -3
- package/dist/excalidraw/components/welcome-screen/WelcomeScreen.Center.js +2 -2
- package/dist/excalidraw/components/welcome-screen/WelcomeScreen.Hints.js +3 -3
- package/dist/excalidraw/constants.d.ts +24 -6
- package/dist/excalidraw/constants.js +29 -7
- 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 +25 -10
- package/dist/excalidraw/data/transform.d.ts +4 -4
- package/dist/excalidraw/data/transform.js +15 -5
- 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 +49 -8
- package/dist/excalidraw/element/binding.js +716 -153
- 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 +4 -4
- package/dist/excalidraw/element/dragElements.js +27 -3
- package/dist/excalidraw/element/embeddable.d.ts +15 -8
- 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 +18 -14
- package/dist/excalidraw/element/linearElementEditor.js +12 -7
- package/dist/excalidraw/element/mutateElement.d.ts +4 -5
- package/dist/excalidraw/element/mutateElement.js +5 -3
- package/dist/excalidraw/element/newElement.d.ts +6 -9
- package/dist/excalidraw/element/newElement.js +21 -17
- package/dist/excalidraw/element/resizeElements.d.ts +12 -4
- package/dist/excalidraw/element/resizeElements.js +174 -98
- package/dist/excalidraw/element/resizeTest.d.ts +7 -7
- package/dist/excalidraw/element/resizeTest.js +53 -8
- package/dist/excalidraw/element/showSelectedShapeActions.d.ts +2 -2
- package/dist/excalidraw/element/sizeHelpers.d.ts +2 -2
- package/dist/excalidraw/element/sizeHelpers.js +3 -0
- package/dist/excalidraw/element/sortElements.d.ts +1 -1
- package/dist/excalidraw/element/textElement.d.ts +7 -30
- package/dist/excalidraw/element/textElement.js +68 -144
- package/dist/excalidraw/element/textWysiwyg.d.ts +12 -6
- package/dist/excalidraw/element/textWysiwyg.js +75 -62
- package/dist/excalidraw/element/transformHandles.d.ts +24 -6
- package/dist/excalidraw/element/transformHandles.js +22 -11
- package/dist/excalidraw/element/typeChecks.d.ts +5 -5
- package/dist/excalidraw/element/types.d.ts +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/fonts/ExcalidrawFont.d.ts +17 -0
- package/dist/excalidraw/fonts/ExcalidrawFont.js +50 -0
- package/dist/excalidraw/fonts/index.d.ts +45 -0
- package/dist/excalidraw/fonts/index.js +202 -0
- package/dist/excalidraw/fonts/metadata.d.ts +34 -0
- package/dist/excalidraw/fonts/metadata.js +90 -0
- package/dist/excalidraw/fractionalIndex.d.ts +40 -0
- package/dist/excalidraw/fractionalIndex.js +239 -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 +6 -4
- package/dist/excalidraw/groups.js +17 -0
- package/dist/excalidraw/history.d.ts +35 -47
- package/dist/excalidraw/history.js +100 -167
- package/dist/excalidraw/hooks/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 +4 -2
- package/dist/excalidraw/index.js +5 -3
- package/dist/excalidraw/jotai.d.ts +1 -1
- package/dist/excalidraw/laser-trails.d.ts +3 -2
- package/dist/excalidraw/locales/en.json +41 -9
- package/dist/excalidraw/math.d.ts +4 -2
- package/dist/excalidraw/math.js +6 -0
- package/dist/excalidraw/mermaid.d.ts +2 -0
- package/dist/excalidraw/mermaid.js +28 -0
- package/dist/excalidraw/points.d.ts +1 -1
- package/dist/excalidraw/queue.d.ts +1 -1
- package/dist/excalidraw/renderer/helpers.d.ts +2 -2
- package/dist/excalidraw/renderer/helpers.js +2 -2
- package/dist/excalidraw/renderer/interactiveScene.d.ts +2 -2
- package/dist/excalidraw/renderer/interactiveScene.js +38 -11
- package/dist/excalidraw/renderer/renderElement.d.ts +6 -4
- package/dist/excalidraw/renderer/renderElement.js +81 -61
- 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 +12 -1
- package/dist/excalidraw/scene/Renderer.d.ts +4 -4
- package/dist/excalidraw/scene/Renderer.js +2 -3
- package/dist/excalidraw/scene/Scene.d.ts +22 -12
- package/dist/excalidraw/scene/Scene.js +47 -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 +3 -2
- package/dist/excalidraw/scene/export.js +40 -29
- package/dist/excalidraw/scene/scroll.d.ts +2 -2
- package/dist/excalidraw/scene/scrollbars.d.ts +3 -3
- package/dist/excalidraw/scene/selection.d.ts +2 -2
- package/dist/excalidraw/scene/types.d.ts +7 -8
- package/dist/excalidraw/scene/zoom.d.ts +1 -1
- package/dist/excalidraw/shapes.d.ts +7 -0
- package/dist/excalidraw/shapes.js +40 -0
- package/dist/excalidraw/snapping.d.ts +4 -4
- package/dist/excalidraw/snapping.js +2 -1
- package/dist/excalidraw/store.d.ts +129 -0
- package/dist/excalidraw/store.js +296 -0
- package/dist/excalidraw/types.d.ts +45 -22
- package/dist/excalidraw/utils.d.ts +20 -4
- package/dist/excalidraw/utils.js +29 -0
- package/dist/excalidraw/zindex.d.ts +4 -4
- package/dist/excalidraw/zindex.js +9 -13
- package/dist/prod/CascadiaMono-Regular-NWCXRPUG.woff2 +0 -0
- package/dist/prod/ComicShanns-Regular-6TOETDFT.woff2 +0 -0
- package/dist/prod/Excalifont-Regular-CPKEUDVM.woff2 +0 -0
- package/dist/prod/LiberationSans-Regular-ZQD73GJM.woff2 +0 -0
- package/dist/prod/Virgil-Regular-YHAB2VGJ.woff2 +0 -0
- package/dist/{dev/en-II4GK66F.json → prod/en-HDAPS7XK.json} +41 -9
- package/dist/prod/index.css +1 -1
- package/dist/prod/index.js +47 -53
- 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 +4 -3
- package/dist/utils/export.js +2 -1
- 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/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/withinBounds.d.ts +1 -1
- package/history.ts +163 -218
- package/package.json +3 -2
- package/dist/browser/dev/Cascadia-CYPE3OJC.woff2 +0 -0
- package/dist/browser/dev/Virgil-UZN6MUT6.woff2 +0 -0
- 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/Cascadia-CYPE3OJC.woff2 +0 -0
- package/dist/browser/prod/Virgil-UZN6MUT6.woff2 +0 -0
- 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/en-LROPV2RN.js +0 -1
- package/dist/browser/prod/excalidraw-assets/image-EFCJDJH3.js +0 -1
- package/dist/dev/Cascadia-CYPE3OJC.woff2 +0 -0
- package/dist/dev/Virgil-UZN6MUT6.woff2 +0 -0
- package/dist/excalidraw/components/Stats.d.ts +0 -11
- package/dist/excalidraw/components/Stats.js +0 -13
- package/dist/excalidraw/scene/Fonts.d.ts +0 -21
- package/dist/excalidraw/scene/Fonts.js +0 -72
- package/dist/prod/Cascadia-CYPE3OJC.woff2 +0 -0
- package/dist/prod/Virgil-UZN6MUT6.woff2 +0 -0
- /package/dist/browser/dev/{Assistant-Bold-ZDZZ6JHA.woff2 → excalidraw-assets-dev/Assistant-Bold-ZDZZ6JHA.woff2} +0 -0
- /package/dist/browser/dev/{Assistant-Medium-DZ25RZU3.woff2 → excalidraw-assets-dev/Assistant-Medium-DZ25RZU3.woff2} +0 -0
- /package/dist/browser/dev/{Assistant-Regular-PLF2XOGW.woff2 → excalidraw-assets-dev/Assistant-Regular-PLF2XOGW.woff2} +0 -0
- /package/dist/browser/dev/{Assistant-SemiBold-CZ5MX6FK.woff2 → excalidraw-assets-dev/Assistant-SemiBold-CZ5MX6FK.woff2} +0 -0
- /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-RAFN4KPD.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-ZNLDWTK3.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
- /package/dist/browser/prod/{Assistant-Bold-ZDZZ6JHA.woff2 → excalidraw-assets/Assistant-Bold-ZDZZ6JHA.woff2} +0 -0
- /package/dist/browser/prod/{Assistant-Medium-DZ25RZU3.woff2 → excalidraw-assets/Assistant-Medium-DZ25RZU3.woff2} +0 -0
- /package/dist/browser/prod/{Assistant-Regular-PLF2XOGW.woff2 → excalidraw-assets/Assistant-Regular-PLF2XOGW.woff2} +0 -0
- /package/dist/browser/prod/{Assistant-SemiBold-CZ5MX6FK.woff2 → excalidraw-assets/Assistant-SemiBold-CZ5MX6FK.woff2} +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, DEFAULT_TEXT_ALIGN, } 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
|
-
import { findShapeByKey } from "../shapes";
|
|
35
|
-
import {
|
|
34
|
+
import { findShapeByKey, getElementShape } from "../shapes";
|
|
35
|
+
import { 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,13 +44,12 @@ 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,
|
|
46
|
-
import { isHittingElementNotConsideringBoundingBox } from "../element/collision";
|
|
47
|
+
import { bindTextToShapeAfterDuplication, getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getContainerCenter, getContainerElement, getLineHeightInPx, getMinTextElementWidth, isMeasureTextSupported, isValidTextContainer, measureText, wrapText, } 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";
|
|
50
51
|
import { actionUnlockAllElements } from "../actions/actionElementLock";
|
|
51
|
-
import { Fonts } from "../
|
|
52
|
+
import { Fonts, getLineHeight } from "../fonts";
|
|
52
53
|
import { getFrameChildren, isCursorInFrame, bindElementsToFramesAfterDuplication, addElementsToFrame, replaceAllElementsInFrame, removeElementsFromFrame, getElementsInResizingFrame, getElementsInNewFrame, getContainingFrame, elementOverlapsWithFrame, updateFrameMembershipOfSelectedElements, isElementInFrame, getFrameLikeTitle, getElementsOverlappingFrame, filterElementsEligibleAsFrameChildren, } from "../frame";
|
|
53
54
|
import { excludeElementsInFramesFromSelection, makeNextSelectedElementIds, } from "../scene/selection";
|
|
54
55
|
import { actionPaste } from "../actions/actionClipboard";
|
|
@@ -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,21 @@ 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, } 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";
|
|
94
|
+
import { getVisibleSceneBounds } from "../element/bounds";
|
|
95
|
+
import { isMaybeMermaidDefinition } from "../mermaid";
|
|
89
96
|
const AppContext = React.createContext(null);
|
|
90
97
|
const AppPropsContext = React.createContext(null);
|
|
91
98
|
const deviceContextInitialValue = {
|
|
@@ -158,13 +165,14 @@ class App extends React.Component {
|
|
|
158
165
|
device = deviceContextInitialValue;
|
|
159
166
|
excalidrawContainerRef = React.createRef();
|
|
160
167
|
scene;
|
|
161
|
-
renderer;
|
|
162
168
|
fonts;
|
|
169
|
+
renderer;
|
|
163
170
|
resizeObserver;
|
|
164
171
|
nearestScrollableContainer;
|
|
165
172
|
library;
|
|
166
173
|
libraryItemsFromStorage;
|
|
167
174
|
id;
|
|
175
|
+
store;
|
|
168
176
|
history;
|
|
169
177
|
excalidrawContainerValue;
|
|
170
178
|
files = {};
|
|
@@ -236,6 +244,8 @@ class App extends React.Component {
|
|
|
236
244
|
this.canvas = document.createElement("canvas");
|
|
237
245
|
this.rc = rough.canvas(this.canvas);
|
|
238
246
|
this.renderer = new Renderer(this.scene);
|
|
247
|
+
this.store = new Store();
|
|
248
|
+
this.history = new History();
|
|
239
249
|
if (excalidrawAPI) {
|
|
240
250
|
const api = {
|
|
241
251
|
updateScene: this.updateScene,
|
|
@@ -279,14 +289,11 @@ class App extends React.Component {
|
|
|
279
289
|
container: this.excalidrawContainerRef.current,
|
|
280
290
|
id: this.id,
|
|
281
291
|
};
|
|
282
|
-
this.fonts = new Fonts({
|
|
283
|
-
scene: this.scene,
|
|
284
|
-
onSceneUpdated: this.onSceneUpdated,
|
|
285
|
-
});
|
|
292
|
+
this.fonts = new Fonts({ scene: this.scene });
|
|
286
293
|
this.history = new History();
|
|
287
294
|
this.actionManager.registerAll(actions);
|
|
288
|
-
this.actionManager.registerAction(createUndoAction(this.history));
|
|
289
|
-
this.actionManager.registerAction(createRedoAction(this.history));
|
|
295
|
+
this.actionManager.registerAction(createUndoAction(this.history, this.store));
|
|
296
|
+
this.actionManager.registerAction(createRedoAction(this.history, this.store));
|
|
290
297
|
}
|
|
291
298
|
onWindowMessage(event) {
|
|
292
299
|
if (event.origin !== "https://player.vimeo.com" &&
|
|
@@ -437,7 +444,7 @@ class App extends React.Component {
|
|
|
437
444
|
return false;
|
|
438
445
|
});
|
|
439
446
|
if (updated) {
|
|
440
|
-
this.scene.
|
|
447
|
+
this.scene.triggerUpdate();
|
|
441
448
|
}
|
|
442
449
|
// GC
|
|
443
450
|
this.iFrameRefs.forEach((ref, id) => {
|
|
@@ -495,7 +502,7 @@ class App extends React.Component {
|
|
|
495
502
|
html, body {
|
|
496
503
|
width: 100%;
|
|
497
504
|
height: 100%;
|
|
498
|
-
color: ${this.state.theme ===
|
|
505
|
+
color: ${this.state.theme === THEME.DARK ? "white" : "black"};
|
|
499
506
|
}
|
|
500
507
|
body {
|
|
501
508
|
display: flex;
|
|
@@ -650,7 +657,7 @@ class App extends React.Component {
|
|
|
650
657
|
? src.srcdoc(this.state.theme)
|
|
651
658
|
: undefined, src: src?.type !== "document" ? src?.link ?? "" : undefined,
|
|
652
659
|
// 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
|
|
660
|
+
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
661
|
}) }));
|
|
655
662
|
}
|
|
656
663
|
getFrameNameDOMId = (frameElement) => {
|
|
@@ -692,7 +699,7 @@ class App extends React.Component {
|
|
|
692
699
|
if (!this.state.frameRendering.enabled || !this.state.frameRendering.name) {
|
|
693
700
|
return null;
|
|
694
701
|
}
|
|
695
|
-
const isDarkTheme = this.state.theme ===
|
|
702
|
+
const isDarkTheme = this.state.theme === THEME.DARK;
|
|
696
703
|
let frameIndex = 0;
|
|
697
704
|
let magicFrameIndex = 0;
|
|
698
705
|
return this.scene.getNonDeletedFramesLikes().map((f) => {
|
|
@@ -796,9 +803,9 @@ class App extends React.Component {
|
|
|
796
803
|
render() {
|
|
797
804
|
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
798
805
|
const { renderTopRightUI, renderCustomStats } = this.props;
|
|
799
|
-
const
|
|
806
|
+
const sceneNonce = this.scene.getSceneNonce();
|
|
800
807
|
const { elementsMap, visibleElements } = this.renderer.getRenderableElements({
|
|
801
|
-
|
|
808
|
+
sceneNonce,
|
|
802
809
|
zoom: this.state.zoom,
|
|
803
810
|
offsetLeft: this.state.offsetLeft,
|
|
804
811
|
offsetTop: this.state.offsetTop,
|
|
@@ -867,14 +874,14 @@ class App extends React.Component {
|
|
|
867
874
|
this.focusContainer();
|
|
868
875
|
callback?.();
|
|
869
876
|
});
|
|
870
|
-
} })), _jsx(StaticCanvas, { canvas: this.canvas, rc: this.rc, elementsMap: elementsMap, allElementsMap: allElementsMap, visibleElements: visibleElements,
|
|
877
|
+
} })), _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
878
|
imageCache: this.imageCache,
|
|
872
879
|
isExporting: false,
|
|
873
880
|
renderGrid: true,
|
|
874
881
|
canvasBackgroundColor: this.state.viewBackgroundColor,
|
|
875
882
|
embedsValidationStatus: this.embedsValidationStatus,
|
|
876
883
|
elementsPendingErasure: this.elementsPendingErasure,
|
|
877
|
-
} }), _jsx(InteractiveCanvas, { containerRef: this.excalidrawContainerRef, canvas: this.interactiveCanvas, elementsMap: elementsMap, visibleElements: visibleElements, selectedElements: selectedElements,
|
|
884
|
+
} }), _jsx(InteractiveCanvas, { containerRef: this.excalidrawContainerRef, canvas: this.interactiveCanvas, elementsMap: elementsMap, visibleElements: visibleElements, allElementsMap: allElementsMap, selectedElements: selectedElements, sceneNonce: sceneNonce, selectionNonce: this.state.selectionElement?.versionNonce, scale: window.devicePixelRatio, appState: this.state, device: this.device, renderInteractiveSceneCallback: this.renderInteractiveSceneCallback, handleCanvasRef: this.handleInteractiveCanvasRef, onContextMenu: this.handleCanvasContextMenu, onPointerMove: this.handleCanvasPointerMove, onPointerUp: this.handleCanvasPointerUp, onPointerCancel: this.removePointer, onTouchMove: this.handleTouchMove, onPointerDown: this.handleCanvasPointerDown, onDoubleClick: this.handleCanvasDoubleClick }), this.state.userToFollow && (_jsx(FollowMode, { width: this.state.width, height: this.state.height, userToFollow: this.state.userToFollow, onDisconnect: this.maybeUnfollowRemoteUser })), this.renderFrameNames()] }), this.renderEmbeddables()] }) }) }) }) }) }) }) }));
|
|
878
885
|
}
|
|
879
886
|
focusContainer = () => {
|
|
880
887
|
this.excalidrawContainerRef.current?.focus();
|
|
@@ -924,7 +931,7 @@ class App extends React.Component {
|
|
|
924
931
|
mutateElement(frameElement, { customData: { generationData: data } }, false);
|
|
925
932
|
}
|
|
926
933
|
this.magicGenerations.set(frameElement.id, data);
|
|
927
|
-
this.
|
|
934
|
+
this.triggerRender();
|
|
928
935
|
};
|
|
929
936
|
getTextFromElements(elements) {
|
|
930
937
|
const text = elements
|
|
@@ -1122,7 +1129,7 @@ class App extends React.Component {
|
|
|
1122
1129
|
opacity: 100,
|
|
1123
1130
|
locked: false,
|
|
1124
1131
|
});
|
|
1125
|
-
this.scene.
|
|
1132
|
+
this.scene.insertElement(frame);
|
|
1126
1133
|
for (const child of selectedElements) {
|
|
1127
1134
|
mutateElement(child, { frameId: frame.id });
|
|
1128
1135
|
}
|
|
@@ -1146,13 +1153,13 @@ class App extends React.Component {
|
|
|
1146
1153
|
if (shouldUpdateStrokeColor) {
|
|
1147
1154
|
this.syncActionResult({
|
|
1148
1155
|
appState: { ...this.state, currentItemStrokeColor: color },
|
|
1149
|
-
|
|
1156
|
+
storeAction: StoreAction.CAPTURE,
|
|
1150
1157
|
});
|
|
1151
1158
|
}
|
|
1152
1159
|
else {
|
|
1153
1160
|
this.syncActionResult({
|
|
1154
1161
|
appState: { ...this.state, currentItemBackgroundColor: color },
|
|
1155
|
-
|
|
1162
|
+
storeAction: StoreAction.CAPTURE,
|
|
1156
1163
|
});
|
|
1157
1164
|
}
|
|
1158
1165
|
}
|
|
@@ -1166,6 +1173,7 @@ class App extends React.Component {
|
|
|
1166
1173
|
}
|
|
1167
1174
|
return el;
|
|
1168
1175
|
}),
|
|
1176
|
+
storeAction: StoreAction.CAPTURE,
|
|
1169
1177
|
});
|
|
1170
1178
|
}
|
|
1171
1179
|
},
|
|
@@ -1176,6 +1184,13 @@ class App extends React.Component {
|
|
|
1176
1184
|
if (this.unmounted || actionResult === false) {
|
|
1177
1185
|
return;
|
|
1178
1186
|
}
|
|
1187
|
+
if (actionResult.storeAction === StoreAction.UPDATE) {
|
|
1188
|
+
this.store.shouldUpdateSnapshot();
|
|
1189
|
+
}
|
|
1190
|
+
else if (actionResult.storeAction === StoreAction.CAPTURE) {
|
|
1191
|
+
this.store.shouldCaptureIncrement();
|
|
1192
|
+
}
|
|
1193
|
+
let didUpdate = false;
|
|
1179
1194
|
let editingElement = null;
|
|
1180
1195
|
if (actionResult.elements) {
|
|
1181
1196
|
actionResult.elements.forEach((element) => {
|
|
@@ -1186,9 +1201,7 @@ class App extends React.Component {
|
|
|
1186
1201
|
}
|
|
1187
1202
|
});
|
|
1188
1203
|
this.scene.replaceAllElements(actionResult.elements);
|
|
1189
|
-
|
|
1190
|
-
this.history.resumeRecording();
|
|
1191
|
-
}
|
|
1204
|
+
didUpdate = true;
|
|
1192
1205
|
}
|
|
1193
1206
|
if (actionResult.files) {
|
|
1194
1207
|
this.files = actionResult.replaceFiles
|
|
@@ -1197,9 +1210,6 @@ class App extends React.Component {
|
|
|
1197
1210
|
this.addNewImagesToImageCache();
|
|
1198
1211
|
}
|
|
1199
1212
|
if (actionResult.appState || editingElement || this.state.contextMenu) {
|
|
1200
|
-
if (actionResult.commitToHistory) {
|
|
1201
|
-
this.history.resumeRecording();
|
|
1202
|
-
}
|
|
1203
1213
|
let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
|
|
1204
1214
|
let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
|
|
1205
1215
|
let gridSize = actionResult?.appState?.gridSize || null;
|
|
@@ -1237,11 +1247,11 @@ class App extends React.Component {
|
|
|
1237
1247
|
name,
|
|
1238
1248
|
errorMessage,
|
|
1239
1249
|
});
|
|
1240
|
-
}, () => {
|
|
1241
|
-
if (actionResult.syncHistory) {
|
|
1242
|
-
this.history.setCurrentState(this.state, this.scene.getElementsIncludingDeleted());
|
|
1243
|
-
}
|
|
1244
1250
|
});
|
|
1251
|
+
didUpdate = true;
|
|
1252
|
+
}
|
|
1253
|
+
if (!didUpdate && actionResult.storeAction !== StoreAction.NONE) {
|
|
1254
|
+
this.scene.triggerUpdate();
|
|
1245
1255
|
}
|
|
1246
1256
|
});
|
|
1247
1257
|
// Lifecycle
|
|
@@ -1258,6 +1268,9 @@ class App extends React.Component {
|
|
|
1258
1268
|
resetHistory = () => {
|
|
1259
1269
|
this.history.clear();
|
|
1260
1270
|
};
|
|
1271
|
+
resetStore = () => {
|
|
1272
|
+
this.store.clear();
|
|
1273
|
+
};
|
|
1261
1274
|
/**
|
|
1262
1275
|
* Resets scene & history.
|
|
1263
1276
|
* ! Do not use to clear scene user action !
|
|
@@ -1269,6 +1282,7 @@ class App extends React.Component {
|
|
|
1269
1282
|
isLoading: opts?.resetLoadingState ? false : state.isLoading,
|
|
1270
1283
|
theme: this.state.theme,
|
|
1271
1284
|
}));
|
|
1285
|
+
this.resetStore();
|
|
1272
1286
|
this.resetHistory();
|
|
1273
1287
|
});
|
|
1274
1288
|
initializeScene = async () => {
|
|
@@ -1290,7 +1304,12 @@ class App extends React.Component {
|
|
|
1290
1304
|
}
|
|
1291
1305
|
let initialData = null;
|
|
1292
1306
|
try {
|
|
1293
|
-
|
|
1307
|
+
if (typeof this.props.initialData === "function") {
|
|
1308
|
+
initialData = (await this.props.initialData()) || null;
|
|
1309
|
+
}
|
|
1310
|
+
else {
|
|
1311
|
+
initialData = (await this.props.initialData) || null;
|
|
1312
|
+
}
|
|
1294
1313
|
if (initialData?.libraryItems) {
|
|
1295
1314
|
this.library
|
|
1296
1315
|
.updateLibrary({
|
|
@@ -1338,16 +1357,17 @@ class App extends React.Component {
|
|
|
1338
1357
|
}),
|
|
1339
1358
|
};
|
|
1340
1359
|
}
|
|
1341
|
-
|
|
1342
|
-
// (looking at you Safari), so on init we manually load fonts for current
|
|
1343
|
-
// text elements on canvas, and rerender them once done. This also
|
|
1344
|
-
// seems faster even in browsers that do fire the loadingdone event.
|
|
1345
|
-
this.fonts.loadFontsForElements(scene.elements);
|
|
1360
|
+
this.resetStore();
|
|
1346
1361
|
this.resetHistory();
|
|
1347
1362
|
this.syncActionResult({
|
|
1348
1363
|
...scene,
|
|
1349
|
-
|
|
1364
|
+
storeAction: StoreAction.UPDATE,
|
|
1350
1365
|
});
|
|
1366
|
+
// FontFaceSet loadingdone event we listen on may not always
|
|
1367
|
+
// fire (looking at you Safari), so on init we manually load all
|
|
1368
|
+
// fonts and rerender scene text elements once done. This also
|
|
1369
|
+
// seems faster even in browsers that do fire the loadingdone event.
|
|
1370
|
+
this.fonts.load();
|
|
1351
1371
|
};
|
|
1352
1372
|
isMobileBreakpoint = (width, height) => {
|
|
1353
1373
|
return (width < MQ_MAX_WIDTH_PORTRAIT ||
|
|
@@ -1417,9 +1437,20 @@ class App extends React.Component {
|
|
|
1417
1437
|
configurable: true,
|
|
1418
1438
|
value: this.history,
|
|
1419
1439
|
},
|
|
1440
|
+
store: {
|
|
1441
|
+
configurable: true,
|
|
1442
|
+
value: this.store,
|
|
1443
|
+
},
|
|
1444
|
+
fonts: {
|
|
1445
|
+
configurable: true,
|
|
1446
|
+
value: this.fonts,
|
|
1447
|
+
},
|
|
1420
1448
|
});
|
|
1421
1449
|
}
|
|
1422
|
-
this.
|
|
1450
|
+
this.store.onStoreIncrementEmitter.on((increment) => {
|
|
1451
|
+
this.history.record(increment.elementsChange, increment.appStateChange);
|
|
1452
|
+
});
|
|
1453
|
+
this.scene.onUpdate(this.triggerRender);
|
|
1423
1454
|
this.addEventListeners();
|
|
1424
1455
|
if (this.props.autoFocus && this.excalidrawContainerRef.current) {
|
|
1425
1456
|
this.focusContainer();
|
|
@@ -1455,19 +1486,22 @@ class App extends React.Component {
|
|
|
1455
1486
|
}
|
|
1456
1487
|
}
|
|
1457
1488
|
componentWillUnmount() {
|
|
1489
|
+
window.launchQueue?.setConsumer(() => { });
|
|
1458
1490
|
this.renderer.destroy();
|
|
1491
|
+
this.scene.destroy();
|
|
1459
1492
|
this.scene = new Scene();
|
|
1493
|
+
this.fonts = new Fonts({ scene: this.scene });
|
|
1460
1494
|
this.renderer = new Renderer(this.scene);
|
|
1461
1495
|
this.files = {};
|
|
1462
1496
|
this.imageCache.clear();
|
|
1463
1497
|
this.resizeObserver?.disconnect();
|
|
1464
1498
|
this.unmounted = true;
|
|
1465
1499
|
this.removeEventListeners();
|
|
1466
|
-
this.scene.destroy();
|
|
1467
1500
|
this.library.destroy();
|
|
1468
1501
|
this.laserTrails.stop();
|
|
1469
1502
|
this.eraserTrail.stop();
|
|
1470
1503
|
this.onChangeEmitter.clear();
|
|
1504
|
+
this.store.onStoreIncrementEmitter.clear();
|
|
1471
1505
|
ShapeCache.destroy();
|
|
1472
1506
|
SnapCache.destroy();
|
|
1473
1507
|
clearTimeout(touchTimeout);
|
|
@@ -1511,15 +1545,18 @@ class App extends React.Component {
|
|
|
1511
1545
|
this.onRemoveEventListenersEmitter.once(addEventListener(document, EVENT.KEYDOWN, this.onKeyDown, false));
|
|
1512
1546
|
}
|
|
1513
1547
|
this.onRemoveEventListenersEmitter.once(addEventListener(this.excalidrawContainerRef.current, EVENT.WHEEL, this.onWheel, { passive: false }), addEventListener(window, EVENT.MESSAGE, this.onWindowMessage, false), addEventListener(document, EVENT.POINTER_UP, this.removePointer), // #3553
|
|
1514
|
-
addEventListener(document, EVENT.COPY, this.onCopy), addEventListener(document, EVENT.KEYUP, this.onKeyUp, { passive: true }), addEventListener(document, EVENT.
|
|
1548
|
+
addEventListener(document, EVENT.COPY, this.onCopy), addEventListener(document, EVENT.KEYUP, this.onKeyUp, { passive: true }), addEventListener(document, EVENT.POINTER_MOVE, this.updateCurrentCursorPosition),
|
|
1515
1549
|
// rerender text elements on font load to fix #637 && #1553
|
|
1516
1550
|
addEventListener(document.fonts, "loadingdone", (event) => {
|
|
1517
1551
|
const loadedFontFaces = event.fontfaces;
|
|
1518
|
-
this.fonts.
|
|
1552
|
+
this.fonts.onLoaded(loadedFontFaces);
|
|
1519
1553
|
}),
|
|
1520
1554
|
// Safari-only desktop pinch zoom
|
|
1521
1555
|
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
1556
|
this.maybeCleanupAfterMissingPointerUp(null);
|
|
1557
|
+
// browsers (chrome?) tend to free up memory a lot, which results
|
|
1558
|
+
// in canvas context being cleared. Thus re-render on focus.
|
|
1559
|
+
this.triggerRender(true);
|
|
1523
1560
|
}));
|
|
1524
1561
|
if (this.state.viewModeEnabled) {
|
|
1525
1562
|
return;
|
|
@@ -1535,7 +1572,8 @@ class App extends React.Component {
|
|
|
1535
1572
|
componentDidUpdate(prevProps, prevState) {
|
|
1536
1573
|
this.updateEmbeddables();
|
|
1537
1574
|
const elements = this.scene.getElementsIncludingDeleted();
|
|
1538
|
-
const elementsMap = this.scene.
|
|
1575
|
+
const elementsMap = this.scene.getElementsMapIncludingDeleted();
|
|
1576
|
+
const nonDeletedElementsMap = this.scene.getNonDeletedElementsMap();
|
|
1539
1577
|
if (!this.state.showWelcomeScreen && !elements.length) {
|
|
1540
1578
|
this.setState({ showWelcomeScreen: true });
|
|
1541
1579
|
}
|
|
@@ -1608,10 +1646,10 @@ class App extends React.Component {
|
|
|
1608
1646
|
gridSize: this.props.gridModeEnabled ? GRID_SIZE : null,
|
|
1609
1647
|
});
|
|
1610
1648
|
}
|
|
1611
|
-
this.excalidrawContainerRef.current?.classList.toggle("theme--dark", this.state.theme ===
|
|
1649
|
+
this.excalidrawContainerRef.current?.classList.toggle("theme--dark", this.state.theme === THEME.DARK);
|
|
1612
1650
|
if (this.state.editingLinearElement &&
|
|
1613
1651
|
!this.state.selectedElementIds[this.state.editingLinearElement.elementId]) {
|
|
1614
|
-
// defer so that the
|
|
1652
|
+
// defer so that the storeAction flag isn't reset via current update
|
|
1615
1653
|
setTimeout(() => {
|
|
1616
1654
|
// execute only if the condition still holds when the deferred callback
|
|
1617
1655
|
// executes (it can be scheduled multiple times depending on how
|
|
@@ -1636,9 +1674,9 @@ class App extends React.Component {
|
|
|
1636
1674
|
multiElement != null &&
|
|
1637
1675
|
isBindingEnabled(this.state) &&
|
|
1638
1676
|
isBindingElement(multiElement, false)) {
|
|
1639
|
-
maybeBindLinearElement(multiElement, this.state,
|
|
1677
|
+
maybeBindLinearElement(multiElement, this.state, tupleToCoors(LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, nonDeletedElementsMap)), this.scene.getNonDeletedElementsMap());
|
|
1640
1678
|
}
|
|
1641
|
-
this.
|
|
1679
|
+
this.store.commit(elementsMap, this.state);
|
|
1642
1680
|
// Do not notify consumers if we're still loading the scene. Among other
|
|
1643
1681
|
// potential issues, this fixes a case where the tab isn't focused during
|
|
1644
1682
|
// init, which would trigger onChange with empty elements, which would then
|
|
@@ -1825,6 +1863,24 @@ class App extends React.Component {
|
|
|
1825
1863
|
});
|
|
1826
1864
|
}
|
|
1827
1865
|
else if (data.text) {
|
|
1866
|
+
if (data.text && isMaybeMermaidDefinition(data.text)) {
|
|
1867
|
+
const api = await import("@excalidraw/mermaid-to-excalidraw");
|
|
1868
|
+
try {
|
|
1869
|
+
const { elements: skeletonElements, files } = await api.parseMermaidToExcalidraw(data.text);
|
|
1870
|
+
const elements = convertToExcalidrawElements(skeletonElements, {
|
|
1871
|
+
regenerateIds: true,
|
|
1872
|
+
});
|
|
1873
|
+
this.addElementsFromPasteOrLibrary({
|
|
1874
|
+
elements,
|
|
1875
|
+
files,
|
|
1876
|
+
position: "cursor",
|
|
1877
|
+
});
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1880
|
+
catch (err) {
|
|
1881
|
+
console.warn(`parsing pasted text as mermaid definition failed: ${err.message}`);
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1828
1884
|
const nonEmptyLines = normalizeEOL(data.text)
|
|
1829
1885
|
.split(/\n+/)
|
|
1830
1886
|
.map((s) => s.trim())
|
|
@@ -1894,16 +1950,15 @@ class App extends React.Component {
|
|
|
1894
1950
|
}), {
|
|
1895
1951
|
randomizeSeed: !opts.retainSeed,
|
|
1896
1952
|
});
|
|
1897
|
-
const
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
];
|
|
1953
|
+
const prevElements = this.scene.getElementsIncludingDeleted();
|
|
1954
|
+
const nextElements = [...prevElements, ...newElements];
|
|
1955
|
+
syncMovedIndices(nextElements, arrayToMap(newElements));
|
|
1901
1956
|
const topLayerFrame = this.getTopLayerFrameAtSceneCoords({ x, y });
|
|
1902
1957
|
if (topLayerFrame) {
|
|
1903
1958
|
const eligibleElements = filterElementsEligibleAsFrameChildren(newElements, topLayerFrame);
|
|
1904
|
-
addElementsToFrame(
|
|
1959
|
+
addElementsToFrame(nextElements, eligibleElements, topLayerFrame);
|
|
1905
1960
|
}
|
|
1906
|
-
this.scene.replaceAllElements(
|
|
1961
|
+
this.scene.replaceAllElements(nextElements);
|
|
1907
1962
|
newElements.forEach((newElement) => {
|
|
1908
1963
|
if (isTextElement(newElement) && isBoundToContainer(newElement)) {
|
|
1909
1964
|
const container = getContainerElement(newElement, this.scene.getElementsMapIncludingDeleted());
|
|
@@ -1913,7 +1968,7 @@ class App extends React.Component {
|
|
|
1913
1968
|
if (opts.files) {
|
|
1914
1969
|
this.files = { ...this.files, ...opts.files };
|
|
1915
1970
|
}
|
|
1916
|
-
this.
|
|
1971
|
+
this.store.shouldCaptureIncrement();
|
|
1917
1972
|
const nextElementsToSelect = excludeElementsInFramesFromSelection(newElements);
|
|
1918
1973
|
this.setState({
|
|
1919
1974
|
...this.state,
|
|
@@ -2030,27 +2085,46 @@ class App extends React.Component {
|
|
|
2030
2085
|
text,
|
|
2031
2086
|
fontSize: this.state.currentItemFontSize,
|
|
2032
2087
|
fontFamily: this.state.currentItemFontFamily,
|
|
2033
|
-
textAlign:
|
|
2088
|
+
textAlign: DEFAULT_TEXT_ALIGN,
|
|
2034
2089
|
verticalAlign: DEFAULT_VERTICAL_ALIGN,
|
|
2035
2090
|
locked: false,
|
|
2036
2091
|
};
|
|
2092
|
+
const fontString = getFontString({
|
|
2093
|
+
fontSize: textElementProps.fontSize,
|
|
2094
|
+
fontFamily: textElementProps.fontFamily,
|
|
2095
|
+
});
|
|
2096
|
+
const lineHeight = getLineHeight(textElementProps.fontFamily);
|
|
2097
|
+
const [x1, , x2] = getVisibleSceneBounds(this.state);
|
|
2098
|
+
// long texts should not go beyond 800 pixels in width nor should it go below 200 px
|
|
2099
|
+
const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.5, 800), 200);
|
|
2037
2100
|
const LINE_GAP = 10;
|
|
2038
2101
|
let currentY = y;
|
|
2039
2102
|
const lines = isPlainPaste ? [text] : text.split("\n");
|
|
2040
2103
|
const textElements = lines.reduce((acc, line, idx) => {
|
|
2041
|
-
const
|
|
2042
|
-
|
|
2043
|
-
if (text.length) {
|
|
2104
|
+
const originalText = line.trim();
|
|
2105
|
+
if (originalText.length) {
|
|
2044
2106
|
const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
|
|
2045
2107
|
x,
|
|
2046
2108
|
y: currentY,
|
|
2047
2109
|
});
|
|
2110
|
+
let metrics = measureText(originalText, fontString, lineHeight);
|
|
2111
|
+
const isTextUnwrapped = metrics.width > maxTextWidth;
|
|
2112
|
+
const text = isTextUnwrapped
|
|
2113
|
+
? wrapText(originalText, fontString, maxTextWidth)
|
|
2114
|
+
: originalText;
|
|
2115
|
+
metrics = isTextUnwrapped
|
|
2116
|
+
? measureText(text, fontString, lineHeight)
|
|
2117
|
+
: metrics;
|
|
2118
|
+
const startX = x - metrics.width / 2;
|
|
2119
|
+
const startY = currentY - metrics.height / 2;
|
|
2048
2120
|
const element = newTextElement({
|
|
2049
2121
|
...textElementProps,
|
|
2050
|
-
x,
|
|
2051
|
-
y:
|
|
2122
|
+
x: startX,
|
|
2123
|
+
y: startY,
|
|
2052
2124
|
text,
|
|
2125
|
+
originalText,
|
|
2053
2126
|
lineHeight,
|
|
2127
|
+
autoResize: !isTextUnwrapped,
|
|
2054
2128
|
frameId: topLayerFrame ? topLayerFrame.id : null,
|
|
2055
2129
|
});
|
|
2056
2130
|
acc.push(element);
|
|
@@ -2071,16 +2145,7 @@ class App extends React.Component {
|
|
|
2071
2145
|
if (textElements.length === 0) {
|
|
2072
2146
|
return;
|
|
2073
2147
|
}
|
|
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
|
-
}
|
|
2148
|
+
this.scene.insertElements(textElements);
|
|
2084
2149
|
this.setState({
|
|
2085
2150
|
selectedElementIds: makeNextSelectedElementIds(Object.fromEntries(textElements.map((el) => [el.id, true])), this.state),
|
|
2086
2151
|
});
|
|
@@ -2096,7 +2161,7 @@ class App extends React.Component {
|
|
|
2096
2161
|
});
|
|
2097
2162
|
PLAIN_PASTE_TOAST_SHOWN = true;
|
|
2098
2163
|
}
|
|
2099
|
-
this.
|
|
2164
|
+
this.store.shouldCaptureIncrement();
|
|
2100
2165
|
}
|
|
2101
2166
|
setAppState = (state, callback) => {
|
|
2102
2167
|
this.setState(state, callback);
|
|
@@ -2278,25 +2343,49 @@ class App extends React.Component {
|
|
|
2278
2343
|
ShapeCache.delete(element);
|
|
2279
2344
|
}
|
|
2280
2345
|
});
|
|
2281
|
-
this.scene.
|
|
2346
|
+
this.scene.triggerUpdate();
|
|
2282
2347
|
this.addNewImagesToImageCache();
|
|
2283
2348
|
});
|
|
2284
2349
|
updateScene = withBatchedUpdates((sceneData) => {
|
|
2285
|
-
|
|
2286
|
-
|
|
2350
|
+
const nextElements = syncInvalidIndices(sceneData.elements ?? []);
|
|
2351
|
+
if (sceneData.storeAction && sceneData.storeAction !== StoreAction.NONE) {
|
|
2352
|
+
const prevCommittedAppState = this.store.snapshot.appState;
|
|
2353
|
+
const prevCommittedElements = this.store.snapshot.elements;
|
|
2354
|
+
const nextCommittedAppState = sceneData.appState
|
|
2355
|
+
? Object.assign({}, prevCommittedAppState, sceneData.appState) // new instance, with partial appstate applied to previously captured one, including hidden prop inside `prevCommittedAppState`
|
|
2356
|
+
: prevCommittedAppState;
|
|
2357
|
+
const nextCommittedElements = sceneData.elements
|
|
2358
|
+
? this.store.filterUncomittedElements(this.scene.getElementsMapIncludingDeleted(), // Only used to detect uncomitted local elements
|
|
2359
|
+
arrayToMap(nextElements))
|
|
2360
|
+
: prevCommittedElements;
|
|
2361
|
+
// 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
|
|
2362
|
+
// do NOT schedule store actions (execute after re-render), as it might cause unexpected concurrency issues if not handled well
|
|
2363
|
+
if (sceneData.storeAction === StoreAction.CAPTURE) {
|
|
2364
|
+
this.store.captureIncrement(nextCommittedElements, nextCommittedAppState);
|
|
2365
|
+
}
|
|
2366
|
+
else if (sceneData.storeAction === StoreAction.UPDATE) {
|
|
2367
|
+
this.store.updateSnapshot(nextCommittedElements, nextCommittedAppState);
|
|
2368
|
+
}
|
|
2287
2369
|
}
|
|
2288
2370
|
if (sceneData.appState) {
|
|
2289
2371
|
this.setState(sceneData.appState);
|
|
2290
2372
|
}
|
|
2291
2373
|
if (sceneData.elements) {
|
|
2292
|
-
this.scene.replaceAllElements(
|
|
2374
|
+
this.scene.replaceAllElements(nextElements);
|
|
2293
2375
|
}
|
|
2294
2376
|
if (sceneData.collaborators) {
|
|
2295
2377
|
this.setState({ collaborators: sceneData.collaborators });
|
|
2296
2378
|
}
|
|
2297
2379
|
});
|
|
2298
|
-
|
|
2299
|
-
|
|
2380
|
+
triggerRender = (
|
|
2381
|
+
/** force always re-renders canvas even if no change */
|
|
2382
|
+
force) => {
|
|
2383
|
+
if (force === true) {
|
|
2384
|
+
this.scene.triggerUpdate();
|
|
2385
|
+
}
|
|
2386
|
+
else {
|
|
2387
|
+
this.setState({});
|
|
2388
|
+
}
|
|
2300
2389
|
};
|
|
2301
2390
|
/**
|
|
2302
2391
|
* @returns whether the menu was toggled on or off
|
|
@@ -2355,8 +2444,7 @@ class App extends React.Component {
|
|
|
2355
2444
|
!event.altKey) {
|
|
2356
2445
|
this.setToast({
|
|
2357
2446
|
message: t("commandPalette.shortcutHint", {
|
|
2358
|
-
|
|
2359
|
-
shortcutTwo: getShortcutFromShortcutName("commandPalette", 1),
|
|
2447
|
+
shortcut: getShortcutFromShortcutName("commandPalette"),
|
|
2360
2448
|
}),
|
|
2361
2449
|
});
|
|
2362
2450
|
event.preventDefault();
|
|
@@ -2464,7 +2552,9 @@ class App extends React.Component {
|
|
|
2464
2552
|
simultaneouslyUpdated: selectedElements,
|
|
2465
2553
|
});
|
|
2466
2554
|
});
|
|
2467
|
-
this.
|
|
2555
|
+
this.setState({
|
|
2556
|
+
suggestedBindings: getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap()),
|
|
2557
|
+
});
|
|
2468
2558
|
event.preventDefault();
|
|
2469
2559
|
}
|
|
2470
2560
|
else if (event.key === KEYS.ENTER) {
|
|
@@ -2476,7 +2566,7 @@ class App extends React.Component {
|
|
|
2476
2566
|
if (!this.state.editingLinearElement ||
|
|
2477
2567
|
this.state.editingLinearElement.elementId !==
|
|
2478
2568
|
selectedElements[0].id) {
|
|
2479
|
-
this.
|
|
2569
|
+
this.store.shouldCaptureIncrement();
|
|
2480
2570
|
this.setState({
|
|
2481
2571
|
editingLinearElement: new LinearElementEditor(selectedElement),
|
|
2482
2572
|
});
|
|
@@ -2548,6 +2638,21 @@ class App extends React.Component {
|
|
|
2548
2638
|
event.stopPropagation();
|
|
2549
2639
|
}
|
|
2550
2640
|
}
|
|
2641
|
+
if (!event[KEYS.CTRL_OR_CMD] &&
|
|
2642
|
+
event.shiftKey &&
|
|
2643
|
+
event.key.toLowerCase() === KEYS.F) {
|
|
2644
|
+
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
2645
|
+
if (this.state.activeTool.type === "selection" &&
|
|
2646
|
+
!selectedElements.length) {
|
|
2647
|
+
return;
|
|
2648
|
+
}
|
|
2649
|
+
if (this.state.activeTool.type === "text" ||
|
|
2650
|
+
selectedElements.find((element) => isTextElement(element) ||
|
|
2651
|
+
getBoundTextElement(element, this.scene.getNonDeletedElementsMap()))) {
|
|
2652
|
+
event.preventDefault();
|
|
2653
|
+
this.setState({ openPopup: "fontFamily" });
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2551
2656
|
if (event.key === KEYS.K && !event.altKey && !event[KEYS.CTRL_OR_CMD]) {
|
|
2552
2657
|
if (this.state.activeTool.type === "laser") {
|
|
2553
2658
|
this.setActiveTool({ type: "selection" });
|
|
@@ -2602,11 +2707,7 @@ class App extends React.Component {
|
|
|
2602
2707
|
this.setState({ isBindingEnabled: true });
|
|
2603
2708
|
}
|
|
2604
2709
|
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);
|
|
2710
|
+
bindOrUnbindLinearElements(this.scene.getSelectedElements(this.state).filter(isLinearElement), this.scene.getNonDeletedElementsMap(), isBindingEnabled(this.state), this.state.selectedLinearElement?.selectedPointsIndices ?? []);
|
|
2610
2711
|
this.setState({ suggestedBindings: [] });
|
|
2611
2712
|
}
|
|
2612
2713
|
});
|
|
@@ -2644,6 +2745,9 @@ class App extends React.Component {
|
|
|
2644
2745
|
originSnapOffset: null,
|
|
2645
2746
|
activeEmbeddable: null,
|
|
2646
2747
|
};
|
|
2748
|
+
if (nextActiveTool.type === "freedraw") {
|
|
2749
|
+
this.store.shouldCaptureIncrement();
|
|
2750
|
+
}
|
|
2647
2751
|
if (nextActiveTool.type !== "selection") {
|
|
2648
2752
|
return {
|
|
2649
2753
|
...prevState,
|
|
@@ -2741,15 +2845,16 @@ class App extends React.Component {
|
|
|
2741
2845
|
});
|
|
2742
2846
|
handleTextWysiwyg(element, { isExistingElement = false, }) {
|
|
2743
2847
|
const elementsMap = this.scene.getElementsMapIncludingDeleted();
|
|
2744
|
-
const updateElement = (
|
|
2848
|
+
const updateElement = (nextOriginalText, isDeleted) => {
|
|
2745
2849
|
this.scene.replaceAllElements([
|
|
2746
2850
|
// Not sure why we include deleted elements as well hence using deleted elements map
|
|
2747
2851
|
...this.scene.getElementsIncludingDeleted().map((_element) => {
|
|
2748
2852
|
if (_element.id === element.id && isTextElement(_element)) {
|
|
2749
|
-
return
|
|
2750
|
-
|
|
2751
|
-
isDeleted,
|
|
2752
|
-
|
|
2853
|
+
return newElementWith(_element, {
|
|
2854
|
+
originalText: nextOriginalText,
|
|
2855
|
+
isDeleted: isDeleted ?? _element.isDeleted,
|
|
2856
|
+
// returns (wrapped) text and new dimensions
|
|
2857
|
+
...refreshTextDimensions(_element, getContainerElement(_element, elementsMap), elementsMap, nextOriginalText),
|
|
2753
2858
|
});
|
|
2754
2859
|
}
|
|
2755
2860
|
return _element;
|
|
@@ -2769,15 +2874,15 @@ class App extends React.Component {
|
|
|
2769
2874
|
viewportY - this.state.offsetTop,
|
|
2770
2875
|
];
|
|
2771
2876
|
},
|
|
2772
|
-
onChange: withBatchedUpdates((
|
|
2773
|
-
updateElement(
|
|
2877
|
+
onChange: withBatchedUpdates((nextOriginalText) => {
|
|
2878
|
+
updateElement(nextOriginalText, false);
|
|
2774
2879
|
if (isNonDeletedElement(element)) {
|
|
2775
2880
|
updateBoundElements(element, elementsMap);
|
|
2776
2881
|
}
|
|
2777
2882
|
}),
|
|
2778
|
-
onSubmit: withBatchedUpdates(({
|
|
2779
|
-
const isDeleted = !
|
|
2780
|
-
updateElement(
|
|
2883
|
+
onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
|
|
2884
|
+
const isDeleted = !nextOriginalText.trim();
|
|
2885
|
+
updateElement(nextOriginalText, isDeleted);
|
|
2781
2886
|
// select the created text element only if submitting via keyboard
|
|
2782
2887
|
// (when submitting via click it should act as signal to deselect)
|
|
2783
2888
|
if (!isDeleted && viaKeyboard) {
|
|
@@ -2797,7 +2902,7 @@ class App extends React.Component {
|
|
|
2797
2902
|
]);
|
|
2798
2903
|
}
|
|
2799
2904
|
if (!isDeleted || isExistingElement) {
|
|
2800
|
-
this.
|
|
2905
|
+
this.store.shouldCaptureIncrement();
|
|
2801
2906
|
}
|
|
2802
2907
|
this.setState({
|
|
2803
2908
|
draggingElement: null,
|
|
@@ -2811,12 +2916,17 @@ class App extends React.Component {
|
|
|
2811
2916
|
element,
|
|
2812
2917
|
excalidrawContainer: this.excalidrawContainerRef.current,
|
|
2813
2918
|
app: this,
|
|
2919
|
+
// when text is selected, it's hard (at least on iOS) to re-position the
|
|
2920
|
+
// caret (i.e. deselect). There's not much use for always selecting
|
|
2921
|
+
// the text on edit anyway (and users can select-all from contextmenu
|
|
2922
|
+
// if needed)
|
|
2923
|
+
autoSelect: !this.device.isTouchScreen,
|
|
2814
2924
|
});
|
|
2815
2925
|
// deselect all other elements when inserting text
|
|
2816
2926
|
this.deselectElements();
|
|
2817
2927
|
// do an initial update to re-initialize element position since we were
|
|
2818
2928
|
// modifying element's x/y for sake of editor (case: syncing to remote)
|
|
2819
|
-
updateElement(element.
|
|
2929
|
+
updateElement(element.originalText, false);
|
|
2820
2930
|
}
|
|
2821
2931
|
deselectElements() {
|
|
2822
2932
|
this.setState({
|
|
@@ -2835,6 +2945,21 @@ class App extends React.Component {
|
|
|
2835
2945
|
}
|
|
2836
2946
|
return null;
|
|
2837
2947
|
}
|
|
2948
|
+
getBoundTextShape(element) {
|
|
2949
|
+
const boundTextElement = getBoundTextElement(element, this.scene.getNonDeletedElementsMap());
|
|
2950
|
+
if (boundTextElement) {
|
|
2951
|
+
if (element.type === "arrow") {
|
|
2952
|
+
return getElementShape({
|
|
2953
|
+
...boundTextElement,
|
|
2954
|
+
// arrow's bound text accurate position is not stored in the element's property
|
|
2955
|
+
// but rather calculated and returned from the following static method
|
|
2956
|
+
...LinearElementEditor.getBoundTextElementPosition(element, boundTextElement, this.scene.getNonDeletedElementsMap()),
|
|
2957
|
+
}, this.scene.getNonDeletedElementsMap());
|
|
2958
|
+
}
|
|
2959
|
+
return getElementShape(boundTextElement, this.scene.getNonDeletedElementsMap());
|
|
2960
|
+
}
|
|
2961
|
+
return null;
|
|
2962
|
+
}
|
|
2838
2963
|
getElementAtPosition(x, y, opts) {
|
|
2839
2964
|
const allHitElements = this.getElementsAtPosition(x, y, opts?.includeBoundTextElement, opts?.includeLockedElements);
|
|
2840
2965
|
if (allHitElements.length > 1) {
|
|
@@ -2848,9 +2973,20 @@ class App extends React.Component {
|
|
|
2848
2973
|
const elementWithHighestZIndex = allHitElements[allHitElements.length - 1];
|
|
2849
2974
|
// If we're hitting element with highest z-index only on its bounding box
|
|
2850
2975
|
// while also hitting other element figure, the latter should be considered.
|
|
2851
|
-
return
|
|
2852
|
-
|
|
2853
|
-
|
|
2976
|
+
return hitElementItself({
|
|
2977
|
+
x,
|
|
2978
|
+
y,
|
|
2979
|
+
element: elementWithHighestZIndex,
|
|
2980
|
+
shape: getElementShape(elementWithHighestZIndex, this.scene.getNonDeletedElementsMap()),
|
|
2981
|
+
// when overlapping, we would like to be more precise
|
|
2982
|
+
// this also avoids the need to update past tests
|
|
2983
|
+
threshold: this.getElementHitThreshold() / 2,
|
|
2984
|
+
frameNameBound: isFrameLikeElement(elementWithHighestZIndex)
|
|
2985
|
+
? this.frameNameBoundsCache.get(elementWithHighestZIndex)
|
|
2986
|
+
: null,
|
|
2987
|
+
})
|
|
2988
|
+
? elementWithHighestZIndex
|
|
2989
|
+
: allHitElements[allHitElements.length - 2];
|
|
2854
2990
|
}
|
|
2855
2991
|
if (allHitElements.length === 1) {
|
|
2856
2992
|
return allHitElements[0];
|
|
@@ -2858,15 +2994,17 @@ class App extends React.Component {
|
|
|
2858
2994
|
return null;
|
|
2859
2995
|
}
|
|
2860
2996
|
getElementsAtPosition(x, y, includeBoundTextElement = false, includeLockedElements = false) {
|
|
2861
|
-
const
|
|
2997
|
+
const iframeLikes = [];
|
|
2998
|
+
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
2999
|
+
const elements = (includeBoundTextElement && includeLockedElements
|
|
2862
3000
|
? this.scene.getNonDeletedElements()
|
|
2863
3001
|
: this.scene
|
|
2864
3002
|
.getNonDeletedElements()
|
|
2865
3003
|
.filter((element) => (includeLockedElements || !element.locked) &&
|
|
2866
3004
|
(includeBoundTextElement ||
|
|
2867
|
-
!(isTextElement(element) && element.containerId)))
|
|
2868
|
-
|
|
2869
|
-
|
|
3005
|
+
!(isTextElement(element) && element.containerId))))
|
|
3006
|
+
.filter((el) => this.hitElement(x, y, el))
|
|
3007
|
+
.filter((element) => {
|
|
2870
3008
|
// hitting a frame's element from outside the frame is not considered a hit
|
|
2871
3009
|
const containingFrame = getContainingFrame(element, elementsMap);
|
|
2872
3010
|
return containingFrame &&
|
|
@@ -2874,9 +3012,82 @@ class App extends React.Component {
|
|
|
2874
3012
|
this.state.frameRendering.clip
|
|
2875
3013
|
? isCursorInFrame({ x, y }, containingFrame, elementsMap)
|
|
2876
3014
|
: true;
|
|
3015
|
+
})
|
|
3016
|
+
.filter((el) => {
|
|
3017
|
+
// The parameter elements comes ordered from lower z-index to higher.
|
|
3018
|
+
// We want to preserve that order on the returned array.
|
|
3019
|
+
// Exception being embeddables which should be on top of everything else in
|
|
3020
|
+
// terms of hit testing.
|
|
3021
|
+
if (isIframeElement(el)) {
|
|
3022
|
+
iframeLikes.push(el);
|
|
3023
|
+
return false;
|
|
3024
|
+
}
|
|
3025
|
+
return true;
|
|
3026
|
+
})
|
|
3027
|
+
.concat(iframeLikes);
|
|
3028
|
+
return elements;
|
|
3029
|
+
}
|
|
3030
|
+
getElementHitThreshold() {
|
|
3031
|
+
return DEFAULT_COLLISION_THRESHOLD / this.state.zoom.value;
|
|
3032
|
+
}
|
|
3033
|
+
hitElement(x, y, element, considerBoundingBox = true) {
|
|
3034
|
+
// if the element is selected, then hit test is done against its bounding box
|
|
3035
|
+
if (considerBoundingBox &&
|
|
3036
|
+
this.state.selectedElementIds[element.id] &&
|
|
3037
|
+
shouldShowBoundingBox([element], this.state)) {
|
|
3038
|
+
const selectionShape = getSelectionBoxShape(element, this.scene.getNonDeletedElementsMap(), this.getElementHitThreshold());
|
|
3039
|
+
return isPointInShape([x, y], selectionShape);
|
|
3040
|
+
}
|
|
3041
|
+
// take bound text element into consideration for hit collision as well
|
|
3042
|
+
const hitBoundTextOfElement = hitElementBoundText(x, y, this.getBoundTextShape(element));
|
|
3043
|
+
if (hitBoundTextOfElement) {
|
|
3044
|
+
return true;
|
|
3045
|
+
}
|
|
3046
|
+
return hitElementItself({
|
|
3047
|
+
x,
|
|
3048
|
+
y,
|
|
3049
|
+
element,
|
|
3050
|
+
shape: getElementShape(element, this.scene.getNonDeletedElementsMap()),
|
|
3051
|
+
threshold: this.getElementHitThreshold(),
|
|
3052
|
+
frameNameBound: isFrameLikeElement(element)
|
|
3053
|
+
? this.frameNameBoundsCache.get(element)
|
|
3054
|
+
: null,
|
|
2877
3055
|
});
|
|
2878
3056
|
}
|
|
2879
|
-
|
|
3057
|
+
getTextBindableContainerAtPosition(x, y) {
|
|
3058
|
+
const elements = this.scene.getNonDeletedElements();
|
|
3059
|
+
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
3060
|
+
if (selectedElements.length === 1) {
|
|
3061
|
+
return isTextBindableContainer(selectedElements[0], false)
|
|
3062
|
+
? selectedElements[0]
|
|
3063
|
+
: null;
|
|
3064
|
+
}
|
|
3065
|
+
let hitElement = null;
|
|
3066
|
+
// We need to do hit testing from front (end of the array) to back (beginning of the array)
|
|
3067
|
+
for (let index = elements.length - 1; index >= 0; --index) {
|
|
3068
|
+
if (elements[index].isDeleted) {
|
|
3069
|
+
continue;
|
|
3070
|
+
}
|
|
3071
|
+
const [x1, y1, x2, y2] = getElementAbsoluteCoords(elements[index], this.scene.getNonDeletedElementsMap());
|
|
3072
|
+
if (isArrowElement(elements[index]) &&
|
|
3073
|
+
hitElementItself({
|
|
3074
|
+
x,
|
|
3075
|
+
y,
|
|
3076
|
+
element: elements[index],
|
|
3077
|
+
shape: getElementShape(elements[index], this.scene.getNonDeletedElementsMap()),
|
|
3078
|
+
threshold: this.getElementHitThreshold(),
|
|
3079
|
+
})) {
|
|
3080
|
+
hitElement = elements[index];
|
|
3081
|
+
break;
|
|
3082
|
+
}
|
|
3083
|
+
else if (x1 < x && x < x2 && y1 < y && y < y2) {
|
|
3084
|
+
hitElement = elements[index];
|
|
3085
|
+
break;
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
return isTextBindableContainer(hitElement, false) ? hitElement : null;
|
|
3089
|
+
}
|
|
3090
|
+
startTextEditing = ({ sceneX, sceneY, insertAtParentCenter = true, container, autoEdit = true, }) => {
|
|
2880
3091
|
let shouldBindToContainer = false;
|
|
2881
3092
|
let parentCenterPosition = insertAtParentCenter &&
|
|
2882
3093
|
this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);
|
|
@@ -2903,7 +3114,7 @@ class App extends React.Component {
|
|
|
2903
3114
|
existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);
|
|
2904
3115
|
}
|
|
2905
3116
|
const fontFamily = existingTextElement?.fontFamily || this.state.currentItemFontFamily;
|
|
2906
|
-
const lineHeight = existingTextElement?.lineHeight ||
|
|
3117
|
+
const lineHeight = existingTextElement?.lineHeight || getLineHeight(fontFamily);
|
|
2907
3118
|
const fontSize = this.state.currentItemFontSize;
|
|
2908
3119
|
if (!existingTextElement &&
|
|
2909
3120
|
shouldBindToContainer &&
|
|
@@ -2974,15 +3185,20 @@ class App extends React.Component {
|
|
|
2974
3185
|
this.scene.insertElementAtIndex(element, containerIndex + 1);
|
|
2975
3186
|
}
|
|
2976
3187
|
else {
|
|
2977
|
-
this.scene.
|
|
3188
|
+
this.scene.insertElement(element);
|
|
2978
3189
|
}
|
|
2979
3190
|
}
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
3191
|
+
if (autoEdit || existingTextElement || container) {
|
|
3192
|
+
this.handleTextWysiwyg(element, {
|
|
3193
|
+
isExistingElement: !!existingTextElement,
|
|
3194
|
+
});
|
|
3195
|
+
}
|
|
3196
|
+
else {
|
|
3197
|
+
this.setState({
|
|
3198
|
+
draggingElement: element,
|
|
3199
|
+
multiElement: null,
|
|
3200
|
+
});
|
|
3201
|
+
}
|
|
2986
3202
|
};
|
|
2987
3203
|
handleCanvasDoubleClick = (event) => {
|
|
2988
3204
|
// case: double-clicking with arrow/line tool selected would both create
|
|
@@ -2999,7 +3215,7 @@ class App extends React.Component {
|
|
|
2999
3215
|
if (event[KEYS.CTRL_OR_CMD] &&
|
|
3000
3216
|
(!this.state.editingLinearElement ||
|
|
3001
3217
|
this.state.editingLinearElement.elementId !== selectedElements[0].id)) {
|
|
3002
|
-
this.
|
|
3218
|
+
this.store.shouldCaptureIncrement();
|
|
3003
3219
|
this.setState({
|
|
3004
3220
|
editingLinearElement: new LinearElementEditor(selectedElements[0]),
|
|
3005
3221
|
});
|
|
@@ -3014,6 +3230,7 @@ class App extends React.Component {
|
|
|
3014
3230
|
const selectedGroupId = hitElement &&
|
|
3015
3231
|
getSelectedGroupIdForElement(hitElement, this.state.selectedGroupIds);
|
|
3016
3232
|
if (selectedGroupId) {
|
|
3233
|
+
this.store.shouldCaptureIncrement();
|
|
3017
3234
|
this.setState((prevState) => ({
|
|
3018
3235
|
...prevState,
|
|
3019
3236
|
...selectGroupsForSelectedElements({
|
|
@@ -3033,11 +3250,17 @@ class App extends React.Component {
|
|
|
3033
3250
|
});
|
|
3034
3251
|
return;
|
|
3035
3252
|
}
|
|
3036
|
-
const container =
|
|
3253
|
+
const container = this.getTextBindableContainerAtPosition(sceneX, sceneY);
|
|
3037
3254
|
if (container) {
|
|
3038
3255
|
if (hasBoundTextElement(container) ||
|
|
3039
3256
|
!isTransparent(container.backgroundColor) ||
|
|
3040
|
-
|
|
3257
|
+
hitElementItself({
|
|
3258
|
+
x: sceneX,
|
|
3259
|
+
y: sceneY,
|
|
3260
|
+
element: container,
|
|
3261
|
+
shape: getElementShape(container, this.scene.getNonDeletedElementsMap()),
|
|
3262
|
+
threshold: this.getElementHitThreshold(),
|
|
3263
|
+
})) {
|
|
3041
3264
|
const midPoint = getContainerCenter(container, this.state, this.scene.getNonDeletedElementsMap());
|
|
3042
3265
|
sceneX = midPoint.x;
|
|
3043
3266
|
sceneY = midPoint.y;
|
|
@@ -3092,7 +3315,7 @@ class App extends React.Component {
|
|
|
3092
3315
|
}
|
|
3093
3316
|
if (!customEvent?.defaultPrevented) {
|
|
3094
3317
|
const target = isLocalLink(url) ? "_self" : "_blank";
|
|
3095
|
-
const newWindow = window.open(undefined, target
|
|
3318
|
+
const newWindow = window.open(undefined, target);
|
|
3096
3319
|
// https://mathiasbynens.github.io/rel-noopener/
|
|
3097
3320
|
if (newWindow) {
|
|
3098
3321
|
newWindow.opener = null;
|
|
@@ -3142,8 +3365,11 @@ class App extends React.Component {
|
|
|
3142
3365
|
}, state);
|
|
3143
3366
|
this.translateCanvas({
|
|
3144
3367
|
zoom: zoomState.zoom,
|
|
3145
|
-
|
|
3146
|
-
|
|
3368
|
+
// 2x multiplier is just a magic number that makes this work correctly
|
|
3369
|
+
// on touchscreen devices (note: if we get report that panning is slower/faster
|
|
3370
|
+
// than actual movement, consider swapping with devicePixelRatio)
|
|
3371
|
+
scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),
|
|
3372
|
+
scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),
|
|
3147
3373
|
shouldCacheIgnoreZoom: true,
|
|
3148
3374
|
});
|
|
3149
3375
|
});
|
|
@@ -3308,15 +3534,23 @@ class App extends React.Component {
|
|
|
3308
3534
|
if (selectedElements.length === 1 &&
|
|
3309
3535
|
!isOverScrollBar &&
|
|
3310
3536
|
!this.state.editingLinearElement) {
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3537
|
+
// for linear elements, we'd like to prioritize point dragging over edge resizing
|
|
3538
|
+
// therefore, we update and check hovered point index first
|
|
3539
|
+
if (this.state.selectedLinearElement) {
|
|
3540
|
+
this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);
|
|
3541
|
+
}
|
|
3542
|
+
if (!this.state.selectedLinearElement ||
|
|
3543
|
+
this.state.selectedLinearElement.hoverPointIndex === -1) {
|
|
3544
|
+
const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);
|
|
3545
|
+
if (elementWithTransformHandleType &&
|
|
3546
|
+
elementWithTransformHandleType.transformHandleType) {
|
|
3547
|
+
setCursor(this.interactiveCanvas, getCursorForResizingElement(elementWithTransformHandleType));
|
|
3548
|
+
return;
|
|
3549
|
+
}
|
|
3316
3550
|
}
|
|
3317
3551
|
}
|
|
3318
3552
|
else if (selectedElements.length > 1 && !isOverScrollBar) {
|
|
3319
|
-
const transformHandleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType);
|
|
3553
|
+
const transformHandleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.device);
|
|
3320
3554
|
if (transformHandleType) {
|
|
3321
3555
|
setCursor(this.interactiveCanvas, getCursorForResizingElement({
|
|
3322
3556
|
transformHandleType,
|
|
@@ -3420,7 +3654,7 @@ class App extends React.Component {
|
|
|
3420
3654
|
}
|
|
3421
3655
|
};
|
|
3422
3656
|
const distance = distance2d(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y, scenePointer.x, scenePointer.y);
|
|
3423
|
-
const threshold =
|
|
3657
|
+
const threshold = this.getElementHitThreshold();
|
|
3424
3658
|
const point = { ...pointerDownState.lastCoords };
|
|
3425
3659
|
let samplingInterval = 0;
|
|
3426
3660
|
while (samplingInterval <= distance) {
|
|
@@ -3456,7 +3690,7 @@ class App extends React.Component {
|
|
|
3456
3690
|
}
|
|
3457
3691
|
}
|
|
3458
3692
|
this.elementsPendingErasure = new Set(this.elementsPendingErasure);
|
|
3459
|
-
this.
|
|
3693
|
+
this.triggerRender();
|
|
3460
3694
|
}
|
|
3461
3695
|
};
|
|
3462
3696
|
// set touch moving for mobile context menu
|
|
@@ -3466,30 +3700,29 @@ class App extends React.Component {
|
|
|
3466
3700
|
handleHoverSelectedLinearElement(linearElementEditor, scenePointerX, scenePointerY) {
|
|
3467
3701
|
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
3468
3702
|
const element = LinearElementEditor.getElement(linearElementEditor.elementId, elementsMap);
|
|
3469
|
-
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
3470
3703
|
if (!element) {
|
|
3471
3704
|
return;
|
|
3472
3705
|
}
|
|
3473
3706
|
if (this.state.selectedLinearElement) {
|
|
3474
3707
|
let hoverPointIndex = -1;
|
|
3475
3708
|
let segmentMidPointHoveredCoords = null;
|
|
3476
|
-
if (
|
|
3709
|
+
if (hitElementItself({
|
|
3710
|
+
x: scenePointerX,
|
|
3711
|
+
y: scenePointerY,
|
|
3712
|
+
element,
|
|
3713
|
+
shape: getElementShape(element, this.scene.getNonDeletedElementsMap()),
|
|
3714
|
+
})) {
|
|
3477
3715
|
hoverPointIndex = LinearElementEditor.getPointIndexUnderCursor(element, elementsMap, this.state.zoom, scenePointerX, scenePointerY);
|
|
3478
3716
|
segmentMidPointHoveredCoords =
|
|
3479
3717
|
LinearElementEditor.getSegmentMidpointHitCoords(linearElementEditor, { x: scenePointerX, y: scenePointerY }, this.state, this.scene.getNonDeletedElementsMap());
|
|
3480
3718
|
if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {
|
|
3481
3719
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
|
3482
3720
|
}
|
|
3483
|
-
else {
|
|
3721
|
+
else if (this.hitElement(scenePointerX, scenePointerY, element)) {
|
|
3484
3722
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
|
3485
3723
|
}
|
|
3486
3724
|
}
|
|
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())) {
|
|
3725
|
+
else if (this.hitElement(scenePointerX, scenePointerY, element)) {
|
|
3493
3726
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
|
3494
3727
|
}
|
|
3495
3728
|
if (this.state.selectedLinearElement.hoverPointIndex !== hoverPointIndex) {
|
|
@@ -3556,6 +3789,7 @@ class App extends React.Component {
|
|
|
3556
3789
|
return obj;
|
|
3557
3790
|
}, {}), this.state),
|
|
3558
3791
|
},
|
|
3792
|
+
storeAction: StoreAction.UPDATE,
|
|
3559
3793
|
});
|
|
3560
3794
|
return;
|
|
3561
3795
|
}
|
|
@@ -3667,7 +3901,6 @@ class App extends React.Component {
|
|
|
3667
3901
|
}
|
|
3668
3902
|
if (this.state.activeTool.type === "text") {
|
|
3669
3903
|
this.handleTextOnPointerDown(event, pointerDownState);
|
|
3670
|
-
return;
|
|
3671
3904
|
}
|
|
3672
3905
|
else if (this.state.activeTool.type === "arrow" ||
|
|
3673
3906
|
this.state.activeTool.type === "line") {
|
|
@@ -3995,8 +4228,11 @@ class App extends React.Component {
|
|
|
3995
4228
|
const elements = this.scene.getNonDeletedElements();
|
|
3996
4229
|
const elementsMap = this.scene.getNonDeletedElementsMap();
|
|
3997
4230
|
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
3998
|
-
if (selectedElements.length === 1 &&
|
|
3999
|
-
|
|
4231
|
+
if (selectedElements.length === 1 &&
|
|
4232
|
+
!this.state.editingLinearElement &&
|
|
4233
|
+
!(this.state.selectedLinearElement &&
|
|
4234
|
+
this.state.selectedLinearElement.hoverPointIndex !== -1)) {
|
|
4235
|
+
const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);
|
|
4000
4236
|
if (elementWithTransformHandleType != null) {
|
|
4001
4237
|
this.setState({
|
|
4002
4238
|
resizingElement: elementWithTransformHandleType.element,
|
|
@@ -4006,7 +4242,7 @@ class App extends React.Component {
|
|
|
4006
4242
|
}
|
|
4007
4243
|
}
|
|
4008
4244
|
else if (selectedElements.length > 1) {
|
|
4009
|
-
pointerDownState.resize.handleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType);
|
|
4245
|
+
pointerDownState.resize.handleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.device);
|
|
4010
4246
|
}
|
|
4011
4247
|
if (pointerDownState.resize.handleType) {
|
|
4012
4248
|
pointerDownState.resize.isResizing = true;
|
|
@@ -4020,7 +4256,7 @@ class App extends React.Component {
|
|
|
4020
4256
|
else {
|
|
4021
4257
|
if (this.state.selectedLinearElement) {
|
|
4022
4258
|
const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;
|
|
4023
|
-
const ret = LinearElementEditor.handlePointerDown(event, this.state, this.
|
|
4259
|
+
const ret = LinearElementEditor.handlePointerDown(event, this.state, this.store, pointerDownState.origin, linearElementEditor, this);
|
|
4024
4260
|
if (ret.hitElement) {
|
|
4025
4261
|
pointerDownState.hit.element = ret.hitElement;
|
|
4026
4262
|
}
|
|
@@ -4181,7 +4417,7 @@ class App extends React.Component {
|
|
|
4181
4417
|
return false;
|
|
4182
4418
|
}
|
|
4183
4419
|
// How many pixels off the shape boundary we still consider a hit
|
|
4184
|
-
const threshold =
|
|
4420
|
+
const threshold = this.getElementHitThreshold();
|
|
4185
4421
|
const [x1, y1, x2, y2] = getCommonBounds(selectedElements);
|
|
4186
4422
|
return (point.x > x1 - threshold &&
|
|
4187
4423
|
point.x < x2 + threshold &&
|
|
@@ -4201,7 +4437,7 @@ class App extends React.Component {
|
|
|
4201
4437
|
includeBoundTextElement: true,
|
|
4202
4438
|
});
|
|
4203
4439
|
// FIXME
|
|
4204
|
-
let container =
|
|
4440
|
+
let container = this.getTextBindableContainerAtPosition(sceneX, sceneY);
|
|
4205
4441
|
if (hasBoundTextElement(element)) {
|
|
4206
4442
|
container = element;
|
|
4207
4443
|
sceneX = element.x + element.width / 2;
|
|
@@ -4212,6 +4448,7 @@ class App extends React.Component {
|
|
|
4212
4448
|
sceneY,
|
|
4213
4449
|
insertAtParentCenter: !event.altKey,
|
|
4214
4450
|
container,
|
|
4451
|
+
autoEdit: false,
|
|
4215
4452
|
});
|
|
4216
4453
|
resetCursor(this.interactiveCanvas);
|
|
4217
4454
|
if (!this.state.activeTool.locked) {
|
|
@@ -4259,8 +4496,8 @@ class App extends React.Component {
|
|
|
4259
4496
|
points: [[0, 0]],
|
|
4260
4497
|
pressures,
|
|
4261
4498
|
});
|
|
4262
|
-
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.
|
|
4263
|
-
this.scene.
|
|
4499
|
+
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.getNonDeletedElementsMap());
|
|
4500
|
+
this.scene.insertElement(element);
|
|
4264
4501
|
this.setState({
|
|
4265
4502
|
draggingElement: element,
|
|
4266
4503
|
editingElement: element,
|
|
@@ -4288,10 +4525,7 @@ class App extends React.Component {
|
|
|
4288
4525
|
width,
|
|
4289
4526
|
height,
|
|
4290
4527
|
});
|
|
4291
|
-
this.scene.
|
|
4292
|
-
...this.scene.getElementsIncludingDeleted(),
|
|
4293
|
-
element,
|
|
4294
|
-
]);
|
|
4528
|
+
this.scene.insertElement(element);
|
|
4295
4529
|
return element;
|
|
4296
4530
|
};
|
|
4297
4531
|
//create rectangle element with youtube top left on nearest grid point width / hight 640/360
|
|
@@ -4326,10 +4560,7 @@ class App extends React.Component {
|
|
|
4326
4560
|
height: embedLink.intrinsicSize.h,
|
|
4327
4561
|
link,
|
|
4328
4562
|
});
|
|
4329
|
-
this.scene.
|
|
4330
|
-
...this.scene.getElementsIncludingDeleted(),
|
|
4331
|
-
element,
|
|
4332
|
-
]);
|
|
4563
|
+
this.scene.insertElement(element);
|
|
4333
4564
|
return element;
|
|
4334
4565
|
};
|
|
4335
4566
|
createImageElement = ({ sceneX, sceneY, addToFrameUnderCursor = true, }) => {
|
|
@@ -4437,8 +4668,8 @@ class App extends React.Component {
|
|
|
4437
4668
|
mutateElement(element, {
|
|
4438
4669
|
points: [...element.points, [0, 0]],
|
|
4439
4670
|
});
|
|
4440
|
-
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.
|
|
4441
|
-
this.scene.
|
|
4671
|
+
const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.getNonDeletedElementsMap());
|
|
4672
|
+
this.scene.insertElement(element);
|
|
4442
4673
|
this.setState({
|
|
4443
4674
|
draggingElement: element,
|
|
4444
4675
|
editingElement: element,
|
|
@@ -4498,7 +4729,7 @@ class App extends React.Component {
|
|
|
4498
4729
|
});
|
|
4499
4730
|
}
|
|
4500
4731
|
else {
|
|
4501
|
-
this.scene.
|
|
4732
|
+
this.scene.insertElement(element);
|
|
4502
4733
|
this.setState({
|
|
4503
4734
|
multiElement: null,
|
|
4504
4735
|
draggingElement: element,
|
|
@@ -4520,10 +4751,7 @@ class App extends React.Component {
|
|
|
4520
4751
|
const frame = type === TOOL_TYPE.magicframe
|
|
4521
4752
|
? newMagicFrameElement(constructorOpts)
|
|
4522
4753
|
: newFrameElement(constructorOpts);
|
|
4523
|
-
this.scene.
|
|
4524
|
-
...this.scene.getElementsIncludingDeleted(),
|
|
4525
|
-
frame,
|
|
4526
|
-
]);
|
|
4754
|
+
this.scene.insertElement(frame);
|
|
4527
4755
|
this.setState({
|
|
4528
4756
|
multiElement: null,
|
|
4529
4757
|
draggingElement: frame,
|
|
@@ -4737,7 +4965,9 @@ class App extends React.Component {
|
|
|
4737
4965
|
// able to select and interact with the text input
|
|
4738
4966
|
!this.state.editingFrame &&
|
|
4739
4967
|
dragSelectedElements(pointerDownState, selectedElements, dragOffset, this.state, this.scene, snapOffset, event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);
|
|
4740
|
-
this.
|
|
4968
|
+
this.setState({
|
|
4969
|
+
suggestedBindings: getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap()),
|
|
4970
|
+
});
|
|
4741
4971
|
// We duplicate the selected element if alt is pressed on pointer move
|
|
4742
4972
|
if (event.altKey && !pointerDownState.hit.hasBeenDuplicated) {
|
|
4743
4973
|
// Move the currently selected elements to the top of the z index stack, and
|
|
@@ -4781,6 +5011,7 @@ class App extends React.Component {
|
|
|
4781
5011
|
}
|
|
4782
5012
|
}
|
|
4783
5013
|
const nextSceneElements = [...nextElements, ...elementsToAppend];
|
|
5014
|
+
syncMovedIndices(nextSceneElements, arrayToMap(elementsToAppend));
|
|
4784
5015
|
bindTextToShapeAfterDuplication(nextElements, elementsToAppend, oldIdToDuplicatedId);
|
|
4785
5016
|
fixBindingsAfterDuplication(nextSceneElements, elementsToAppend, oldIdToDuplicatedId, "duplicatesServeAsOld");
|
|
4786
5017
|
bindElementsToFramesAfterDuplication(nextSceneElements, elementsToAppend, oldIdToDuplicatedId);
|
|
@@ -4972,7 +5203,7 @@ class App extends React.Component {
|
|
|
4972
5203
|
this.actionManager.executeAction(actionFinalize);
|
|
4973
5204
|
}
|
|
4974
5205
|
else {
|
|
4975
|
-
const editingLinearElement = LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state, this
|
|
5206
|
+
const editingLinearElement = LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state, this);
|
|
4976
5207
|
if (editingLinearElement !== this.state.editingLinearElement) {
|
|
4977
5208
|
this.setState({
|
|
4978
5209
|
editingLinearElement,
|
|
@@ -4991,7 +5222,7 @@ class App extends React.Component {
|
|
|
4991
5222
|
}
|
|
4992
5223
|
}
|
|
4993
5224
|
else {
|
|
4994
|
-
const linearElementEditor = LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state, this
|
|
5225
|
+
const linearElementEditor = LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state, this);
|
|
4995
5226
|
const { startBindingElement, endBindingElement } = linearElementEditor;
|
|
4996
5227
|
const element = this.scene.getElement(linearElementEditor.elementId);
|
|
4997
5228
|
if (isBindingElement(element)) {
|
|
@@ -5060,7 +5291,7 @@ class App extends React.Component {
|
|
|
5060
5291
|
}
|
|
5061
5292
|
if (isLinearElement(draggingElement)) {
|
|
5062
5293
|
if (draggingElement.points.length > 1) {
|
|
5063
|
-
this.
|
|
5294
|
+
this.store.shouldCaptureIncrement();
|
|
5064
5295
|
}
|
|
5065
5296
|
const pointerCoords = viewportCoordsToSceneCoords(childEvent, this.state);
|
|
5066
5297
|
if (!pointerDownState.drag.hasOccurred &&
|
|
@@ -5083,7 +5314,7 @@ class App extends React.Component {
|
|
|
5083
5314
|
else if (pointerDownState.drag.hasOccurred && !multiElement) {
|
|
5084
5315
|
if (isBindingEnabled(this.state) &&
|
|
5085
5316
|
isBindingElement(draggingElement, false)) {
|
|
5086
|
-
maybeBindLinearElement(draggingElement, this.state, this.scene
|
|
5317
|
+
maybeBindLinearElement(draggingElement, this.state, pointerCoords, this.scene.getNonDeletedElementsMap());
|
|
5087
5318
|
}
|
|
5088
5319
|
this.setState({ suggestedBindings: [], startBoundElement: null });
|
|
5089
5320
|
if (!activeTool.locked) {
|
|
@@ -5108,15 +5339,34 @@ class App extends React.Component {
|
|
|
5108
5339
|
}
|
|
5109
5340
|
return;
|
|
5110
5341
|
}
|
|
5342
|
+
if (isTextElement(draggingElement)) {
|
|
5343
|
+
const minWidth = getMinTextElementWidth(getFontString({
|
|
5344
|
+
fontSize: draggingElement.fontSize,
|
|
5345
|
+
fontFamily: draggingElement.fontFamily,
|
|
5346
|
+
}), draggingElement.lineHeight);
|
|
5347
|
+
if (draggingElement.width < minWidth) {
|
|
5348
|
+
mutateElement(draggingElement, {
|
|
5349
|
+
autoResize: true,
|
|
5350
|
+
});
|
|
5351
|
+
}
|
|
5352
|
+
this.resetCursor();
|
|
5353
|
+
this.handleTextWysiwyg(draggingElement, {
|
|
5354
|
+
isExistingElement: true,
|
|
5355
|
+
});
|
|
5356
|
+
}
|
|
5111
5357
|
if (activeTool.type !== "selection" &&
|
|
5112
5358
|
draggingElement &&
|
|
5113
5359
|
isInvisiblySmallElement(draggingElement)) {
|
|
5114
5360
|
// remove invisible element which was added in onPointerDown
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5361
|
+
// update the store snapshot, so that invisible elements are not captured by the store
|
|
5362
|
+
this.updateScene({
|
|
5363
|
+
elements: this.scene
|
|
5364
|
+
.getElementsIncludingDeleted()
|
|
5365
|
+
.filter((el) => el.id !== draggingElement.id),
|
|
5366
|
+
appState: {
|
|
5367
|
+
draggingElement: null,
|
|
5368
|
+
},
|
|
5369
|
+
storeAction: StoreAction.UPDATE,
|
|
5120
5370
|
});
|
|
5121
5371
|
return;
|
|
5122
5372
|
}
|
|
@@ -5139,7 +5389,7 @@ class App extends React.Component {
|
|
|
5139
5389
|
groupIds: [],
|
|
5140
5390
|
});
|
|
5141
5391
|
removeElementsFromFrame([linearElement], this.scene.getNonDeletedElementsMap());
|
|
5142
|
-
this.scene.
|
|
5392
|
+
this.scene.triggerUpdate();
|
|
5143
5393
|
}
|
|
5144
5394
|
}
|
|
5145
5395
|
}
|
|
@@ -5197,12 +5447,16 @@ class App extends React.Component {
|
|
|
5197
5447
|
mutateElement(draggingElement, getNormalizedDimensions(draggingElement));
|
|
5198
5448
|
}
|
|
5199
5449
|
if (resizingElement) {
|
|
5200
|
-
this.
|
|
5450
|
+
this.store.shouldCaptureIncrement();
|
|
5201
5451
|
}
|
|
5202
5452
|
if (resizingElement && isInvisiblySmallElement(resizingElement)) {
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5453
|
+
// update the store snapshot, so that invisible elements are not captured by the store
|
|
5454
|
+
this.updateScene({
|
|
5455
|
+
elements: this.scene
|
|
5456
|
+
.getElementsIncludingDeleted()
|
|
5457
|
+
.filter((el) => el.id !== resizingElement.id),
|
|
5458
|
+
storeAction: StoreAction.UPDATE,
|
|
5459
|
+
});
|
|
5206
5460
|
}
|
|
5207
5461
|
// handle frame membership for resizing frames and/or selected elements
|
|
5208
5462
|
if (pointerDownState.resize.isResizing) {
|
|
@@ -5357,10 +5611,23 @@ class App extends React.Component {
|
|
|
5357
5611
|
}));
|
|
5358
5612
|
}
|
|
5359
5613
|
}
|
|
5360
|
-
if (
|
|
5614
|
+
if (
|
|
5615
|
+
// not dragged
|
|
5616
|
+
!pointerDownState.drag.hasOccurred &&
|
|
5617
|
+
// not resized
|
|
5361
5618
|
!this.state.isResizing &&
|
|
5619
|
+
// only hitting the bounding box of the previous hit element
|
|
5362
5620
|
((hitElement &&
|
|
5363
|
-
|
|
5621
|
+
hitElementBoundingBoxOnly({
|
|
5622
|
+
x: pointerDownState.origin.x,
|
|
5623
|
+
y: pointerDownState.origin.y,
|
|
5624
|
+
element: hitElement,
|
|
5625
|
+
shape: getElementShape(hitElement, this.scene.getNonDeletedElementsMap()),
|
|
5626
|
+
threshold: this.getElementHitThreshold(),
|
|
5627
|
+
frameNameBound: isFrameLikeElement(hitElement)
|
|
5628
|
+
? this.frameNameBoundsCache.get(hitElement)
|
|
5629
|
+
: null,
|
|
5630
|
+
}, elementsMap)) ||
|
|
5364
5631
|
(!hitElement &&
|
|
5365
5632
|
pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements))) {
|
|
5366
5633
|
if (this.state.editingLinearElement) {
|
|
@@ -5375,6 +5642,8 @@ class App extends React.Component {
|
|
|
5375
5642
|
activeEmbeddable: null,
|
|
5376
5643
|
});
|
|
5377
5644
|
}
|
|
5645
|
+
// reset cursor
|
|
5646
|
+
setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO);
|
|
5378
5647
|
return;
|
|
5379
5648
|
}
|
|
5380
5649
|
if (!activeTool.locked &&
|
|
@@ -5392,13 +5661,17 @@ class App extends React.Component {
|
|
|
5392
5661
|
}));
|
|
5393
5662
|
}
|
|
5394
5663
|
if (activeTool.type !== "selection" ||
|
|
5395
|
-
isSomeElementSelected(this.scene.getNonDeletedElements(), this.state)
|
|
5396
|
-
this.
|
|
5664
|
+
isSomeElementSelected(this.scene.getNonDeletedElements(), this.state) ||
|
|
5665
|
+
!isShallowEqual(this.state.previousSelectedElementIds, this.state.selectedElementIds)) {
|
|
5666
|
+
this.store.shouldCaptureIncrement();
|
|
5397
5667
|
}
|
|
5398
5668
|
if (pointerDownState.drag.hasOccurred || isResizing || isRotating) {
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5669
|
+
// We only allow binding via linear elements, specifically via dragging
|
|
5670
|
+
// the endpoints ("start" or "end").
|
|
5671
|
+
const linearElements = this.scene
|
|
5672
|
+
.getSelectedElements(this.state)
|
|
5673
|
+
.filter(isLinearElement);
|
|
5674
|
+
bindOrUnbindLinearElements(linearElements, this.scene.getNonDeletedElementsMap(), isBindingEnabled(this.state), this.state.selectedLinearElement?.selectedPointsIndices ?? []);
|
|
5402
5675
|
}
|
|
5403
5676
|
if (activeTool.type === "laser") {
|
|
5404
5677
|
this.laserTrails.endPath();
|
|
@@ -5433,7 +5706,7 @@ class App extends React.Component {
|
|
|
5433
5706
|
}
|
|
5434
5707
|
restoreReadyToEraseElements = () => {
|
|
5435
5708
|
this.elementsPendingErasure = new Set();
|
|
5436
|
-
this.
|
|
5709
|
+
this.triggerRender();
|
|
5437
5710
|
};
|
|
5438
5711
|
eraseElements = () => {
|
|
5439
5712
|
let didChange = false;
|
|
@@ -5449,7 +5722,7 @@ class App extends React.Component {
|
|
|
5449
5722
|
});
|
|
5450
5723
|
this.elementsPendingErasure = new Set();
|
|
5451
5724
|
if (didChange) {
|
|
5452
|
-
this.
|
|
5725
|
+
this.store.shouldCaptureIncrement();
|
|
5453
5726
|
this.scene.replaceAllElements(elements);
|
|
5454
5727
|
}
|
|
5455
5728
|
};
|
|
@@ -5552,7 +5825,7 @@ class App extends React.Component {
|
|
|
5552
5825
|
this.setState({ errorMessage: t("errors.imageToolNotSupported") });
|
|
5553
5826
|
return;
|
|
5554
5827
|
}
|
|
5555
|
-
this.scene.
|
|
5828
|
+
this.scene.insertElement(imageElement);
|
|
5556
5829
|
try {
|
|
5557
5830
|
return await this.initializeImage({
|
|
5558
5831
|
imageFile,
|
|
@@ -5725,7 +5998,7 @@ class App extends React.Component {
|
|
|
5725
5998
|
if (uncachedImageElements.length) {
|
|
5726
5999
|
const { updatedFiles } = await this.updateImageCache(uncachedImageElements, files);
|
|
5727
6000
|
if (updatedFiles.size) {
|
|
5728
|
-
this.scene.
|
|
6001
|
+
this.scene.triggerUpdate();
|
|
5729
6002
|
}
|
|
5730
6003
|
}
|
|
5731
6004
|
};
|
|
@@ -5741,7 +6014,7 @@ class App extends React.Component {
|
|
|
5741
6014
|
}
|
|
5742
6015
|
};
|
|
5743
6016
|
maybeSuggestBindingAtCursor = (pointerCoords) => {
|
|
5744
|
-
const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this.scene.
|
|
6017
|
+
const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this.scene.getNonDeletedElementsMap());
|
|
5745
6018
|
this.setState({
|
|
5746
6019
|
suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : [],
|
|
5747
6020
|
});
|
|
@@ -5756,7 +6029,7 @@ class App extends React.Component {
|
|
|
5756
6029
|
return;
|
|
5757
6030
|
}
|
|
5758
6031
|
const suggestedBindings = pointerCoords.reduce((acc, coords) => {
|
|
5759
|
-
const hoveredBindableElement = getHoveredElementForBinding(coords, this.scene.
|
|
6032
|
+
const hoveredBindableElement = getHoveredElementForBinding(coords, this.scene.getNonDeletedElementsMap());
|
|
5760
6033
|
if (hoveredBindableElement != null &&
|
|
5761
6034
|
!isLinearElementSimpleAndAlreadyBound(linearElement, oppositeBindingBoundElement?.id, hoveredBindableElement)) {
|
|
5762
6035
|
acc.push(hoveredBindableElement);
|
|
@@ -5765,13 +6038,6 @@ class App extends React.Component {
|
|
|
5765
6038
|
}, []);
|
|
5766
6039
|
this.setState({ suggestedBindings });
|
|
5767
6040
|
};
|
|
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
6041
|
clearSelection(hitElement) {
|
|
5776
6042
|
this.setState((prevState) => ({
|
|
5777
6043
|
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
|
@@ -5831,7 +6097,7 @@ class App extends React.Component {
|
|
|
5831
6097
|
isLoading: false,
|
|
5832
6098
|
},
|
|
5833
6099
|
replaceFiles: true,
|
|
5834
|
-
|
|
6100
|
+
storeAction: StoreAction.CAPTURE,
|
|
5835
6101
|
});
|
|
5836
6102
|
return;
|
|
5837
6103
|
}
|
|
@@ -5899,9 +6165,10 @@ class App extends React.Component {
|
|
|
5899
6165
|
loadFileToCanvas = async (file, fileHandle) => {
|
|
5900
6166
|
file = await normalizeFile(file);
|
|
5901
6167
|
try {
|
|
6168
|
+
const elements = this.scene.getElementsIncludingDeleted();
|
|
5902
6169
|
let ret;
|
|
5903
6170
|
try {
|
|
5904
|
-
ret = await loadSceneOrLibraryFromBlob(file, this.state,
|
|
6171
|
+
ret = await loadSceneOrLibraryFromBlob(file, this.state, elements, fileHandle);
|
|
5905
6172
|
}
|
|
5906
6173
|
catch (error) {
|
|
5907
6174
|
const imageSceneDataError = error instanceof ImageSceneDataError;
|
|
@@ -5926,6 +6193,10 @@ class App extends React.Component {
|
|
|
5926
6193
|
return;
|
|
5927
6194
|
}
|
|
5928
6195
|
if (ret.type === MIME_TYPES.excalidraw) {
|
|
6196
|
+
// restore the fractional indices by mutating elements
|
|
6197
|
+
syncInvalidIndices(elements.concat(ret.data.elements));
|
|
6198
|
+
// update the store snapshot for old elements, otherwise we would end up with duplicated fractional indices on undo
|
|
6199
|
+
this.store.updateSnapshot(arrayToMap(elements), this.state);
|
|
5929
6200
|
this.setState({ isLoading: true });
|
|
5930
6201
|
this.syncActionResult({
|
|
5931
6202
|
...ret.data,
|
|
@@ -5934,7 +6205,7 @@ class App extends React.Component {
|
|
|
5934
6205
|
isLoading: false,
|
|
5935
6206
|
},
|
|
5936
6207
|
replaceFiles: true,
|
|
5937
|
-
|
|
6208
|
+
storeAction: StoreAction.CAPTURE,
|
|
5938
6209
|
});
|
|
5939
6210
|
}
|
|
5940
6211
|
else if (ret.type === MIME_TYPES.excalidrawlib) {
|
|
@@ -6006,7 +6277,7 @@ class App extends React.Component {
|
|
|
6006
6277
|
}
|
|
6007
6278
|
if (draggingElement.type === "selection" &&
|
|
6008
6279
|
this.state.activeTool.type !== "eraser") {
|
|
6009
|
-
dragNewElement(draggingElement, this.state.activeTool.type, pointerDownState.origin.x, pointerDownState.origin.y, pointerCoords.x, pointerCoords.y, distance(pointerDownState.origin.x, pointerCoords.x), distance(pointerDownState.origin.y, pointerCoords.y), shouldMaintainAspectRatio(event), shouldResizeFromCenter(event));
|
|
6280
|
+
dragNewElement(draggingElement, this.state.activeTool.type, pointerDownState.origin.x, pointerDownState.origin.y, pointerCoords.x, pointerCoords.y, distance(pointerDownState.origin.x, pointerCoords.x), distance(pointerDownState.origin.y, pointerCoords.y), shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), this.state.zoom.value);
|
|
6010
6281
|
}
|
|
6011
6282
|
else {
|
|
6012
6283
|
let [gridX, gridY] = getGridPoint(pointerCoords.x, pointerCoords.y, event[KEYS.CTRL_OR_CMD] ? null : this.state.gridSize);
|
|
@@ -6032,8 +6303,7 @@ class App extends React.Component {
|
|
|
6032
6303
|
});
|
|
6033
6304
|
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
6305
|
? !shouldMaintainAspectRatio(event)
|
|
6035
|
-
: shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), aspectRatio, this.state.originSnapOffset);
|
|
6036
|
-
this.maybeSuggestBindingForAll([draggingElement]);
|
|
6306
|
+
: shouldMaintainAspectRatio(event), shouldResizeFromCenter(event), this.state.zoom.value, aspectRatio, this.state.originSnapOffset);
|
|
6037
6307
|
// highlight elements that are to be added to frames on frames creation
|
|
6038
6308
|
if (this.state.activeTool.type === TOOL_TYPE.frame ||
|
|
6039
6309
|
this.state.activeTool.type === TOOL_TYPE.magicframe) {
|
|
@@ -6087,16 +6357,17 @@ class App extends React.Component {
|
|
|
6087
6357
|
snapLines,
|
|
6088
6358
|
});
|
|
6089
6359
|
}
|
|
6090
|
-
if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.
|
|
6360
|
+
if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.some((element) => isImageElement(element))
|
|
6091
6361
|
? !shouldMaintainAspectRatio(event)
|
|
6092
6362
|
: shouldMaintainAspectRatio(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {
|
|
6093
|
-
this.
|
|
6363
|
+
const suggestedBindings = getSuggestedBindingsForArrows(selectedElements, this.scene.getNonDeletedElementsMap());
|
|
6094
6364
|
const elementsToHighlight = new Set();
|
|
6095
6365
|
selectedFrames.forEach((frame) => {
|
|
6096
6366
|
getElementsInResizingFrame(this.scene.getNonDeletedElements(), frame, this.state, this.scene.getNonDeletedElementsMap()).forEach((element) => elementsToHighlight.add(element));
|
|
6097
6367
|
});
|
|
6098
6368
|
this.setState({
|
|
6099
6369
|
elementsToHighlight: [...elementsToHighlight],
|
|
6370
|
+
suggestedBindings,
|
|
6100
6371
|
});
|
|
6101
6372
|
return true;
|
|
6102
6373
|
}
|
|
@@ -6141,6 +6412,7 @@ class App extends React.Component {
|
|
|
6141
6412
|
return [actionCopy, ...options];
|
|
6142
6413
|
}
|
|
6143
6414
|
return [
|
|
6415
|
+
CONTEXT_MENU_SEPARATOR,
|
|
6144
6416
|
actionCut,
|
|
6145
6417
|
actionCopy,
|
|
6146
6418
|
actionPaste,
|
|
@@ -6153,6 +6425,7 @@ class App extends React.Component {
|
|
|
6153
6425
|
actionPasteStyles,
|
|
6154
6426
|
CONTEXT_MENU_SEPARATOR,
|
|
6155
6427
|
actionGroup,
|
|
6428
|
+
actionTextAutoResize,
|
|
6156
6429
|
actionUnbindText,
|
|
6157
6430
|
actionBindText,
|
|
6158
6431
|
actionWrapTextInContainer,
|
|
@@ -6321,7 +6594,7 @@ export const createTestHook = () => {
|
|
|
6321
6594
|
return this.app?.scene.getElementsIncludingDeleted();
|
|
6322
6595
|
},
|
|
6323
6596
|
set(elements) {
|
|
6324
|
-
return this.app?.scene.replaceAllElements(elements);
|
|
6597
|
+
return this.app?.scene.replaceAllElements(syncInvalidIndices(elements));
|
|
6325
6598
|
},
|
|
6326
6599
|
},
|
|
6327
6600
|
});
|