@excalidraw/excalidraw 0.17.1-7441-4e2c539 → 0.17.1-a38e82f

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 (249) hide show
  1. package/CHANGELOG.md +52 -2
  2. package/dist/browser/dev/excalidraw-assets-dev/chunk-5VWQDKDR.js +20279 -0
  3. package/dist/browser/dev/excalidraw-assets-dev/chunk-5VWQDKDR.js.map +7 -0
  4. package/dist/browser/dev/excalidraw-assets-dev/{chunk-2W5GQUR4.js → chunk-IM4WTX2M.js} +12 -6
  5. package/dist/browser/dev/excalidraw-assets-dev/chunk-IM4WTX2M.js.map +7 -0
  6. package/dist/browser/dev/excalidraw-assets-dev/{en-OC6JWP3X.js → en-IOBA4CS2.js} +4 -2
  7. package/dist/browser/dev/excalidraw-assets-dev/image-LK4UNFRZ.css +6 -0
  8. package/dist/browser/dev/excalidraw-assets-dev/image-LK4UNFRZ.css.map +7 -0
  9. package/dist/browser/dev/excalidraw-assets-dev/{image-HYNUJ3XL.js → image-VKDAL6BQ.js} +2 -4
  10. package/dist/browser/dev/excalidraw-assets-dev/roundRect-T5BX56ZF.js +161 -0
  11. package/dist/browser/dev/excalidraw-assets-dev/roundRect-T5BX56ZF.js.map +7 -0
  12. package/dist/browser/dev/index.css +189 -129
  13. package/dist/browser/dev/index.css.map +3 -3
  14. package/dist/browser/dev/index.js +34707 -26
  15. package/dist/browser/dev/index.js.map +4 -4
  16. package/dist/browser/prod/excalidraw-assets/chunk-LIG3S5TN.js +11 -0
  17. package/dist/browser/prod/excalidraw-assets/chunk-N2C5DK3B.js +55 -0
  18. package/dist/browser/prod/excalidraw-assets/en-WFZVQ7I6.js +1 -0
  19. package/dist/browser/prod/excalidraw-assets/image-4AT7LYMR.js +1 -0
  20. package/dist/browser/prod/excalidraw-assets/image-X66R2EM5.css +1 -0
  21. package/dist/browser/prod/excalidraw-assets/roundRect-2ACQK4DA.js +1 -0
  22. package/dist/browser/prod/index.css +1 -1
  23. package/dist/browser/prod/index.js +203 -1
  24. package/dist/{prod/en-RLIAOBCI.json → dev/en-TDNWCAOT.json} +9 -5
  25. package/dist/dev/index.css +189 -129
  26. package/dist/dev/index.css.map +3 -3
  27. package/dist/dev/index.js +38445 -39402
  28. package/dist/dev/index.js.map +4 -4
  29. package/dist/excalidraw/actions/actionAddToLibrary.d.ts +12 -12
  30. package/dist/excalidraw/actions/actionAlign.d.ts +6 -6
  31. package/dist/excalidraw/actions/actionAlign.js +2 -1
  32. package/dist/excalidraw/actions/actionBoundText.d.ts +8 -8
  33. package/dist/excalidraw/actions/actionBoundText.js +8 -8
  34. package/dist/excalidraw/actions/actionCanvas.d.ts +46 -46
  35. package/dist/excalidraw/actions/actionClipboard.d.ts +27 -27
  36. package/dist/excalidraw/actions/actionClipboard.js +9 -2
  37. package/dist/excalidraw/actions/actionDeleteSelected.d.ts +12 -12
  38. package/dist/excalidraw/actions/actionDeleteSelected.js +3 -2
  39. package/dist/excalidraw/actions/actionDistribute.d.ts +2 -2
  40. package/dist/excalidraw/actions/actionDistribute.js +1 -1
  41. package/dist/excalidraw/actions/actionDuplicateSelection.d.ts +1 -1
  42. package/dist/excalidraw/actions/actionDuplicateSelection.js +4 -3
  43. package/dist/excalidraw/actions/actionElementLock.d.ts +8 -8
  44. package/dist/excalidraw/actions/actionExport.d.ts +35 -35
  45. package/dist/excalidraw/actions/actionExport.js +4 -4
  46. package/dist/excalidraw/actions/actionFinalize.d.ts +7 -7
  47. package/dist/excalidraw/actions/actionFinalize.js +7 -6
  48. package/dist/excalidraw/actions/actionFlip.d.ts +2 -2
  49. package/dist/excalidraw/actions/actionFlip.js +11 -11
  50. package/dist/excalidraw/actions/actionFrame.d.ts +13 -13
  51. package/dist/excalidraw/actions/actionFrame.js +1 -1
  52. package/dist/excalidraw/actions/actionGroup.d.ts +8 -8
  53. package/dist/excalidraw/actions/actionGroup.js +3 -2
  54. package/dist/excalidraw/actions/actionLinearEditor.d.ts +4 -4
  55. package/dist/excalidraw/actions/actionLinearEditor.js +1 -1
  56. package/dist/excalidraw/{element/Hyperlink.d.ts → actions/actionLink.d.ts} +28 -50
  57. package/dist/excalidraw/actions/actionLink.js +40 -0
  58. package/dist/excalidraw/actions/actionMenu.d.ts +11 -11
  59. package/dist/excalidraw/actions/actionNavigate.d.ts +8 -8
  60. package/dist/excalidraw/actions/actionNavigate.js +1 -1
  61. package/dist/excalidraw/actions/actionProperties.d.ts +64 -64
  62. package/dist/excalidraw/actions/actionProperties.js +32 -27
  63. package/dist/excalidraw/actions/actionSelectAll.d.ts +4 -4
  64. package/dist/excalidraw/actions/actionSelectAll.js +1 -1
  65. package/dist/excalidraw/actions/actionStyles.d.ts +6 -6
  66. package/dist/excalidraw/actions/actionStyles.js +4 -4
  67. package/dist/excalidraw/actions/actionToggleGridMode.d.ts +4 -4
  68. package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +4 -4
  69. package/dist/excalidraw/actions/actionToggleStats.d.ts +4 -4
  70. package/dist/excalidraw/actions/actionToggleViewMode.d.ts +4 -4
  71. package/dist/excalidraw/actions/actionToggleZenMode.d.ts +4 -4
  72. package/dist/excalidraw/actions/index.d.ts +1 -1
  73. package/dist/excalidraw/actions/index.js +1 -1
  74. package/dist/excalidraw/actions/manager.js +2 -1
  75. package/dist/excalidraw/align.d.ts +2 -2
  76. package/dist/excalidraw/align.js +2 -2
  77. package/dist/excalidraw/animated-trail.d.ts +33 -0
  78. package/dist/excalidraw/animated-trail.js +96 -0
  79. package/dist/excalidraw/animation-frame-handler.d.ts +16 -0
  80. package/dist/excalidraw/animation-frame-handler.js +55 -0
  81. package/dist/excalidraw/appState.d.ts +1 -1
  82. package/dist/excalidraw/appState.js +1 -3
  83. package/dist/excalidraw/clipboard.js +5 -5
  84. package/dist/excalidraw/components/Actions.d.ts +3 -3
  85. package/dist/excalidraw/components/Actions.js +18 -7
  86. package/dist/excalidraw/components/App.d.ts +32 -17
  87. package/dist/excalidraw/components/App.js +474 -339
  88. package/dist/excalidraw/components/Button.d.ts +1 -1
  89. package/dist/excalidraw/components/FilledButton.d.ts +2 -2
  90. package/dist/excalidraw/components/FilledButton.js +27 -3
  91. package/dist/excalidraw/components/FollowMode/FollowMode.js +1 -1
  92. package/dist/excalidraw/components/ImageExportDialog.d.ts +2 -1
  93. package/dist/excalidraw/components/ImageExportDialog.js +16 -12
  94. package/dist/excalidraw/components/JSONExportDialog.js +1 -1
  95. package/dist/excalidraw/components/{LaserTool/LaserPointerButton.d.ts → LaserPointerButton.d.ts} +1 -1
  96. package/dist/excalidraw/components/{LaserTool/LaserPointerButton.js → LaserPointerButton.js} +2 -2
  97. package/dist/excalidraw/components/LayerUI.js +3 -3
  98. package/dist/excalidraw/components/MobileMenu.js +1 -1
  99. package/dist/excalidraw/components/ProjectName.d.ts +0 -1
  100. package/dist/excalidraw/components/ProjectName.js +1 -1
  101. package/dist/excalidraw/components/SVGLayer.d.ts +8 -0
  102. package/dist/excalidraw/components/SVGLayer.js +20 -0
  103. package/dist/excalidraw/components/ShareableLinkDialog.js +10 -10
  104. package/dist/excalidraw/components/Stack.d.ts +2 -2
  105. package/dist/excalidraw/components/TTDDialog/common.js +10 -1
  106. package/dist/excalidraw/components/TextField.d.ts +5 -2
  107. package/dist/excalidraw/components/TextField.js +6 -3
  108. package/dist/excalidraw/components/Toast.d.ts +3 -2
  109. package/dist/excalidraw/components/Toast.js +2 -2
  110. package/dist/excalidraw/components/ToolButton.js +2 -1
  111. package/dist/excalidraw/components/canvases/InteractiveCanvas.d.ts +2 -2
  112. package/dist/excalidraw/components/canvases/InteractiveCanvas.js +6 -5
  113. package/dist/excalidraw/components/canvases/StaticCanvas.d.ts +4 -3
  114. package/dist/excalidraw/components/canvases/StaticCanvas.js +7 -5
  115. package/dist/excalidraw/components/dropdownMenu/DropdownMenuContent.js +22 -2
  116. package/dist/excalidraw/components/dropdownMenu/common.d.ts +1 -1
  117. package/dist/excalidraw/components/hyperlink/Hyperlink.d.ts +19 -0
  118. package/dist/excalidraw/{element → components/hyperlink}/Hyperlink.js +40 -115
  119. package/dist/excalidraw/components/hyperlink/helpers.d.ts +7 -0
  120. package/dist/excalidraw/components/hyperlink/helpers.js +49 -0
  121. package/dist/excalidraw/components/icons.d.ts +2 -1
  122. package/dist/excalidraw/components/icons.js +2 -1
  123. package/dist/excalidraw/components/live-collaboration/LiveCollaborationTrigger.js +3 -2
  124. package/dist/excalidraw/components/main-menu/DefaultItems.js +5 -2
  125. package/dist/excalidraw/constants.d.ts +8 -0
  126. package/dist/excalidraw/constants.js +10 -0
  127. package/dist/excalidraw/data/blob.js +13 -14
  128. package/dist/excalidraw/data/filesystem.d.ts +1 -1
  129. package/dist/excalidraw/data/index.d.ts +2 -1
  130. package/dist/excalidraw/data/index.js +20 -16
  131. package/dist/excalidraw/data/json.d.ts +1 -1
  132. package/dist/excalidraw/data/json.js +5 -3
  133. package/dist/excalidraw/data/resave.d.ts +1 -1
  134. package/dist/excalidraw/data/resave.js +2 -2
  135. package/dist/excalidraw/data/restore.js +8 -13
  136. package/dist/excalidraw/data/transform.js +13 -9
  137. package/dist/excalidraw/distribute.d.ts +2 -2
  138. package/dist/excalidraw/distribute.js +2 -2
  139. package/dist/excalidraw/element/ElementCanvasButtons.d.ts +3 -2
  140. package/dist/excalidraw/element/ElementCanvasButtons.js +4 -4
  141. package/dist/excalidraw/element/binding.d.ts +9 -9
  142. package/dist/excalidraw/element/binding.js +61 -59
  143. package/dist/excalidraw/element/bounds.d.ts +5 -5
  144. package/dist/excalidraw/element/bounds.js +29 -32
  145. package/dist/excalidraw/element/collision.d.ts +11 -11
  146. package/dist/excalidraw/element/collision.js +49 -46
  147. package/dist/excalidraw/element/containerCache.d.ts +11 -0
  148. package/dist/excalidraw/element/containerCache.js +14 -0
  149. package/dist/excalidraw/element/dragElements.js +10 -19
  150. package/dist/excalidraw/element/embeddable.d.ts +11 -12
  151. package/dist/excalidraw/element/embeddable.js +17 -27
  152. package/dist/excalidraw/element/image.js +1 -2
  153. package/dist/excalidraw/element/index.d.ts +0 -1
  154. package/dist/excalidraw/element/index.js +0 -1
  155. package/dist/excalidraw/element/linearElementEditor.d.ts +35 -35
  156. package/dist/excalidraw/element/linearElementEditor.js +79 -80
  157. package/dist/excalidraw/element/newElement.d.ts +4 -6
  158. package/dist/excalidraw/element/newElement.js +11 -16
  159. package/dist/excalidraw/element/resizeElements.d.ts +6 -6
  160. package/dist/excalidraw/element/resizeElements.js +40 -46
  161. package/dist/excalidraw/element/resizeTest.d.ts +3 -3
  162. package/dist/excalidraw/element/resizeTest.js +4 -4
  163. package/dist/excalidraw/element/sizeHelpers.d.ts +2 -2
  164. package/dist/excalidraw/element/sizeHelpers.js +2 -2
  165. package/dist/excalidraw/element/textElement.d.ts +18 -20
  166. package/dist/excalidraw/element/textElement.js +80 -111
  167. package/dist/excalidraw/element/textWysiwyg.d.ts +1 -6
  168. package/dist/excalidraw/element/textWysiwyg.js +15 -37
  169. package/dist/excalidraw/element/transformHandles.d.ts +4 -4
  170. package/dist/excalidraw/element/transformHandles.js +6 -6
  171. package/dist/excalidraw/element/typeChecks.js +4 -1
  172. package/dist/excalidraw/element/types.d.ts +24 -11
  173. package/dist/excalidraw/emitter.d.ts +5 -9
  174. package/dist/excalidraw/emitter.js +12 -12
  175. package/dist/excalidraw/frame.d.ts +26 -20
  176. package/dist/excalidraw/frame.js +157 -84
  177. package/dist/excalidraw/groups.d.ts +3 -3
  178. package/dist/excalidraw/groups.js +11 -3
  179. package/dist/excalidraw/history.d.ts +1 -1
  180. package/dist/excalidraw/index.d.ts +7 -3
  181. package/dist/excalidraw/index.js +14 -5
  182. package/dist/excalidraw/laser-trails.d.ts +19 -0
  183. package/dist/excalidraw/laser-trails.js +95 -0
  184. package/dist/excalidraw/locales/en.json +9 -5
  185. package/dist/excalidraw/reactUtils.d.ts +14 -0
  186. package/dist/excalidraw/reactUtils.js +45 -0
  187. package/dist/excalidraw/renderer/helpers.d.ts +13 -0
  188. package/dist/excalidraw/renderer/helpers.js +39 -0
  189. package/dist/excalidraw/renderer/interactiveScene.d.ts +20 -0
  190. package/dist/excalidraw/renderer/{renderScene.js → interactiveScene.js} +199 -474
  191. package/dist/excalidraw/renderer/renderElement.d.ts +6 -6
  192. package/dist/excalidraw/renderer/renderElement.js +54 -366
  193. package/dist/excalidraw/renderer/staticScene.d.ts +11 -0
  194. package/dist/excalidraw/renderer/staticScene.js +205 -0
  195. package/dist/excalidraw/renderer/staticSvgScene.d.ts +5 -0
  196. package/dist/excalidraw/renderer/staticSvgScene.js +385 -0
  197. package/dist/excalidraw/scene/Fonts.js +2 -1
  198. package/dist/excalidraw/scene/Renderer.d.ts +1 -1
  199. package/dist/excalidraw/scene/Renderer.js +32 -20
  200. package/dist/excalidraw/scene/Scene.d.ts +10 -9
  201. package/dist/excalidraw/scene/Scene.js +45 -21
  202. package/dist/excalidraw/scene/Shape.d.ts +3 -1
  203. package/dist/excalidraw/scene/Shape.js +7 -5
  204. package/dist/excalidraw/scene/ShapeCache.d.ts +2 -1
  205. package/dist/excalidraw/scene/ShapeCache.js +1 -0
  206. package/dist/excalidraw/scene/comparisons.js +2 -1
  207. package/dist/excalidraw/scene/export.d.ts +3 -0
  208. package/dist/excalidraw/scene/export.js +20 -40
  209. package/dist/excalidraw/scene/index.d.ts +0 -1
  210. package/dist/excalidraw/scene/index.js +0 -1
  211. package/dist/excalidraw/scene/scrollbars.d.ts +1 -1
  212. package/dist/excalidraw/scene/scrollbars.js +1 -1
  213. package/dist/excalidraw/scene/selection.d.ts +5 -5
  214. package/dist/excalidraw/scene/selection.js +16 -14
  215. package/dist/excalidraw/scene/types.d.ts +11 -5
  216. package/dist/excalidraw/snapping.d.ts +7 -7
  217. package/dist/excalidraw/snapping.js +21 -20
  218. package/dist/excalidraw/types.d.ts +11 -12
  219. package/dist/excalidraw/utility-types.d.ts +5 -0
  220. package/dist/excalidraw/utils.d.ts +25 -16
  221. package/dist/excalidraw/utils.js +52 -45
  222. package/dist/{dev/en-RLIAOBCI.json → prod/en-TDNWCAOT.json} +9 -5
  223. package/dist/prod/index.css +1 -1
  224. package/dist/prod/index.js +45 -45
  225. package/dist/utils/export.d.ts +0 -6
  226. package/dist/utils/export.js +0 -6
  227. package/dist/utils/index.d.ts +3 -0
  228. package/dist/utils/index.js +3 -0
  229. package/dist/utils/withinBounds.js +2 -1
  230. package/package.json +4 -4
  231. package/dist/browser/dev/excalidraw-assets-dev/chunk-2W5GQUR4.js.map +0 -7
  232. package/dist/browser/dev/excalidraw-assets-dev/chunk-SUHLFFEF.js +0 -53449
  233. package/dist/browser/dev/excalidraw-assets-dev/chunk-SUHLFFEF.js.map +0 -7
  234. package/dist/browser/dev/excalidraw-assets-dev/image-NOPDRTTM.css +0 -5797
  235. package/dist/browser/dev/excalidraw-assets-dev/image-NOPDRTTM.css.map +0 -7
  236. package/dist/browser/prod/excalidraw-assets/chunk-HE2P7BQ6.js +0 -257
  237. package/dist/browser/prod/excalidraw-assets/chunk-OWLL6VOG.js +0 -11
  238. package/dist/browser/prod/excalidraw-assets/en-ERQOR3OC.js +0 -1
  239. package/dist/browser/prod/excalidraw-assets/image-DZ6B4AID.js +0 -1
  240. package/dist/browser/prod/excalidraw-assets/image-J2QCCYAR.css +0 -1
  241. package/dist/excalidraw/components/LaserTool/LaserPathManager.d.ts +0 -28
  242. package/dist/excalidraw/components/LaserTool/LaserPathManager.js +0 -225
  243. package/dist/excalidraw/components/LaserTool/LaserTool.d.ts +0 -8
  244. package/dist/excalidraw/components/LaserTool/LaserTool.js +0 -15
  245. package/dist/excalidraw/renderer/renderScene.d.ts +0 -25
  246. package/dist/excalidraw/vite.config.d.mts +0 -2
  247. package/dist/excalidraw/vite.config.mjs +0 -13
  248. /package/dist/browser/dev/excalidraw-assets-dev/{en-OC6JWP3X.js.map → en-IOBA4CS2.js.map} +0 -0
  249. /package/dist/browser/dev/excalidraw-assets-dev/{image-HYNUJ3XL.js.map → image-VKDAL6BQ.js.map} +0 -0
@@ -1,15 +1,15 @@
1
1
  import { copyBlobToClipboardAsPng, copyTextToSystemClipboard, } from "../clipboard";
2
- import { DEFAULT_EXPORT_PADDING, isFirefox, MIME_TYPES } from "../constants";
2
+ import { DEFAULT_EXPORT_PADDING, DEFAULT_FILENAME, isFirefox, MIME_TYPES, } from "../constants";
3
3
  import { getNonDeletedElements } from "../element";
4
4
  import { isFrameLikeElement } from "../element/typeChecks";
5
5
  import { t } from "../i18n";
6
- import { elementsOverlappingBBox } from "../../utils/export";
7
6
  import { isSomeElementSelected, getSelectedElements } from "../scene";
8
7
  import { exportToCanvas, exportToSvg } from "../scene/export";
9
8
  import { cloneJSON } from "../utils";
10
9
  import { canvasToBlob } from "./blob";
11
10
  import { fileSave } from "./filesystem";
12
11
  import { serializeAsJSON } from "./json";
12
+ import { getElementsOverlappingFrame } from "../frame";
13
13
  export { loadFromBlob } from "./blob";
14
14
  export { loadFromJSON, saveAsJSON } from "./json";
15
15
  export const prepareElementsForExport = (elements, { selectedElementIds }, exportSelectionOnly) => {
@@ -26,11 +26,7 @@ export const prepareElementsForExport = (elements, { selectedElementIds }, expor
26
26
  if (exportedElements.length === 1 &&
27
27
  isFrameLikeElement(exportedElements[0])) {
28
28
  exportingFrame = exportedElements[0];
29
- exportedElements = elementsOverlappingBBox({
30
- elements,
31
- bounds: exportingFrame,
32
- type: "overlap",
33
- });
29
+ exportedElements = getElementsOverlappingFrame(elements, exportingFrame);
34
30
  }
35
31
  else if (exportedElements.length > 1) {
36
32
  exportedElements = getSelectedElements(elements, { selectedElementIds }, {
@@ -44,12 +40,12 @@ export const prepareElementsForExport = (elements, { selectedElementIds }, expor
44
40
  exportedElements: cloneJSON(exportedElements),
45
41
  };
46
42
  };
47
- export const exportCanvas = async (type, elements, appState, files, { exportBackground, exportPadding = DEFAULT_EXPORT_PADDING, viewBackgroundColor, name, fileHandle = null, exportingFrame = null, }) => {
43
+ export const exportCanvas = async (type, elements, appState, files, { exportBackground, exportPadding = DEFAULT_EXPORT_PADDING, viewBackgroundColor, name = appState.name || DEFAULT_FILENAME, fileHandle = null, exportingFrame = null, }) => {
48
44
  if (elements.length === 0) {
49
45
  throw new Error(t("alerts.cannotExportEmptyCanvas"));
50
46
  }
51
47
  if (type === "svg" || type === "clipboard-svg") {
52
- const tempSvg = await exportToSvg(elements, {
48
+ const svgPromise = exportToSvg(elements, {
53
49
  exportBackground,
54
50
  exportWithDarkMode: appState.exportWithDarkMode,
55
51
  viewBackgroundColor,
@@ -58,7 +54,9 @@ export const exportCanvas = async (type, elements, appState, files, { exportBack
58
54
  exportEmbedScene: appState.exportEmbedScene && type === "svg",
59
55
  }, files, { exportingFrame });
60
56
  if (type === "svg") {
61
- return await fileSave(new Blob([tempSvg.outerHTML], { type: MIME_TYPES.svg }), {
57
+ return fileSave(svgPromise.then((svg) => {
58
+ return new Blob([svg.outerHTML], { type: MIME_TYPES.svg });
59
+ }), {
62
60
  description: "Export to SVG",
63
61
  name,
64
62
  extension: appState.exportEmbedScene ? "excalidraw.svg" : "svg",
@@ -66,7 +64,13 @@ export const exportCanvas = async (type, elements, appState, files, { exportBack
66
64
  });
67
65
  }
68
66
  else if (type === "clipboard-svg") {
69
- await copyTextToSystemClipboard(tempSvg.outerHTML);
67
+ const svg = await svgPromise.then((svg) => svg.outerHTML);
68
+ try {
69
+ await copyTextToSystemClipboard(svg);
70
+ }
71
+ catch (e) {
72
+ throw new Error(t("errors.copyToSystemClipboardFailed"));
73
+ }
70
74
  return;
71
75
  }
72
76
  }
@@ -77,14 +81,14 @@ export const exportCanvas = async (type, elements, appState, files, { exportBack
77
81
  exportingFrame,
78
82
  });
79
83
  if (type === "png") {
80
- let blob = await canvasToBlob(tempCanvas);
84
+ let blob = canvasToBlob(tempCanvas);
81
85
  if (appState.exportEmbedScene) {
82
- blob = await (await import("./image")).encodePngMetadata({
86
+ blob = blob.then((blob) => import("./image").then(({ encodePngMetadata }) => encodePngMetadata({
83
87
  blob,
84
88
  metadata: serializeAsJSON(elements, appState, files, "local"),
85
- });
89
+ })));
86
90
  }
87
- return await fileSave(blob, {
91
+ return fileSave(blob, {
88
92
  description: "Export to PNG",
89
93
  name,
90
94
  // FIXME reintroduce `excalidraw.png` when most people upgrade away
@@ -101,7 +105,7 @@ export const exportCanvas = async (type, elements, appState, files, { exportBack
101
105
  catch (error) {
102
106
  console.warn(error);
103
107
  if (error.name === "CANVAS_POSSIBLY_TOO_BIG") {
104
- throw error;
108
+ throw new Error(t("canvasError.canvasTooBig"));
105
109
  }
106
110
  // TypeError *probably* suggests ClipboardItem not defined, which
107
111
  // people on Firefox can enable through a flag, so let's tell them.
@@ -2,7 +2,7 @@ import { ExcalidrawElement } from "../element/types";
2
2
  import { AppState, BinaryFiles, LibraryItems } from "../types";
3
3
  import { ImportedDataState, ImportedLibraryData } from "./types";
4
4
  export declare const serializeAsJSON: (elements: readonly ExcalidrawElement[], appState: Partial<AppState>, files: BinaryFiles, type: "local" | "database") => string;
5
- export declare const saveAsJSON: (elements: readonly ExcalidrawElement[], appState: AppState, files: BinaryFiles) => Promise<{
5
+ export declare const saveAsJSON: (elements: readonly ExcalidrawElement[], appState: AppState, files: BinaryFiles, name?: string) => Promise<{
6
6
  fileHandle: import("browser-fs-access").FileSystemHandle | null;
7
7
  }>;
8
8
  export declare const loadFromJSON: (localAppState: AppState, localElements: readonly ExcalidrawElement[] | null) => Promise<import("./restore").RestoredDataState>;
@@ -1,6 +1,6 @@
1
1
  import { fileOpen, fileSave } from "./filesystem";
2
2
  import { cleanAppStateForExport, clearAppStateForDatabase } from "../appState";
3
- import { EXPORT_DATA_TYPES, EXPORT_SOURCE, MIME_TYPES, VERSIONS, } from "../constants";
3
+ import { DEFAULT_FILENAME, EXPORT_DATA_TYPES, EXPORT_SOURCE, MIME_TYPES, VERSIONS, } from "../constants";
4
4
  import { clearElementsForDatabase, clearElementsForExport } from "../element";
5
5
  import { isImageFileHandle, loadFromBlob, normalizeFile } from "./blob";
6
6
  /**
@@ -36,13 +36,15 @@ export const serializeAsJSON = (elements, appState, files, type) => {
36
36
  };
37
37
  return JSON.stringify(data, null, 2);
38
38
  };
39
- export const saveAsJSON = async (elements, appState, files) => {
39
+ export const saveAsJSON = async (elements, appState, files,
40
+ /** filename */
41
+ name = appState.name || DEFAULT_FILENAME) => {
40
42
  const serialized = serializeAsJSON(elements, appState, files, "local");
41
43
  const blob = new Blob([serialized], {
42
44
  type: MIME_TYPES.excalidraw,
43
45
  });
44
46
  const fileHandle = await fileSave(blob, {
45
- name: appState.name,
47
+ name,
46
48
  extension: "excalidraw",
47
49
  description: "Excalidraw file",
48
50
  fileHandle: isImageFileHandle(appState.fileHandle)
@@ -1,5 +1,5 @@
1
1
  import { ExcalidrawElement } from "../element/types";
2
2
  import { AppState, BinaryFiles } from "../types";
3
- export declare const resaveAsImageWithScene: (elements: readonly ExcalidrawElement[], appState: AppState, files: BinaryFiles) => Promise<{
3
+ export declare const resaveAsImageWithScene: (elements: readonly ExcalidrawElement[], appState: AppState, files: BinaryFiles, name: string) => Promise<{
4
4
  fileHandle: import("browser-fs-access").FileSystemHandle;
5
5
  }>;
@@ -1,7 +1,7 @@
1
1
  import { exportCanvas, prepareElementsForExport } from ".";
2
2
  import { getFileHandleType, isImageFileHandleType } from "./blob";
3
- export const resaveAsImageWithScene = async (elements, appState, files) => {
4
- const { exportBackground, viewBackgroundColor, name, fileHandle } = appState;
3
+ export const resaveAsImageWithScene = async (elements, appState, files, name) => {
4
+ const { exportBackground, viewBackgroundColor, fileHandle } = appState;
5
5
  const fileHandleType = getFileHandleType(fileHandle);
6
6
  if (!fileHandle || !isImageFileHandleType(fileHandleType)) {
7
7
  throw new Error("fileHandle should exist and should be of type svg or png when resaving");
@@ -5,9 +5,9 @@ import { DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, DEFAULT_VERTICAL_ALIGN, PRECED
5
5
  import { getDefaultAppState } from "../appState";
6
6
  import { LinearElementEditor } from "../element/linearElementEditor";
7
7
  import { bumpVersion } from "../element/mutateElement";
8
- import { getFontString, getUpdatedTimestamp, updateActiveTool } from "../utils";
8
+ import { getUpdatedTimestamp, updateActiveTool } from "../utils";
9
9
  import { arrayToMap } from "../utils";
10
- import { detectLineHeight, getDefaultLineHeight, measureBaseline, } from "../element/textElement";
10
+ import { detectLineHeight, getContainerElement, getDefaultLineHeight, } from "../element/textElement";
11
11
  import { normalizeLink } from "./url";
12
12
  export const AllowedExcalidrawActiveTools = {
13
13
  selection: true,
@@ -94,7 +94,7 @@ const restoreElementWithProperties = (element, extra) => {
94
94
  ...extra,
95
95
  };
96
96
  };
97
- const restoreElement = (element, refreshDimensions = false) => {
97
+ const restoreElement = (element) => {
98
98
  switch (element.type) {
99
99
  case "text":
100
100
  let fontSize = element.fontSize;
@@ -117,7 +117,6 @@ const restoreElement = (element, refreshDimensions = false) => {
117
117
  : // no element height likely means programmatic use, so default
118
118
  // to a fixed line height
119
119
  getDefaultLineHeight(element.fontFamily));
120
- const baseline = measureBaseline(element.text, getFontString(element), lineHeight);
121
120
  element = restoreElementWithProperties(element, {
122
121
  fontSize,
123
122
  fontFamily,
@@ -127,7 +126,6 @@ const restoreElement = (element, refreshDimensions = false) => {
127
126
  containerId: element.containerId ?? null,
128
127
  originalText: element.originalText || text,
129
128
  lineHeight,
130
- baseline,
131
129
  });
132
130
  // if empty text, mark as deleted. We keep in array
133
131
  // for data integrity purposes (collab etc.)
@@ -135,9 +133,6 @@ const restoreElement = (element, refreshDimensions = false) => {
135
133
  element = { ...element, originalText: text, isDeleted: true };
136
134
  element = bumpVersion(element);
137
135
  }
138
- if (refreshDimensions) {
139
- element = { ...element, ...refreshTextDimensions(element) };
140
- }
141
136
  return element;
142
137
  case "freedraw": {
143
138
  return restoreElementWithProperties(element, {
@@ -190,11 +185,8 @@ const restoreElement = (element, refreshDimensions = false) => {
190
185
  case "rectangle":
191
186
  case "diamond":
192
187
  case "iframe":
193
- return restoreElementWithProperties(element, {});
194
188
  case "embeddable":
195
- return restoreElementWithProperties(element, {
196
- validated: null,
197
- });
189
+ return restoreElementWithProperties(element, {});
198
190
  case "magicframe":
199
191
  case "frame":
200
192
  return restoreElementWithProperties(element, {
@@ -287,7 +279,7 @@ localElements, opts) => {
287
279
  // filtering out selection, which is legacy, no longer kept in elements,
288
280
  // and causing issues if retained
289
281
  if (element.type !== "selection" && !isInvisiblySmallElement(element)) {
290
- let migratedElement = restoreElement(element, opts?.refreshDimensions);
282
+ let migratedElement = restoreElement(element);
291
283
  if (migratedElement) {
292
284
  const localElement = localElementsMap?.get(element.id);
293
285
  if (localElement && localElement.version > migratedElement.version) {
@@ -317,6 +309,9 @@ localElements, opts) => {
317
309
  else if (element.boundElements) {
318
310
  repairContainerElement(element, restoredElementsMap);
319
311
  }
312
+ if (opts.refreshDimensions && isTextElement(element)) {
313
+ Object.assign(element, refreshTextDimensions(element, getContainerElement(element, restoredElementsMap), restoredElementsMap));
314
+ }
320
315
  }
321
316
  return restoredElements;
322
317
  };
@@ -3,7 +3,7 @@ import { getCommonBounds, newElement, newLinearElement, redrawTextBoundingBox, }
3
3
  import { bindLinearElement } from "../element/binding";
4
4
  import { newFrameElement, newImageElement, newMagicFrameElement, newTextElement, } from "../element/newElement";
5
5
  import { getDefaultLineHeight, measureText, normalizeText, } from "../element/textElement";
6
- import { assertNever, cloneJSON, getFontString } from "../utils";
6
+ import { assertNever, cloneJSON, getFontString, toBrandedType } from "../utils";
7
7
  import { getSizeFromPoints } from "../points";
8
8
  import { randomId } from "../random";
9
9
  const DEFAULT_LINEAR_ELEMENT_PROPS = {
@@ -11,7 +11,7 @@ const DEFAULT_LINEAR_ELEMENT_PROPS = {
11
11
  height: 0,
12
12
  };
13
13
  const DEFAULT_DIMENSION = 100;
14
- const bindTextToContainer = (container, textProps) => {
14
+ const bindTextToContainer = (container, textProps, elementsMap) => {
15
15
  const textElement = newTextElement({
16
16
  x: 0,
17
17
  y: 0,
@@ -27,10 +27,10 @@ const bindTextToContainer = (container, textProps) => {
27
27
  id: textElement.id,
28
28
  }),
29
29
  });
30
- redrawTextBoundingBox(textElement, container);
30
+ redrawTextBoundingBox(textElement, container, elementsMap);
31
31
  return [container, textElement];
32
32
  };
33
- const bindLinearElementToElement = (linearElement, start, end, elementStore) => {
33
+ const bindLinearElementToElement = (linearElement, start, end, elementStore, elementsMap) => {
34
34
  let startBoundElement;
35
35
  let endBoundElement;
36
36
  Object.assign(linearElement, {
@@ -97,7 +97,7 @@ const bindLinearElementToElement = (linearElement, start, end, elementStore) =>
97
97
  }
98
98
  }
99
99
  }
100
- bindLinearElement(linearElement, startBoundElement, "start");
100
+ bindLinearElement(linearElement, startBoundElement, "start", elementsMap);
101
101
  }
102
102
  }
103
103
  if (end) {
@@ -159,7 +159,7 @@ const bindLinearElementToElement = (linearElement, start, end, elementStore) =>
159
159
  }
160
160
  }
161
161
  }
162
- bindLinearElement(linearElement, endBoundElement, "end");
162
+ bindLinearElement(linearElement, endBoundElement, "end", elementsMap);
163
163
  }
164
164
  }
165
165
  // Update start/end points by 0.5 so bindings don't overlap with start/end bound element coordinates.
@@ -208,6 +208,9 @@ class ElementStore {
208
208
  getElements = () => {
209
209
  return Array.from(this.excalidrawElements.values());
210
210
  };
211
+ getElementsMap = () => {
212
+ return toBrandedType(this.excalidrawElements);
213
+ };
211
214
  getElement = (id) => {
212
215
  return this.excalidrawElements.get(id);
213
216
  };
@@ -337,6 +340,7 @@ export const convertToExcalidrawElements = (elementsSkeleton, opts) => {
337
340
  }
338
341
  }
339
342
  }
343
+ const elementsMap = elementStore.getElementsMap();
340
344
  // Add labels and arrow bindings
341
345
  for (const [id, element] of elementsWithIds) {
342
346
  const excalidrawElement = elementStore.getElement(id);
@@ -346,7 +350,7 @@ export const convertToExcalidrawElements = (elementsSkeleton, opts) => {
346
350
  case "diamond":
347
351
  case "arrow": {
348
352
  if (element.label?.text) {
349
- let [container, text] = bindTextToContainer(excalidrawElement, element?.label);
353
+ let [container, text] = bindTextToContainer(excalidrawElement, element?.label, elementsMap);
350
354
  elementStore.add(container);
351
355
  elementStore.add(text);
352
356
  if (container.type === "arrow") {
@@ -364,7 +368,7 @@ export const convertToExcalidrawElements = (elementsSkeleton, opts) => {
364
368
  Object.assign(originalEnd, { id: newEndId });
365
369
  }
366
370
  }
367
- const { linearElement, startBoundElement, endBoundElement } = bindLinearElementToElement(container, originalStart, originalEnd, elementStore);
371
+ const { linearElement, startBoundElement, endBoundElement } = bindLinearElementToElement(container, originalStart, originalEnd, elementStore, elementsMap);
368
372
  container = linearElement;
369
373
  elementStore.add(linearElement);
370
374
  elementStore.add(startBoundElement);
@@ -383,7 +387,7 @@ export const convertToExcalidrawElements = (elementsSkeleton, opts) => {
383
387
  const newEndId = oldToNewElementIdMap.get(end.id);
384
388
  Object.assign(end, { id: newEndId });
385
389
  }
386
- const { linearElement, startBoundElement, endBoundElement } = bindLinearElementToElement(excalidrawElement, start, end, elementStore);
390
+ const { linearElement, startBoundElement, endBoundElement } = bindLinearElementToElement(excalidrawElement, start, end, elementStore, elementsMap);
387
391
  elementStore.add(linearElement);
388
392
  elementStore.add(startBoundElement);
389
393
  elementStore.add(endBoundElement);
@@ -1,6 +1,6 @@
1
- import { ExcalidrawElement } from "./element/types";
1
+ import type { ElementsMap, ExcalidrawElement } from "./element/types";
2
2
  export interface Distribution {
3
3
  space: "between";
4
4
  axis: "x" | "y";
5
5
  }
6
- export declare const distributeElements: (selectedElements: ExcalidrawElement[], distribution: Distribution) => ExcalidrawElement[];
6
+ export declare const distributeElements: (selectedElements: ExcalidrawElement[], elementsMap: ElementsMap, distribution: Distribution) => ExcalidrawElement[];
@@ -1,12 +1,12 @@
1
1
  import { newElementWith } from "./element/mutateElement";
2
2
  import { getMaximumGroups } from "./groups";
3
3
  import { getCommonBoundingBox } from "./element/bounds";
4
- export const distributeElements = (selectedElements, distribution) => {
4
+ export const distributeElements = (selectedElements, elementsMap, distribution) => {
5
5
  const [start, mid, end, extent] = distribution.axis === "x"
6
6
  ? ["minX", "midX", "maxX", "width"]
7
7
  : ["minY", "midY", "maxY", "height"];
8
8
  const bounds = getCommonBoundingBox(selectedElements);
9
- const groups = getMaximumGroups(selectedElements)
9
+ const groups = getMaximumGroups(selectedElements, elementsMap)
10
10
  .map((group) => [group, getCommonBoundingBox(group)])
11
11
  .sort((a, b) => a[1][mid] - b[1][mid]);
12
12
  let span = 0;
@@ -1,7 +1,8 @@
1
1
  /// <reference types="react" />
2
- import { NonDeletedExcalidrawElement } from "./types";
2
+ import { ElementsMap, NonDeletedExcalidrawElement } from "./types";
3
3
  import "./ElementCanvasButtons.scss";
4
- export declare const ElementCanvasButtons: ({ children, element, }: {
4
+ export declare const ElementCanvasButtons: ({ children, element, elementsMap, }: {
5
5
  children: React.ReactNode;
6
6
  element: NonDeletedExcalidrawElement;
7
+ elementsMap: ElementsMap;
7
8
  }) => JSX.Element | null;
@@ -4,14 +4,14 @@ import { getElementAbsoluteCoords } from ".";
4
4
  import { useExcalidrawAppState } from "../components/App";
5
5
  import "./ElementCanvasButtons.scss";
6
6
  const CONTAINER_PADDING = 5;
7
- const getContainerCoords = (element, appState) => {
8
- const [x1, y1] = getElementAbsoluteCoords(element);
7
+ const getContainerCoords = (element, appState, elementsMap) => {
8
+ const [x1, y1] = getElementAbsoluteCoords(element, elementsMap);
9
9
  const { x: viewportX, y: viewportY } = sceneCoordsToViewportCoords({ sceneX: x1 + element.width, sceneY: y1 }, appState);
10
10
  const x = viewportX - appState.offsetLeft + 10;
11
11
  const y = viewportY - appState.offsetTop;
12
12
  return { x, y };
13
13
  };
14
- export const ElementCanvasButtons = ({ children, element, }) => {
14
+ export const ElementCanvasButtons = ({ children, element, elementsMap, }) => {
15
15
  const appState = useExcalidrawAppState();
16
16
  if (appState.contextMenu ||
17
17
  appState.draggingElement ||
@@ -21,7 +21,7 @@ export const ElementCanvasButtons = ({ children, element, }) => {
21
21
  appState.viewModeEnabled) {
22
22
  return null;
23
23
  }
24
- const { x, y } = getContainerCoords(element, appState);
24
+ const { x, y } = getContainerCoords(element, appState, elementsMap);
25
25
  return (_jsx("div", { className: "excalidraw-canvas-buttons", style: {
26
26
  top: `${y}px`,
27
27
  left: `${x}px`,
@@ -1,4 +1,4 @@
1
- import { ExcalidrawLinearElement, ExcalidrawBindableElement, NonDeleted, NonDeletedExcalidrawElement, ExcalidrawElement } from "./types";
1
+ import { ExcalidrawLinearElement, ExcalidrawBindableElement, NonDeleted, NonDeletedExcalidrawElement, ExcalidrawElement, ElementsMap, NonDeletedSceneElementsMap } from "./types";
2
2
  import { AppState } from "../types";
3
3
  import Scene from "../scene/Scene";
4
4
  export type SuggestedBinding = NonDeleted<ExcalidrawBindableElement> | SuggestedPointBinding;
@@ -9,26 +9,26 @@ export type SuggestedPointBinding = [
9
9
  ];
10
10
  export declare const shouldEnableBindingForPointerEvent: (event: React.PointerEvent<HTMLElement>) => boolean;
11
11
  export declare const isBindingEnabled: (appState: AppState) => boolean;
12
- export declare const bindOrUnbindLinearElement: (linearElement: NonDeleted<ExcalidrawLinearElement>, startBindingElement: ExcalidrawBindableElement | null | "keep", endBindingElement: ExcalidrawBindableElement | null | "keep") => void;
13
- export declare const bindOrUnbindSelectedElements: (elements: NonDeleted<ExcalidrawElement>[]) => void;
12
+ export declare const bindOrUnbindLinearElement: (linearElement: NonDeleted<ExcalidrawLinearElement>, startBindingElement: ExcalidrawBindableElement | null | "keep", endBindingElement: ExcalidrawBindableElement | null | "keep", elementsMap: NonDeletedSceneElementsMap) => void;
13
+ export declare const bindOrUnbindSelectedElements: (selectedElements: NonDeleted<ExcalidrawElement>[], elements: readonly ExcalidrawElement[], elementsMap: NonDeletedSceneElementsMap) => void;
14
14
  export declare const maybeBindLinearElement: (linearElement: NonDeleted<ExcalidrawLinearElement>, appState: AppState, scene: Scene, pointerCoords: {
15
15
  x: number;
16
16
  y: number;
17
- }) => void;
18
- export declare const bindLinearElement: (linearElement: NonDeleted<ExcalidrawLinearElement>, hoveredElement: ExcalidrawBindableElement, startOrEnd: "start" | "end") => void;
17
+ }, elementsMap: NonDeletedSceneElementsMap) => void;
18
+ export declare const bindLinearElement: (linearElement: NonDeleted<ExcalidrawLinearElement>, hoveredElement: ExcalidrawBindableElement, startOrEnd: "start" | "end", elementsMap: NonDeletedSceneElementsMap) => void;
19
19
  export declare const isLinearElementSimpleAndAlreadyBound: (linearElement: NonDeleted<ExcalidrawLinearElement>, alreadyBoundToId: ExcalidrawBindableElement["id"] | undefined, bindableElement: ExcalidrawBindableElement) => boolean;
20
- export declare const unbindLinearElements: (elements: NonDeleted<ExcalidrawElement>[]) => void;
20
+ export declare const unbindLinearElements: (elements: NonDeleted<ExcalidrawElement>[], elementsMap: NonDeletedSceneElementsMap) => void;
21
21
  export declare const getHoveredElementForBinding: (pointerCoords: {
22
22
  x: number;
23
23
  y: number;
24
- }, scene: Scene) => NonDeleted<ExcalidrawBindableElement> | null;
25
- export declare const updateBoundElements: (changedElement: NonDeletedExcalidrawElement, options?: {
24
+ }, elements: readonly NonDeletedExcalidrawElement[], elementsMap: NonDeletedSceneElementsMap) => NonDeleted<ExcalidrawBindableElement> | null;
25
+ export declare const updateBoundElements: (changedElement: NonDeletedExcalidrawElement, elementsMap: ElementsMap, options?: {
26
26
  simultaneouslyUpdated?: readonly ExcalidrawElement[];
27
27
  newSize?: {
28
28
  width: number;
29
29
  height: number;
30
30
  };
31
31
  }) => void;
32
- export declare const getEligibleElementsForBinding: (elements: NonDeleted<ExcalidrawElement>[]) => SuggestedBinding[];
32
+ export declare const getEligibleElementsForBinding: (selectedElements: NonDeleted<ExcalidrawElement>[], elements: readonly ExcalidrawElement[], elementsMap: NonDeletedSceneElementsMap) => SuggestedBinding[];
33
33
  export declare const fixBindingsAfterDuplication: (sceneElements: readonly ExcalidrawElement[], oldElements: readonly ExcalidrawElement[], oldIdToDuplicatedId: Map<ExcalidrawElement["id"], ExcalidrawElement["id"]>, duplicatesServeAsOld?: "duplicatesServeAsOld" | undefined) => void;
34
34
  export declare const fixBindingsAfterDeletion: (sceneElements: readonly ExcalidrawElement[], deletedElements: readonly ExcalidrawElement[]) => void;