@excalidraw/excalidraw 0.17.1-88812e0 → 0.17.1-96eeec5

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