@excalidraw/excalidraw 0.17.1-7500-ac247a0 → 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 (251) 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-5TVMINCA.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 +34708 -37
  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 +39078 -40080
  28. package/dist/dev/index.js.map +4 -4
  29. package/dist/excalidraw/actions/actionAddToLibrary.d.ts +15 -15
  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 +10 -10
  33. package/dist/excalidraw/actions/actionBoundText.js +8 -8
  34. package/dist/excalidraw/actions/actionCanvas.d.ts +58 -58
  35. package/dist/excalidraw/actions/actionClipboard.d.ts +34 -34
  36. package/dist/excalidraw/actions/actionClipboard.js +9 -2
  37. package/dist/excalidraw/actions/actionDeleteSelected.d.ts +15 -15
  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 +10 -10
  44. package/dist/excalidraw/actions/actionExport.d.ts +43 -43
  45. package/dist/excalidraw/actions/actionExport.js +4 -4
  46. package/dist/excalidraw/actions/actionFinalize.d.ts +9 -9
  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 +16 -16
  51. package/dist/excalidraw/actions/actionFrame.js +1 -1
  52. package/dist/excalidraw/actions/actionGroup.d.ts +10 -10
  53. package/dist/excalidraw/actions/actionGroup.js +3 -2
  54. package/dist/excalidraw/actions/actionLinearEditor.d.ts +5 -5
  55. package/dist/excalidraw/actions/actionLinearEditor.js +1 -1
  56. package/dist/excalidraw/{element/Hyperlink.d.ts → actions/actionLink.d.ts} +29 -51
  57. package/dist/excalidraw/actions/actionLink.js +40 -0
  58. package/dist/excalidraw/actions/actionMenu.d.ts +13 -13
  59. package/dist/excalidraw/actions/actionNavigate.d.ts +10 -10
  60. package/dist/excalidraw/actions/actionNavigate.js +1 -1
  61. package/dist/excalidraw/actions/actionProperties.d.ts +77 -77
  62. package/dist/excalidraw/actions/actionProperties.js +32 -27
  63. package/dist/excalidraw/actions/actionSelectAll.d.ts +5 -5
  64. package/dist/excalidraw/actions/actionSelectAll.js +1 -1
  65. package/dist/excalidraw/actions/actionStyles.d.ts +7 -7
  66. package/dist/excalidraw/actions/actionStyles.js +4 -4
  67. package/dist/excalidraw/actions/actionToggleGridMode.d.ts +5 -5
  68. package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +5 -5
  69. package/dist/excalidraw/actions/actionToggleStats.d.ts +5 -5
  70. package/dist/excalidraw/actions/actionToggleViewMode.d.ts +5 -5
  71. package/dist/excalidraw/actions/actionToggleZenMode.d.ts +5 -5
  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 +23 -16
  87. package/dist/excalidraw/components/App.js +387 -272
  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 +17 -13
  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/PublishLibrary.js +1 -1
  102. package/dist/excalidraw/components/SVGLayer.d.ts +8 -0
  103. package/dist/excalidraw/components/SVGLayer.js +20 -0
  104. package/dist/excalidraw/components/ShareableLinkDialog.js +10 -10
  105. package/dist/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
  106. package/dist/excalidraw/components/Stack.d.ts +2 -2
  107. package/dist/excalidraw/components/TTDDialog/common.js +10 -1
  108. package/dist/excalidraw/components/TextField.d.ts +5 -2
  109. package/dist/excalidraw/components/TextField.js +6 -3
  110. package/dist/excalidraw/components/Toast.d.ts +3 -2
  111. package/dist/excalidraw/components/Toast.js +2 -2
  112. package/dist/excalidraw/components/ToolButton.js +2 -1
  113. package/dist/excalidraw/components/canvases/InteractiveCanvas.d.ts +2 -2
  114. package/dist/excalidraw/components/canvases/InteractiveCanvas.js +6 -5
  115. package/dist/excalidraw/components/canvases/StaticCanvas.d.ts +4 -3
  116. package/dist/excalidraw/components/canvases/StaticCanvas.js +7 -5
  117. package/dist/excalidraw/components/dropdownMenu/DropdownMenuContent.js +22 -2
  118. package/dist/excalidraw/components/hyperlink/Hyperlink.d.ts +19 -0
  119. package/dist/excalidraw/{element → components/hyperlink}/Hyperlink.js +40 -115
  120. package/dist/excalidraw/components/hyperlink/helpers.d.ts +7 -0
  121. package/dist/excalidraw/components/hyperlink/helpers.js +49 -0
  122. package/dist/excalidraw/components/icons.d.ts +2 -1
  123. package/dist/excalidraw/components/icons.js +2 -1
  124. package/dist/excalidraw/components/live-collaboration/LiveCollaborationTrigger.js +3 -2
  125. package/dist/excalidraw/components/main-menu/DefaultItems.js +5 -2
  126. package/dist/excalidraw/constants.d.ts +6 -0
  127. package/dist/excalidraw/constants.js +6 -0
  128. package/dist/excalidraw/data/blob.js +13 -14
  129. package/dist/excalidraw/data/filesystem.d.ts +1 -1
  130. package/dist/excalidraw/data/index.d.ts +2 -1
  131. package/dist/excalidraw/data/index.js +20 -16
  132. package/dist/excalidraw/data/json.d.ts +1 -1
  133. package/dist/excalidraw/data/json.js +5 -3
  134. package/dist/excalidraw/data/resave.d.ts +1 -1
  135. package/dist/excalidraw/data/resave.js +2 -2
  136. package/dist/excalidraw/data/restore.js +8 -13
  137. package/dist/excalidraw/data/transform.js +13 -9
  138. package/dist/excalidraw/distribute.d.ts +2 -2
  139. package/dist/excalidraw/distribute.js +2 -2
  140. package/dist/excalidraw/element/ElementCanvasButtons.d.ts +3 -2
  141. package/dist/excalidraw/element/ElementCanvasButtons.js +4 -4
  142. package/dist/excalidraw/element/binding.d.ts +9 -9
  143. package/dist/excalidraw/element/binding.js +61 -59
  144. package/dist/excalidraw/element/bounds.d.ts +5 -5
  145. package/dist/excalidraw/element/bounds.js +29 -32
  146. package/dist/excalidraw/element/collision.d.ts +11 -11
  147. package/dist/excalidraw/element/collision.js +49 -46
  148. package/dist/excalidraw/element/containerCache.d.ts +11 -0
  149. package/dist/excalidraw/element/containerCache.js +14 -0
  150. package/dist/excalidraw/element/dragElements.js +10 -19
  151. package/dist/excalidraw/element/embeddable.d.ts +12 -13
  152. package/dist/excalidraw/element/embeddable.js +17 -27
  153. package/dist/excalidraw/element/image.js +1 -2
  154. package/dist/excalidraw/element/index.d.ts +0 -1
  155. package/dist/excalidraw/element/index.js +0 -1
  156. package/dist/excalidraw/element/linearElementEditor.d.ts +36 -36
  157. package/dist/excalidraw/element/linearElementEditor.js +79 -80
  158. package/dist/excalidraw/element/newElement.d.ts +4 -6
  159. package/dist/excalidraw/element/newElement.js +11 -16
  160. package/dist/excalidraw/element/resizeElements.d.ts +6 -6
  161. package/dist/excalidraw/element/resizeElements.js +40 -46
  162. package/dist/excalidraw/element/resizeTest.d.ts +3 -3
  163. package/dist/excalidraw/element/resizeTest.js +4 -4
  164. package/dist/excalidraw/element/sizeHelpers.d.ts +2 -2
  165. package/dist/excalidraw/element/sizeHelpers.js +2 -2
  166. package/dist/excalidraw/element/textElement.d.ts +18 -20
  167. package/dist/excalidraw/element/textElement.js +80 -111
  168. package/dist/excalidraw/element/textWysiwyg.d.ts +1 -6
  169. package/dist/excalidraw/element/textWysiwyg.js +15 -37
  170. package/dist/excalidraw/element/transformHandles.d.ts +4 -4
  171. package/dist/excalidraw/element/transformHandles.js +6 -6
  172. package/dist/excalidraw/element/typeChecks.js +4 -1
  173. package/dist/excalidraw/element/types.d.ts +24 -11
  174. package/dist/excalidraw/frame.d.ts +26 -20
  175. package/dist/excalidraw/frame.js +157 -84
  176. package/dist/excalidraw/groups.d.ts +3 -3
  177. package/dist/excalidraw/groups.js +11 -3
  178. package/dist/excalidraw/history.d.ts +1 -1
  179. package/dist/excalidraw/hooks/useLibraryItemSvg.js +1 -1
  180. package/dist/excalidraw/index.d.ts +8 -9
  181. package/dist/excalidraw/index.js +15 -11
  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 +10 -11
  219. package/dist/excalidraw/utility-types.d.ts +5 -0
  220. package/dist/excalidraw/utils.d.ts +18 -15
  221. package/dist/excalidraw/utils.js +37 -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 +42 -42
  225. package/dist/utils/bbox.d.ts +2 -2
  226. package/dist/utils/export.d.ts +3 -3
  227. package/dist/utils/export.js +3 -13
  228. package/dist/utils/index.d.ts +2 -2
  229. package/dist/utils/index.js +2 -2
  230. package/dist/utils/withinBounds.d.ts +1 -1
  231. package/dist/utils/withinBounds.js +5 -2
  232. package/package.json +4 -4
  233. package/dist/browser/dev/excalidraw-assets-dev/chunk-2W5GQUR4.js.map +0 -7
  234. package/dist/browser/dev/excalidraw-assets-dev/chunk-KGZXLFLR.js +0 -53497
  235. package/dist/browser/dev/excalidraw-assets-dev/chunk-KGZXLFLR.js.map +0 -7
  236. package/dist/browser/dev/excalidraw-assets-dev/image-3MFRCKYM.css +0 -5797
  237. package/dist/browser/dev/excalidraw-assets-dev/image-3MFRCKYM.css.map +0 -7
  238. package/dist/browser/prod/excalidraw-assets/chunk-4YN2HN3S.js +0 -257
  239. package/dist/browser/prod/excalidraw-assets/chunk-OWLL6VOG.js +0 -11
  240. package/dist/browser/prod/excalidraw-assets/en-ERQOR3OC.js +0 -1
  241. package/dist/browser/prod/excalidraw-assets/image-LTLHTTSE.js +0 -1
  242. package/dist/browser/prod/excalidraw-assets/image-QBL334OA.css +0 -1
  243. package/dist/excalidraw/components/LaserTool/LaserPathManager.d.ts +0 -28
  244. package/dist/excalidraw/components/LaserTool/LaserPathManager.js +0 -225
  245. package/dist/excalidraw/components/LaserTool/LaserTool.d.ts +0 -8
  246. package/dist/excalidraw/components/LaserTool/LaserTool.js +0 -15
  247. package/dist/excalidraw/renderer/renderScene.d.ts +0 -25
  248. package/dist/excalidraw/vite.config.d.mts +0 -2
  249. package/dist/excalidraw/vite.config.mjs +0 -13
  250. /package/dist/browser/dev/excalidraw-assets-dev/{en-OC6JWP3X.js.map → en-IOBA4CS2.js.map} +0 -0
  251. /package/dist/browser/dev/excalidraw-assets-dev/{image-5TVMINCA.js.map → image-VKDAL6BQ.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- /// <reference types="react" />
1
+ import React from "react";
2
2
  import "./Button.scss";
3
3
  interface ButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
4
4
  type?: "button" | "submit" | "reset";
@@ -6,12 +6,12 @@ export type ButtonSize = "medium" | "large";
6
6
  export type FilledButtonProps = {
7
7
  label: string;
8
8
  children?: React.ReactNode;
9
- onClick?: () => void;
9
+ onClick?: (event: React.MouseEvent) => void;
10
10
  variant?: ButtonVariant;
11
11
  color?: ButtonColor;
12
12
  size?: ButtonSize;
13
13
  className?: string;
14
14
  fullWidth?: boolean;
15
- startIcon?: React.ReactNode;
15
+ icon?: React.ReactNode;
16
16
  };
17
17
  export declare const FilledButton: React.ForwardRefExoticComponent<FilledButtonProps & React.RefAttributes<HTMLButtonElement>>;
@@ -1,7 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { forwardRef } from "react";
2
+ import { forwardRef, useState } from "react";
3
3
  import clsx from "clsx";
4
4
  import "./FilledButton.scss";
5
- export const FilledButton = forwardRef(({ children, startIcon, onClick, label, variant = "filled", color = "primary", size = "medium", fullWidth, className, }, ref) => {
6
- return (_jsxs("button", { className: clsx("ExcButton", `ExcButton--color-${color}`, `ExcButton--variant-${variant}`, `ExcButton--size-${size}`, { "ExcButton--fullWidth": fullWidth }, className), onClick: onClick, type: "button", "aria-label": label, ref: ref, children: [startIcon && (_jsx("div", { className: "ExcButton__icon", "aria-hidden": true, children: startIcon })), variant !== "icon" && (children ?? label)] }));
5
+ import { AbortError } from "../errors";
6
+ import Spinner from "./Spinner";
7
+ import { isPromiseLike } from "../utils";
8
+ export const FilledButton = forwardRef(({ children, icon, onClick, label, variant = "filled", color = "primary", size = "medium", fullWidth, className, }, ref) => {
9
+ const [isLoading, setIsLoading] = useState(false);
10
+ const _onClick = async (event) => {
11
+ const ret = onClick?.(event);
12
+ if (isPromiseLike(ret)) {
13
+ try {
14
+ setIsLoading(true);
15
+ await ret;
16
+ }
17
+ catch (error) {
18
+ if (!(error instanceof AbortError)) {
19
+ throw error;
20
+ }
21
+ else {
22
+ console.warn(error);
23
+ }
24
+ }
25
+ finally {
26
+ setIsLoading(false);
27
+ }
28
+ }
29
+ };
30
+ return (_jsx("button", { className: clsx("ExcButton", `ExcButton--color-${color}`, `ExcButton--variant-${variant}`, `ExcButton--size-${size}`, { "ExcButton--fullWidth": fullWidth }, className), onClick: _onClick, type: "button", "aria-label": label, ref: ref, disabled: isLoading, children: _jsxs("div", { className: "ExcButton__contents", children: [isLoading && _jsx(Spinner, {}), icon && (_jsx("div", { className: "ExcButton__icon", "aria-hidden": true, children: icon })), variant !== "icon" && (children ?? label)] }) }));
7
31
  });
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { CloseIcon } from "../icons";
3
3
  import "./FollowMode.scss";
4
4
  const FollowMode = ({ height, width, userToFollow, onDisconnect, }) => {
5
- return (_jsx("div", { style: { position: "relative" }, children: _jsx("div", { className: "follow-mode", style: { width, height }, children: _jsxs("div", { className: "follow-mode__badge", children: [_jsxs("div", { className: "follow-mode__badge__label", children: ["Following", " ", _jsx("span", { className: "follow-mode__badge__username", title: userToFollow.username, children: userToFollow.username })] }), _jsx("button", { onClick: onDisconnect, className: "follow-mode__disconnect-btn", children: CloseIcon })] }) }) }));
5
+ return (_jsx("div", { className: "follow-mode", style: { width, height }, children: _jsxs("div", { className: "follow-mode__badge", children: [_jsxs("div", { className: "follow-mode__badge__label", children: ["Following", " ", _jsx("span", { className: "follow-mode__badge__username", title: userToFollow.username, children: userToFollow.username })] }), _jsx("button", { onClick: onDisconnect, className: "follow-mode__disconnect-btn", children: CloseIcon })] }) }));
6
6
  };
7
7
  export default FollowMode;
@@ -4,11 +4,12 @@ import type { AppClassProperties, BinaryFiles, UIAppState } from "../types";
4
4
  import { NonDeletedExcalidrawElement } from "../element/types";
5
5
  import "./ImageExportDialog.scss";
6
6
  export declare const ErrorCanvasPreview: () => JSX.Element;
7
- export declare const ImageExportDialog: ({ elements, appState, files, actionManager, onExportImage, onCloseRequest, }: {
7
+ export declare const ImageExportDialog: ({ elements, appState, files, actionManager, onExportImage, onCloseRequest, name, }: {
8
8
  appState: UIAppState;
9
9
  elements: readonly NonDeletedExcalidrawElement[];
10
10
  files: BinaryFiles;
11
11
  actionManager: ActionManager;
12
12
  onExportImage: AppClassProperties["onExportImage"];
13
13
  onCloseRequest: () => void;
14
+ name: string;
14
15
  }) => JSX.Element;
@@ -7,14 +7,13 @@ import { canvasToBlob } from "../data/blob";
7
7
  import { nativeFileSystemSupported } from "../data/filesystem";
8
8
  import { t } from "../i18n";
9
9
  import { isSomeElementSelected } from "../scene";
10
- import { exportToCanvas } from "../../utils/index";
10
+ import { exportToCanvas } from "../../utils/export";
11
11
  import { copyIcon, downloadIcon, helpIcon } from "./icons";
12
12
  import { Dialog } from "./Dialog";
13
13
  import { RadioGroup } from "./RadioGroup";
14
14
  import { Switch } from "./Switch";
15
15
  import { Tooltip } from "./Tooltip";
16
16
  import "./ImageExportDialog.scss";
17
- import { useAppProps } from "./App";
18
17
  import { FilledButton } from "./FilledButton";
19
18
  import { cloneJSON } from "../utils";
20
19
  import { prepareElementsForExport } from "../data";
@@ -22,10 +21,9 @@ const supportsContextFilters = "filter" in document.createElement("canvas").getC
22
21
  export const ErrorCanvasPreview = () => {
23
22
  return (_jsxs("div", { children: [_jsx("h3", { children: t("canvasError.cannotShowPreview") }), _jsx("p", { children: _jsx("span", { children: t("canvasError.canvasTooBig") }) }), _jsxs("em", { children: ["(", t("canvasError.canvasTooBigTip"), ")"] })] }));
24
23
  };
25
- const ImageExportModal = ({ appStateSnapshot, elementsSnapshot, files, actionManager, onExportImage, }) => {
24
+ const ImageExportModal = ({ appStateSnapshot, elementsSnapshot, files, actionManager, onExportImage, name, }) => {
26
25
  const hasSelection = isSomeElementSelected(elementsSnapshot, appStateSnapshot);
27
- const appProps = useAppProps();
28
- const [projectName, setProjectName] = useState(appStateSnapshot.name);
26
+ const [projectName, setProjectName] = useState(name);
29
27
  const [exportSelectionOnly, setExportSelectionOnly] = useState(hasSelection);
30
28
  const [exportWithBackground, setExportWithBackground] = useState(appStateSnapshot.exportBackground);
31
29
  const [exportDarkMode, setExportDarkMode] = useState(appStateSnapshot.exportWithDarkMode);
@@ -63,8 +61,15 @@ const ImageExportModal = ({ appStateSnapshot, elementsSnapshot, files, actionMan
63
61
  setRenderError(null);
64
62
  // if converting to blob fails, there's some problem that will
65
63
  // likely prevent preview and export (e.g. canvas too big)
66
- return canvasToBlob(canvas).then(() => {
64
+ return canvasToBlob(canvas)
65
+ .then(() => {
67
66
  previewNode.replaceChildren(canvas);
67
+ })
68
+ .catch((e) => {
69
+ if (e.name === "CANVAS_POSSIBLY_TOO_BIG") {
70
+ throw new Error(t("canvasError.canvasTooBig"));
71
+ }
72
+ throw e;
68
73
  });
69
74
  })
70
75
  .catch((error) => {
@@ -82,8 +87,7 @@ const ImageExportModal = ({ appStateSnapshot, elementsSnapshot, files, actionMan
82
87
  exportScale,
83
88
  embedScene,
84
89
  ]);
85
- return (_jsxs("div", { className: "ImageExportModal", children: [_jsx("h3", { children: t("imageExportDialog.header") }), _jsxs("div", { className: "ImageExportModal__preview", children: [_jsx("div", { className: "ImageExportModal__preview__canvas", ref: previewRef, children: renderError && _jsx(ErrorCanvasPreview, {}) }), _jsx("div", { className: "ImageExportModal__preview__filename", children: !nativeFileSystemSupported && (_jsx("input", { type: "text", className: "TextInput", value: projectName, style: { width: "30ch" }, disabled: typeof appProps.name !== "undefined" ||
86
- appStateSnapshot.viewModeEnabled, onChange: (event) => {
90
+ return (_jsxs("div", { className: "ImageExportModal", children: [_jsx("h3", { children: t("imageExportDialog.header") }), _jsxs("div", { className: "ImageExportModal__preview", children: [_jsx("div", { className: "ImageExportModal__preview__canvas", ref: previewRef, children: renderError && _jsx(ErrorCanvasPreview, {}) }), _jsx("div", { className: "ImageExportModal__preview__filename", children: !nativeFileSystemSupported && (_jsx("input", { type: "text", className: "TextInput", value: projectName, style: { width: "30ch" }, onChange: (event) => {
87
91
  setProjectName(event.target.value);
88
92
  actionManager.executeAction(actionChangeProjectName, "ui", event.target.value);
89
93
  } })) })] }), _jsxs("div", { className: "ImageExportModal__settings", children: [_jsx("h3", { children: t("imageExportDialog.header") }), hasSelection && (_jsx(ExportSetting, { label: t("imageExportDialog.label.onlySelected"), name: "exportOnlySelected", children: _jsx(Switch, { name: "exportOnlySelected", checked: exportSelectionOnly, onChange: (checked) => {
@@ -105,16 +109,16 @@ const ImageExportModal = ({ appStateSnapshot, elementsSnapshot, files, actionMan
105
109
  label: `${scale}\u00d7`,
106
110
  })) }) }), _jsxs("div", { className: "ImageExportModal__settings__buttons", children: [_jsx(FilledButton, { className: "ImageExportModal__settings__buttons__button", label: t("imageExportDialog.title.exportToPng"), onClick: () => onExportImage(EXPORT_IMAGE_TYPES.png, exportedElements, {
107
111
  exportingFrame,
108
- }), startIcon: downloadIcon, children: t("imageExportDialog.button.exportToPng") }), _jsx(FilledButton, { className: "ImageExportModal__settings__buttons__button", label: t("imageExportDialog.title.exportToSvg"), onClick: () => onExportImage(EXPORT_IMAGE_TYPES.svg, exportedElements, {
112
+ }), icon: downloadIcon, children: t("imageExportDialog.button.exportToPng") }), _jsx(FilledButton, { className: "ImageExportModal__settings__buttons__button", label: t("imageExportDialog.title.exportToSvg"), onClick: () => onExportImage(EXPORT_IMAGE_TYPES.svg, exportedElements, {
109
113
  exportingFrame,
110
- }), startIcon: downloadIcon, children: t("imageExportDialog.button.exportToSvg") }), (probablySupportsClipboardBlob || isFirefox) && (_jsx(FilledButton, { className: "ImageExportModal__settings__buttons__button", label: t("imageExportDialog.title.copyPngToClipboard"), onClick: () => onExportImage(EXPORT_IMAGE_TYPES.clipboard, exportedElements, {
114
+ }), icon: downloadIcon, children: t("imageExportDialog.button.exportToSvg") }), (probablySupportsClipboardBlob || isFirefox) && (_jsx(FilledButton, { className: "ImageExportModal__settings__buttons__button", label: t("imageExportDialog.title.copyPngToClipboard"), onClick: () => onExportImage(EXPORT_IMAGE_TYPES.clipboard, exportedElements, {
111
115
  exportingFrame,
112
- }), startIcon: copyIcon, children: t("imageExportDialog.button.copyPngToClipboard") }))] })] })] }));
116
+ }), icon: copyIcon, children: t("imageExportDialog.button.copyPngToClipboard") }))] })] })] }));
113
117
  };
114
118
  const ExportSetting = ({ label, children, tooltip, name, }) => {
115
119
  return (_jsxs("div", { className: "ImageExportModal__settings__setting", title: label, children: [_jsxs("label", { htmlFor: name, className: "ImageExportModal__settings__setting__label", children: [label, tooltip && (_jsx(Tooltip, { label: tooltip, long: true, children: helpIcon }))] }), _jsx("div", { className: "ImageExportModal__settings__setting__content", children: children })] }));
116
120
  };
117
- export const ImageExportDialog = ({ elements, appState, files, actionManager, onExportImage, onCloseRequest, }) => {
121
+ export const ImageExportDialog = ({ elements, appState, files, actionManager, onExportImage, onCloseRequest, name, }) => {
118
122
  // we need to take a snapshot so that the exported state can't be modified
119
123
  // while the dialog is open
120
124
  const [{ appStateSnapshot, elementsSnapshot }] = useState(() => {
@@ -123,5 +127,5 @@ export const ImageExportDialog = ({ elements, appState, files, actionManager, on
123
127
  elementsSnapshot: cloneJSON(elements),
124
128
  };
125
129
  });
126
- return (_jsx(Dialog, { onCloseRequest: onCloseRequest, size: "wide", title: false, children: _jsx(ImageExportModal, { elementsSnapshot: elementsSnapshot, appStateSnapshot: appStateSnapshot, files: files, actionManager: actionManager, onExportImage: onExportImage }) }));
130
+ return (_jsx(Dialog, { onCloseRequest: onCloseRequest, size: "wide", title: false, children: _jsx(ImageExportModal, { elementsSnapshot: elementsSnapshot, appStateSnapshot: appStateSnapshot, files: files, actionManager: actionManager, onExportImage: onExportImage, name: name }) }));
127
131
  };
@@ -18,7 +18,7 @@ const JSONExportModal = ({ elements, appState, setAppState, files, actionManager
18
18
  } })] })), onExportToBackend && (_jsxs(Card, { color: "pink", children: [_jsx("div", { className: "Card-icon", children: LinkIcon }), _jsx("h2", { children: t("exportDialog.link_title") }), _jsx("div", { className: "Card-details", children: t("exportDialog.link_details") }), _jsx(ToolButton, { className: "Card-button", type: "button", title: t("exportDialog.link_button"), "aria-label": t("exportDialog.link_button"), showAriaLabel: true, onClick: async () => {
19
19
  try {
20
20
  trackEvent("export", "link", `ui (${getFrame()})`);
21
- await onExportToBackend(elements, appState, files, canvas);
21
+ await onExportToBackend(elements, appState, files);
22
22
  onCloseRequest();
23
23
  }
24
24
  catch (error) {
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import "../ToolIcon.scss";
2
+ import "./ToolIcon.scss";
3
3
  type LaserPointerIconProps = {
4
4
  title?: string;
5
5
  name?: string;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import "../ToolIcon.scss";
2
+ import "./ToolIcon.scss";
3
3
  import clsx from "clsx";
4
- import { laserPointerToolIcon } from "../icons";
4
+ import { laserPointerToolIcon } from "./icons";
5
5
  const DEFAULT_SIZE = "small";
6
6
  export const LaserPointerButton = (props) => {
7
7
  return (_jsxs("label", { className: clsx("ToolIcon ToolIcon__LaserPointer", `ToolIcon_size_${DEFAULT_SIZE}`, {
@@ -45,7 +45,7 @@ import "./Toolbar.scss";
45
45
  import { mutateElement } from "../element/mutateElement";
46
46
  import { ShapeCache } from "../scene/ShapeCache";
47
47
  import Scene from "../scene/Scene";
48
- import { LaserPointerButton } from "./LaserTool/LaserPointerButton";
48
+ import { LaserPointerButton } from "./LaserPointerButton";
49
49
  import { MagicSettings } from "./MagicSettings";
50
50
  import { TTDDialog } from "./TTDDialog/TTDDialog";
51
51
  const DefaultMainMenu = ({ UIOptions }) => {
@@ -69,7 +69,7 @@ const LayerUI = ({ actionManager, appState, files, setAppState, elements, canvas
69
69
  appState.openDialog?.name !== "imageExport") {
70
70
  return null;
71
71
  }
72
- return (_jsx(ImageExportDialog, { elements: elements, appState: appState, files: files, actionManager: actionManager, onExportImage: onExportImage, onCloseRequest: () => setAppState({ openDialog: null }) }));
72
+ return (_jsx(ImageExportDialog, { elements: elements, appState: appState, files: files, actionManager: actionManager, onExportImage: onExportImage, onCloseRequest: () => setAppState({ openDialog: null }), name: app.getName() }));
73
73
  };
74
74
  const renderCanvasActions = () => (_jsxs("div", { style: { position: "relative" }, children: [_jsx(tunnels.MainMenuTunnel.Out, {}), renderWelcomeScreen && _jsx(tunnels.WelcomeScreenMenuHintTunnel.Out, {})] }));
75
75
  const renderSelectedShapeActions = () => (_jsx(Section, { heading: "selectedShapeActions", className: clsx("selected-shape-actions zen-mode-transition", {
@@ -78,7 +78,7 @@ const LayerUI = ({ actionManager, appState, files, setAppState, elements, canvas
78
78
  // we want to make sure this doesn't overflow so subtracting the
79
79
  // approximate height of hamburgerMenu + footer
80
80
  maxHeight: `${appState.height - 166}px`,
81
- }, children: _jsx(SelectedShapeActions, { appState: appState, elements: elements, renderAction: actionManager.renderAction }) }) }));
81
+ }, children: _jsx(SelectedShapeActions, { appState: appState, elementsMap: app.scene.getNonDeletedElementsMap(), renderAction: actionManager.renderAction }) }) }));
82
82
  const renderFixedSideContainer = () => {
83
83
  const shouldRenderSelectedShapeActions = showSelectedShapeActions(appState, elements);
84
84
  return (_jsx(FixedSideContainer, { side: "top", children: _jsxs("div", { className: "App-menu App-menu_top", children: [_jsxs(Stack.Col, { gap: 6, className: clsx("App-menu_top__left"), children: [renderCanvasActions(), shouldRenderSelectedShapeActions && renderSelectedShapeActions()] }), !appState.viewModeEnabled && (_jsx(Section, { heading: "shapes", className: "shapes-section", children: (heading) => (_jsxs("div", { style: { position: "relative" }, children: [renderWelcomeScreen && (_jsx(tunnels.WelcomeScreenToolbarHintTunnel.Out, {})), _jsx(Stack.Col, { gap: 4, align: "start", children: _jsxs(Stack.Row, { gap: 1, className: clsx("App-toolbar-container", {
@@ -35,7 +35,7 @@ export const MobileMenu = ({ appState, elements, actionManager, setAppState, onL
35
35
  marginRight: SCROLLBAR_WIDTH + SCROLLBAR_MARGIN * 2,
36
36
  }, children: _jsxs(Island, { padding: 0, children: [appState.openMenu === "shape" &&
37
37
  !appState.viewModeEnabled &&
38
- showSelectedShapeActions(appState, elements) ? (_jsx(Section, { className: "App-mobile-menu", heading: "selectedShapeActions", children: _jsx(SelectedShapeActions, { appState: appState, elements: elements, renderAction: actionManager.renderAction }) })) : null, _jsxs("footer", { className: "App-toolbar", children: [renderAppToolbar(), appState.scrolledOutside &&
38
+ showSelectedShapeActions(appState, elements) ? (_jsx(Section, { className: "App-mobile-menu", heading: "selectedShapeActions", children: _jsx(SelectedShapeActions, { appState: appState, elementsMap: app.scene.getNonDeletedElementsMap(), renderAction: actionManager.renderAction }) })) : null, _jsxs("footer", { className: "App-toolbar", children: [renderAppToolbar(), appState.scrolledOutside &&
39
39
  !appState.openMenu &&
40
40
  !appState.openSidebar && (_jsx("button", { className: "scroll-back-to-content", onClick: () => {
41
41
  setAppState((appState) => ({
@@ -5,7 +5,6 @@ type Props = {
5
5
  value: string;
6
6
  onChange: (value: string) => void;
7
7
  label: string;
8
- isNameEditable: boolean;
9
8
  ignoreFocus?: boolean;
10
9
  };
11
10
  export declare const ProjectName: (props: Props) => JSX.Element;
@@ -26,5 +26,5 @@ export const ProjectName = (props) => {
26
26
  event.currentTarget.blur();
27
27
  }
28
28
  };
29
- return (_jsxs("div", { className: "ProjectName", children: [_jsx("label", { className: "ProjectName-label", htmlFor: "filename", children: `${props.label}${props.isNameEditable ? "" : ":"}` }), props.isNameEditable ? (_jsx("input", { type: "text", className: "TextInput", onBlur: handleBlur, onKeyDown: handleKeyDown, id: `${id}-filename`, value: fileName, onChange: (event) => setFileName(event.target.value) })) : (_jsx("span", { className: "TextInput TextInput--readonly", id: `${id}-filename`, children: props.value }))] }));
29
+ return (_jsxs("div", { className: "ProjectName", children: [_jsx("label", { className: "ProjectName-label", htmlFor: "filename", children: `${props.label}:` }), _jsx("input", { type: "text", className: "TextInput", onBlur: handleBlur, onKeyDown: handleKeyDown, id: `${id}-filename`, value: fileName, onChange: (event) => setFileName(event.target.value) })] }));
30
30
  };
@@ -4,7 +4,7 @@ import OpenColor from "open-color";
4
4
  import { Dialog } from "./Dialog";
5
5
  import { t } from "../i18n";
6
6
  import Trans from "./Trans";
7
- import { exportToCanvas, exportToSvg } from "../../utils/index";
7
+ import { exportToCanvas, exportToSvg } from "../../utils/export";
8
8
  import { EDITOR_LS_KEYS, EXPORT_DATA_TYPES, EXPORT_SOURCE, MIME_TYPES, VERSIONS, } from "../constants";
9
9
  import { canvasToBlob, resizeImageFile } from "../data/blob";
10
10
  import { chunk } from "../utils";
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { Trail } from "../animated-trail";
3
+ import "./SVGLayer.scss";
4
+ type SVGLayerProps = {
5
+ trails: Trail[];
6
+ };
7
+ export declare const SVGLayer: ({ trails }: SVGLayerProps) => JSX.Element;
8
+ export {};
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from "react";
3
+ import "./SVGLayer.scss";
4
+ export const SVGLayer = ({ trails }) => {
5
+ const svgRef = useRef(null);
6
+ useEffect(() => {
7
+ if (svgRef.current) {
8
+ for (const trail of trails) {
9
+ trail.start(svgRef.current);
10
+ }
11
+ }
12
+ return () => {
13
+ for (const trail of trails) {
14
+ trail.stop();
15
+ }
16
+ };
17
+ // eslint-disable-next-line react-hooks/exhaustive-deps
18
+ }, trails);
19
+ return (_jsx("div", { className: "SVGLayer", children: _jsx("svg", { ref: svgRef }) }));
20
+ };
@@ -16,18 +16,18 @@ export const ShareableLinkDialog = ({ link, onCloseRequest, setErrorMessage, })
16
16
  const copyRoomLink = async () => {
17
17
  try {
18
18
  await copyTextToSystemClipboard(link);
19
- setJustCopied(true);
20
- if (timerRef.current) {
21
- window.clearTimeout(timerRef.current);
22
- }
23
- timerRef.current = window.setTimeout(() => {
24
- setJustCopied(false);
25
- }, 3000);
26
19
  }
27
- catch (error) {
28
- setErrorMessage(error.message);
20
+ catch (e) {
21
+ setErrorMessage(t("errors.copyToSystemClipboardFailed"));
29
22
  }
23
+ setJustCopied(true);
24
+ if (timerRef.current) {
25
+ window.clearTimeout(timerRef.current);
26
+ }
27
+ timerRef.current = window.setTimeout(() => {
28
+ setJustCopied(false);
29
+ }, 3000);
30
30
  ref.current?.select();
31
31
  };
32
- return (_jsx(Dialog, { onCloseRequest: onCloseRequest, title: false, size: "small", children: _jsxs("div", { className: "ShareableLinkDialog", children: [_jsx("h3", { children: "Shareable link" }), _jsxs("div", { className: "ShareableLinkDialog__linkRow", children: [_jsx(TextField, { ref: ref, label: "Link", readonly: true, fullWidth: true, value: link, selectOnRender: true }), _jsxs(Popover.Root, { open: justCopied, children: [_jsx(Popover.Trigger, { asChild: true, children: _jsx(FilledButton, { size: "large", label: "Copy link", startIcon: copyIcon, onClick: copyRoomLink }) }), _jsxs(Popover.Content, { onOpenAutoFocus: (event) => event.preventDefault(), onCloseAutoFocus: (event) => event.preventDefault(), className: "ShareableLinkDialog__popover", side: "top", align: "end", sideOffset: 5.5, children: [tablerCheckIcon, " copied"] })] })] }), _jsxs("div", { className: "ShareableLinkDialog__description", children: ["\uD83D\uDD12 ", t("alerts.uploadedSecurly")] })] }) }));
32
+ return (_jsx(Dialog, { onCloseRequest: onCloseRequest, title: false, size: "small", children: _jsxs("div", { className: "ShareableLinkDialog", children: [_jsx("h3", { children: "Shareable link" }), _jsxs("div", { className: "ShareableLinkDialog__linkRow", children: [_jsx(TextField, { ref: ref, label: "Link", readonly: true, fullWidth: true, value: link, selectOnRender: true }), _jsxs(Popover.Root, { open: justCopied, children: [_jsx(Popover.Trigger, { asChild: true, children: _jsx(FilledButton, { size: "large", label: "Copy link", icon: copyIcon, onClick: copyRoomLink }) }), _jsxs(Popover.Content, { onOpenAutoFocus: (event) => event.preventDefault(), onCloseAutoFocus: (event) => event.preventDefault(), className: "ShareableLinkDialog__popover", side: "top", align: "end", sideOffset: 5.5, children: [tablerCheckIcon, " copied"] })] })] }), _jsxs("div", { className: "ShareableLinkDialog__description", children: ["\uD83D\uDD12 ", t("alerts.uploadedSecurly")] })] }) }));
33
33
  };
@@ -22,7 +22,7 @@ export declare const SidebarInner: React.ForwardRefExoticComponent<Pick<{
22
22
  docked?: boolean | undefined;
23
23
  className?: string | undefined;
24
24
  __fallback?: boolean | undefined;
25
- } & Omit<React.RefAttributes<HTMLDivElement>, "onSelect">, "name" | "children" | "key" | "className" | "__fallback" | "onDock" | "docked" | "onStateChange"> & React.RefAttributes<HTMLDivElement>>;
25
+ } & Omit<React.RefAttributes<HTMLDivElement>, "onSelect">, "name" | "children" | "key" | "className" | "onDock" | "docked" | "onStateChange" | "__fallback"> & React.RefAttributes<HTMLDivElement>>;
26
26
  export declare const Sidebar: React.ForwardRefExoticComponent<{
27
27
  name: string;
28
28
  children: React.ReactNode;
@@ -10,7 +10,7 @@ type StackProps = {
10
10
  ref: React.RefObject<HTMLDivElement>;
11
11
  };
12
12
  declare const _default: {
13
- Row: React.ForwardRefExoticComponent<Pick<StackProps, "children" | "style" | "align" | "gap" | "className" | "justifyContent"> & React.RefAttributes<HTMLDivElement>>;
14
- Col: React.ForwardRefExoticComponent<Pick<StackProps, "children" | "style" | "align" | "gap" | "className" | "justifyContent"> & React.RefAttributes<HTMLDivElement>>;
13
+ Row: React.ForwardRefExoticComponent<Pick<StackProps, "children" | "style" | "gap" | "className" | "align" | "justifyContent"> & React.RefAttributes<HTMLDivElement>>;
14
+ Col: React.ForwardRefExoticComponent<Pick<StackProps, "children" | "style" | "gap" | "className" | "align" | "justifyContent"> & React.RefAttributes<HTMLDivElement>>;
15
15
  };
16
16
  export default _default;
@@ -2,6 +2,7 @@ import { DEFAULT_EXPORT_PADDING, DEFAULT_FONT_SIZE, EDITOR_LS_KEYS, } from "../.
2
2
  import { convertToExcalidrawElements, exportToCanvas } from "../../index";
3
3
  import { canvasToBlob } from "../../data/blob";
4
4
  import { EditorLocalStorage } from "../../data/EditorLocalStorage";
5
+ import { t } from "../../i18n";
5
6
  const resetPreview = ({ canvasRef, setError, }) => {
6
7
  const canvasNode = canvasRef.current;
7
8
  if (!canvasNode) {
@@ -55,7 +56,15 @@ export const convertMermaidToExcalidraw = async ({ canvasRef, mermaidToExcalidra
55
56
  });
56
57
  // if converting to blob fails, there's some problem that will
57
58
  // likely prevent preview and export (e.g. canvas too big)
58
- await canvasToBlob(canvas);
59
+ try {
60
+ await canvasToBlob(canvas);
61
+ }
62
+ catch (e) {
63
+ if (e.name === "CANVAS_POSSIBLY_TOO_BIG") {
64
+ throw new Error(t("canvasError.canvasTooBig"));
65
+ }
66
+ throw e;
67
+ }
59
68
  parent.style.background = "var(--default-bg-color)";
60
69
  canvasNode.replaceChildren(canvas);
61
70
  }
@@ -1,7 +1,6 @@
1
1
  import { KeyboardEvent } from "react";
2
2
  import "./TextField.scss";
3
3
  type TextFieldProps = {
4
- value?: string;
5
4
  onChange?: (value: string) => void;
6
5
  onClick?: () => void;
7
6
  onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
@@ -11,6 +10,10 @@ type TextFieldProps = {
11
10
  label?: string;
12
11
  placeholder?: string;
13
12
  isRedacted?: boolean;
14
- };
13
+ } & ({
14
+ value: string;
15
+ } | {
16
+ defaultValue: string;
17
+ });
15
18
  export declare const TextField: import("react").ForwardRefExoticComponent<TextFieldProps & import("react").RefAttributes<HTMLInputElement>>;
16
19
  export {};
@@ -4,7 +4,7 @@ import clsx from "clsx";
4
4
  import "./TextField.scss";
5
5
  import { Button } from "./Button";
6
6
  import { eyeIcon, eyeClosedIcon } from "./icons";
7
- export const TextField = forwardRef(({ value, onChange, label, fullWidth, placeholder, readonly, selectOnRender, onKeyDown, isRedacted = false, }, ref) => {
7
+ export const TextField = forwardRef(({ onChange, label, fullWidth, placeholder, readonly, selectOnRender, onKeyDown, isRedacted = false, ...rest }, ref) => {
8
8
  const innerRef = useRef(null);
9
9
  useImperativeHandle(ref, () => innerRef.current);
10
10
  useLayoutEffect(() => {
@@ -20,6 +20,9 @@ export const TextField = forwardRef(({ value, onChange, label, fullWidth, placeh
20
20
  }, children: [_jsx("div", { className: "ExcTextField__label", children: label }), _jsxs("div", { className: clsx("ExcTextField__input", {
21
21
  "ExcTextField__input--readonly": readonly,
22
22
  }), children: [_jsx("input", { className: clsx({
23
- "is-redacted": value && isRedacted && !isTemporarilyUnredacted,
24
- }), readOnly: readonly, value: value, placeholder: placeholder, ref: innerRef, onChange: (event) => onChange?.(event.target.value), onKeyDown: onKeyDown }), isRedacted && (_jsx(Button, { onSelect: () => setIsTemporarilyUnredacted(!isTemporarilyUnredacted), style: { border: 0, userSelect: "none" }, children: isTemporarilyUnredacted ? eyeClosedIcon : eyeIcon }))] })] }));
23
+ "is-redacted": "value" in rest &&
24
+ rest.value &&
25
+ isRedacted &&
26
+ !isTemporarilyUnredacted,
27
+ }), readOnly: readonly, value: "value" in rest ? rest.value : undefined, defaultValue: "defaultValue" in rest ? rest.defaultValue : undefined, placeholder: placeholder, ref: innerRef, onChange: (event) => onChange?.(event.target.value), onKeyDown: onKeyDown }), isRedacted && (_jsx(Button, { onSelect: () => setIsTemporarilyUnredacted(!isTemporarilyUnredacted), style: { border: 0, userSelect: "none" }, children: isTemporarilyUnredacted ? eyeClosedIcon : eyeIcon }))] })] }));
25
28
  });
@@ -1,8 +1,9 @@
1
- /// <reference types="react" />
1
+ import { CSSProperties } from "react";
2
2
  import "./Toast.scss";
3
- export declare const Toast: ({ message, onClose, closable, duration, }: {
3
+ export declare const Toast: ({ message, onClose, closable, duration, style, }: {
4
4
  message: string;
5
5
  onClose: () => void;
6
6
  closable?: boolean | undefined;
7
7
  duration?: number | undefined;
8
+ style?: CSSProperties | undefined;
8
9
  }) => JSX.Element;
@@ -6,7 +6,7 @@ import { ToolButton } from "./ToolButton";
6
6
  const DEFAULT_TOAST_TIMEOUT = 5000;
7
7
  export const Toast = ({ message, onClose, closable = false,
8
8
  // To prevent autoclose, pass duration as Infinity
9
- duration = DEFAULT_TOAST_TIMEOUT, }) => {
9
+ duration = DEFAULT_TOAST_TIMEOUT, style, }) => {
10
10
  const timerRef = useRef(0);
11
11
  const shouldAutoClose = duration !== Infinity;
12
12
  const scheduleTimeout = useCallback(() => {
@@ -26,5 +26,5 @@ duration = DEFAULT_TOAST_TIMEOUT, }) => {
26
26
  ? () => clearTimeout(timerRef?.current)
27
27
  : undefined;
28
28
  const onMouseLeave = shouldAutoClose ? scheduleTimeout : undefined;
29
- return (_jsxs("div", { className: "Toast", onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: [_jsx("p", { className: "Toast__message", children: message }), closable && (_jsx(ToolButton, { icon: CloseIcon, "aria-label": "close", type: "icon", onClick: onClose, className: "close" }))] }));
29
+ return (_jsxs("div", { className: "Toast", onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, style: style, children: [_jsx("p", { className: "Toast__message", children: message }), closable && (_jsx(ToolButton, { icon: CloseIcon, "aria-label": "close", type: "icon", onClick: onClose, className: "close" }))] }));
30
30
  };
@@ -5,6 +5,7 @@ import clsx from "clsx";
5
5
  import { useExcalidrawContainer } from "./App";
6
6
  import { AbortError } from "../errors";
7
7
  import Spinner from "./Spinner";
8
+ import { isPromiseLike } from "../utils";
8
9
  export const ToolButton = React.forwardRef((props, ref) => {
9
10
  const { id: excalId } = useExcalidrawContainer();
10
11
  const innerRef = React.useRef(null);
@@ -14,7 +15,7 @@ export const ToolButton = React.forwardRef((props, ref) => {
14
15
  const isMountedRef = useRef(true);
15
16
  const onClick = async (event) => {
16
17
  const ret = "onClick" in props && props.onClick?.(event);
17
- if (ret && "then" in ret) {
18
+ if (isPromiseLike(ret)) {
18
19
  try {
19
20
  setIsLoading(true);
20
21
  await ret;
@@ -1,12 +1,12 @@
1
1
  import React from "react";
2
2
  import type { DOMAttributes } from "react";
3
3
  import type { InteractiveCanvasAppState } from "../../types";
4
- import type { RenderInteractiveSceneCallback } from "../../scene/types";
4
+ import type { RenderableElementsMap, RenderInteractiveSceneCallback } from "../../scene/types";
5
5
  import type { NonDeletedExcalidrawElement } from "../../element/types";
6
6
  type InteractiveCanvasProps = {
7
7
  containerRef: React.RefObject<HTMLDivElement>;
8
8
  canvas: HTMLCanvasElement | null;
9
- elements: readonly NonDeletedExcalidrawElement[];
9
+ elementsMap: RenderableElementsMap;
10
10
  visibleElements: readonly NonDeletedExcalidrawElement[];
11
11
  selectedElements: readonly NonDeletedExcalidrawElement[];
12
12
  versionNonce: number | undefined;
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React, { useEffect, useRef } from "react";
3
- import { renderInteractiveScene } from "../../renderer/renderScene";
4
- import { isRenderThrottlingEnabled, isShallowEqual, sceneCoordsToViewportCoords, } from "../../utils";
3
+ import { isShallowEqual, sceneCoordsToViewportCoords } from "../../utils";
5
4
  import { CURSOR_TYPE } from "../../constants";
6
5
  import { t } from "../../i18n";
6
+ import { isRenderThrottlingEnabled } from "../../reactUtils";
7
+ import { renderInteractiveScene } from "../../renderer/interactiveScene";
7
8
  const InteractiveCanvas = (props) => {
8
9
  const isComponentMounted = useRef(false);
9
10
  useEffect(() => {
@@ -45,7 +46,7 @@ const InteractiveCanvas = (props) => {
45
46
  "#6965db";
46
47
  renderInteractiveScene({
47
48
  canvas: props.canvas,
48
- elements: props.elements,
49
+ elementsMap: props.elementsMap,
49
50
  visibleElements: props.visibleElements,
50
51
  selectedElements: props.selectedElements,
51
52
  scale: window.devicePixelRatio,
@@ -103,10 +104,10 @@ const areEqual = (prevProps, nextProps) => {
103
104
  if (prevProps.selectionNonce !== nextProps.selectionNonce ||
104
105
  prevProps.versionNonce !== nextProps.versionNonce ||
105
106
  prevProps.scale !== nextProps.scale ||
106
- // we need to memoize on element arrays because they may have renewed
107
+ // we need to memoize on elementsMap because they may have renewed
107
108
  // even if versionNonce didn't change (e.g. we filter elements out based
108
109
  // on appState)
109
- prevProps.elements !== nextProps.elements ||
110
+ prevProps.elementsMap !== nextProps.elementsMap ||
110
111
  prevProps.visibleElements !== nextProps.visibleElements ||
111
112
  prevProps.selectedElements !== nextProps.selectedElements) {
112
113
  return false;
@@ -1,12 +1,13 @@
1
1
  import React from "react";
2
2
  import { RoughCanvas } from "roughjs/bin/canvas";
3
3
  import type { StaticCanvasAppState } from "../../types";
4
- import type { StaticCanvasRenderConfig } from "../../scene/types";
5
- import type { NonDeletedExcalidrawElement } from "../../element/types";
4
+ import type { RenderableElementsMap, StaticCanvasRenderConfig } from "../../scene/types";
5
+ import type { NonDeletedExcalidrawElement, NonDeletedSceneElementsMap } from "../../element/types";
6
6
  type StaticCanvasProps = {
7
7
  canvas: HTMLCanvasElement;
8
8
  rc: RoughCanvas;
9
- elements: readonly NonDeletedExcalidrawElement[];
9
+ elementsMap: RenderableElementsMap;
10
+ allElementsMap: NonDeletedSceneElementsMap;
10
11
  visibleElements: readonly NonDeletedExcalidrawElement[];
11
12
  versionNonce: number | undefined;
12
13
  selectionNonce: number | undefined;
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React, { useEffect, useRef } from "react";
3
- import { renderStaticScene } from "../../renderer/renderScene";
4
- import { isRenderThrottlingEnabled, isShallowEqual } from "../../utils";
3
+ import { renderStaticScene } from "../../renderer/staticScene";
4
+ import { isShallowEqual } from "../../utils";
5
+ import { isRenderThrottlingEnabled } from "../../reactUtils";
5
6
  const StaticCanvas = (props) => {
6
7
  const wrapperRef = useRef(null);
7
8
  const isComponentMounted = useRef(false);
@@ -38,7 +39,8 @@ const StaticCanvas = (props) => {
38
39
  canvas,
39
40
  rc: props.rc,
40
41
  scale: props.scale,
41
- elements: props.elements,
42
+ elementsMap: props.elementsMap,
43
+ allElementsMap: props.allElementsMap,
42
44
  visibleElements: props.visibleElements,
43
45
  appState: props.appState,
44
46
  renderConfig: props.renderConfig,
@@ -70,10 +72,10 @@ const getRelevantAppStateProps = (appState) => ({
70
72
  const areEqual = (prevProps, nextProps) => {
71
73
  if (prevProps.versionNonce !== nextProps.versionNonce ||
72
74
  prevProps.scale !== nextProps.scale ||
73
- // we need to memoize on element arrays because they may have renewed
75
+ // we need to memoize on elementsMap because they may have renewed
74
76
  // even if versionNonce didn't change (e.g. we filter elements out based
75
77
  // on appState)
76
- prevProps.elements !== nextProps.elements ||
78
+ prevProps.elementsMap !== nextProps.elementsMap ||
77
79
  prevProps.visibleElements !== nextProps.visibleElements) {
78
80
  return false;
79
81
  }