@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
@@ -0,0 +1,33 @@
1
+ import { LaserPointerOptions } from "@excalidraw/laser-pointer";
2
+ import { AnimationFrameHandler } from "./animation-frame-handler";
3
+ import type App from "./components/App";
4
+ export interface Trail {
5
+ start(container: SVGSVGElement): void;
6
+ stop(): void;
7
+ startPath(x: number, y: number): void;
8
+ addPointToPath(x: number, y: number): void;
9
+ endPath(): void;
10
+ }
11
+ export interface AnimatedTrailOptions {
12
+ fill: (trail: AnimatedTrail) => string;
13
+ }
14
+ export declare class AnimatedTrail implements Trail {
15
+ private animationFrameHandler;
16
+ private app;
17
+ private options;
18
+ private currentTrail?;
19
+ private pastTrails;
20
+ private container?;
21
+ private trailElement;
22
+ constructor(animationFrameHandler: AnimationFrameHandler, app: App, options: Partial<LaserPointerOptions> & Partial<AnimatedTrailOptions>);
23
+ get hasCurrentTrail(): boolean;
24
+ hasLastPoint(x: number, y: number): boolean;
25
+ start(container?: SVGSVGElement): void;
26
+ stop(): void;
27
+ startPath(x: number, y: number): void;
28
+ addPointToPath(x: number, y: number): void;
29
+ endPath(): void;
30
+ private update;
31
+ private onFrame;
32
+ private drawTrail;
33
+ }
@@ -0,0 +1,96 @@
1
+ import { LaserPointer } from "@excalidraw/laser-pointer";
2
+ import { getSvgPathFromStroke, sceneCoordsToViewportCoords } from "./utils";
3
+ import { SVG_NS } from "./constants";
4
+ export class AnimatedTrail {
5
+ animationFrameHandler;
6
+ app;
7
+ options;
8
+ currentTrail;
9
+ pastTrails = [];
10
+ container;
11
+ trailElement;
12
+ constructor(animationFrameHandler, app, options) {
13
+ this.animationFrameHandler = animationFrameHandler;
14
+ this.app = app;
15
+ this.options = options;
16
+ this.animationFrameHandler.register(this, this.onFrame.bind(this));
17
+ this.trailElement = document.createElementNS(SVG_NS, "path");
18
+ }
19
+ get hasCurrentTrail() {
20
+ return !!this.currentTrail;
21
+ }
22
+ hasLastPoint(x, y) {
23
+ if (this.currentTrail) {
24
+ const len = this.currentTrail.originalPoints.length;
25
+ return (this.currentTrail.originalPoints[len - 1][0] === x &&
26
+ this.currentTrail.originalPoints[len - 1][1] === y);
27
+ }
28
+ return false;
29
+ }
30
+ start(container) {
31
+ if (container) {
32
+ this.container = container;
33
+ }
34
+ if (this.trailElement.parentNode !== this.container && this.container) {
35
+ this.container.appendChild(this.trailElement);
36
+ }
37
+ this.animationFrameHandler.start(this);
38
+ }
39
+ stop() {
40
+ this.animationFrameHandler.stop(this);
41
+ if (this.trailElement.parentNode === this.container) {
42
+ this.container?.removeChild(this.trailElement);
43
+ }
44
+ }
45
+ startPath(x, y) {
46
+ this.currentTrail = new LaserPointer(this.options);
47
+ this.currentTrail.addPoint([x, y, performance.now()]);
48
+ this.update();
49
+ }
50
+ addPointToPath(x, y) {
51
+ if (this.currentTrail) {
52
+ this.currentTrail.addPoint([x, y, performance.now()]);
53
+ this.update();
54
+ }
55
+ }
56
+ endPath() {
57
+ if (this.currentTrail) {
58
+ this.currentTrail.close();
59
+ this.currentTrail.options.keepHead = false;
60
+ this.pastTrails.push(this.currentTrail);
61
+ this.currentTrail = undefined;
62
+ this.update();
63
+ }
64
+ }
65
+ update() {
66
+ this.start();
67
+ }
68
+ onFrame() {
69
+ const paths = [];
70
+ for (const trail of this.pastTrails) {
71
+ paths.push(this.drawTrail(trail, this.app.state));
72
+ }
73
+ if (this.currentTrail) {
74
+ const currentPath = this.drawTrail(this.currentTrail, this.app.state);
75
+ paths.push(currentPath);
76
+ }
77
+ this.pastTrails = this.pastTrails.filter((trail) => {
78
+ return trail.getStrokeOutline().length !== 0;
79
+ });
80
+ if (paths.length === 0) {
81
+ this.stop();
82
+ }
83
+ const svgPaths = paths.join(" ").trim();
84
+ this.trailElement.setAttribute("d", svgPaths);
85
+ this.trailElement.setAttribute("fill", (this.options.fill ?? (() => "black"))(this));
86
+ }
87
+ drawTrail(trail, state) {
88
+ const stroke = trail
89
+ .getStrokeOutline(trail.options.size / state.zoom.value)
90
+ .map(([x, y]) => {
91
+ const result = sceneCoordsToViewportCoords({ sceneX: x, sceneY: y }, state);
92
+ return [result.x, result.y];
93
+ });
94
+ return getSvgPathFromStroke(stroke, true);
95
+ }
96
+ }
@@ -0,0 +1,16 @@
1
+ export type AnimationCallback = (timestamp: number) => void | boolean;
2
+ export type AnimationTarget = {
3
+ callback: AnimationCallback;
4
+ stopped: boolean;
5
+ };
6
+ export declare class AnimationFrameHandler {
7
+ private targets;
8
+ private rafIds;
9
+ register(key: object, callback: AnimationCallback): void;
10
+ start(key: object): void;
11
+ stop(key: object): void;
12
+ private constructFrame;
13
+ private scheduleFrame;
14
+ private cancelFrame;
15
+ private onFrame;
16
+ }
@@ -0,0 +1,55 @@
1
+ export class AnimationFrameHandler {
2
+ targets = new WeakMap();
3
+ rafIds = new WeakMap();
4
+ register(key, callback) {
5
+ this.targets.set(key, { callback, stopped: true });
6
+ }
7
+ start(key) {
8
+ const target = this.targets.get(key);
9
+ if (!target) {
10
+ return;
11
+ }
12
+ if (this.rafIds.has(key)) {
13
+ return;
14
+ }
15
+ this.targets.set(key, { ...target, stopped: false });
16
+ this.scheduleFrame(key);
17
+ }
18
+ stop(key) {
19
+ const target = this.targets.get(key);
20
+ if (target && !target.stopped) {
21
+ this.targets.set(key, { ...target, stopped: true });
22
+ }
23
+ this.cancelFrame(key);
24
+ }
25
+ constructFrame(key) {
26
+ return (timestamp) => {
27
+ const target = this.targets.get(key);
28
+ if (!target) {
29
+ return;
30
+ }
31
+ const shouldAbort = this.onFrame(target, timestamp);
32
+ if (!target.stopped && !shouldAbort) {
33
+ this.scheduleFrame(key);
34
+ }
35
+ else {
36
+ this.cancelFrame(key);
37
+ }
38
+ };
39
+ }
40
+ scheduleFrame(key) {
41
+ const rafId = requestAnimationFrame(this.constructFrame(key));
42
+ this.rafIds.set(key, rafId);
43
+ }
44
+ cancelFrame(key) {
45
+ if (this.rafIds.has(key)) {
46
+ const rafId = this.rafIds.get(key);
47
+ cancelAnimationFrame(rafId);
48
+ }
49
+ this.rafIds.delete(key);
50
+ }
51
+ onFrame(target, timestamp) {
52
+ const shouldAbort = target.callback(timestamp);
53
+ return shouldAbort ?? false;
54
+ }
55
+ }
@@ -30,7 +30,7 @@ export declare const clearAppStateForLocalStorage: (appState: Partial<AppState>)
30
30
  scrollY?: number | undefined;
31
31
  cursorButton?: "up" | "down" | undefined;
32
32
  scrolledOutside?: boolean | undefined;
33
- name?: string | undefined;
33
+ name?: string | null | undefined;
34
34
  zoom?: Readonly<{
35
35
  value: NormalizedZoomValue;
36
36
  }> | undefined;
@@ -1,7 +1,5 @@
1
1
  import { COLOR_PALETTE } from "./colors";
2
2
  import { DEFAULT_ELEMENT_PROPS, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, DEFAULT_TEXT_ALIGN, EXPORT_SCALES, THEME, } from "./constants";
3
- import { t } from "./i18n";
4
- import { getDateTime } from "./utils";
5
3
  const defaultExportScale = EXPORT_SCALES.includes(devicePixelRatio)
6
4
  ? devicePixelRatio
7
5
  : 1;
@@ -52,7 +50,7 @@ export const getDefaultAppState = () => {
52
50
  isRotating: false,
53
51
  lastPointerDownWith: "mouse",
54
52
  multiElement: null,
55
- name: `${t("labels.untitled")}-${getDateTime()}`,
53
+ name: null,
56
54
  contextMenu: null,
57
55
  openMenu: null,
58
56
  openPopup: null,
@@ -4,8 +4,7 @@ import { isFrameLikeElement, isInitializedImageElement, } from "./element/typeCh
4
4
  import { deepCopyElement } from "./element/newElement";
5
5
  import { mutateElement } from "./element/mutateElement";
6
6
  import { getContainingFrame } from "./frame";
7
- import { isMemberOf, isPromiseLike } from "./utils";
8
- import { t } from "./i18n";
7
+ import { arrayToMap, isMemberOf, isPromiseLike } from "./utils";
9
8
  export const probablySupportsClipboardReadText = "clipboard" in navigator && "readText" in navigator.clipboard;
10
9
  export const probablySupportsClipboardWriteText = "clipboard" in navigator && "writeText" in navigator.clipboard;
11
10
  export const probablySupportsClipboardBlob = "clipboard" in navigator &&
@@ -61,6 +60,7 @@ export const createPasteEvent = ({ types, files, }) => {
61
60
  return event;
62
61
  };
63
62
  export const serializeAsClipboardJSON = ({ elements, files, }) => {
63
+ const elementsMap = arrayToMap(elements);
64
64
  const framesToCopy = new Set(elements.filter((element) => isFrameLikeElement(element)));
65
65
  let foundFile = false;
66
66
  const _files = elements.reduce((acc, element) => {
@@ -79,8 +79,8 @@ export const serializeAsClipboardJSON = ({ elements, files, }) => {
79
79
  const contents = {
80
80
  type: EXPORT_DATA_TYPES.excalidrawClipboard,
81
81
  elements: elements.map((element) => {
82
- if (getContainingFrame(element) &&
83
- !framesToCopy.has(getContainingFrame(element))) {
82
+ if (getContainingFrame(element, elementsMap) &&
83
+ !framesToCopy.has(getContainingFrame(element, elementsMap))) {
84
84
  const copiedElement = deepCopyElement(element);
85
85
  mutateElement(copiedElement, {
86
86
  frameId: null,
@@ -313,7 +313,7 @@ export const copyTextToSystemClipboard = async (text, clipboardEvent) => {
313
313
  }
314
314
  // (3) if that fails, use document.execCommand
315
315
  if (!copyTextViaExecCommand(text)) {
316
- throw new Error(t("errors.copyToSystemClipboardFailed"));
316
+ throw new Error("Error copying to clipboard.");
317
317
  }
318
318
  };
319
319
  // adapted from https://github.com/zenorocha/clipboard.js/blob/ce79f170aa655c408b6aab33c9472e8e4fa52e19/src/clipboard-action.js#L48
@@ -1,11 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import { ActionManager } from "../actions/manager";
3
- import { ExcalidrawElement } from "../element/types";
3
+ import { NonDeletedElementsMap, NonDeletedSceneElementsMap } from "../element/types";
4
4
  import { AppClassProperties, AppProps, UIAppState, Zoom } from "../types";
5
5
  import "./Actions.scss";
6
- export declare const SelectedShapeActions: ({ appState, elements, renderAction, }: {
6
+ export declare const SelectedShapeActions: ({ appState, elementsMap, renderAction, }: {
7
7
  appState: UIAppState;
8
- elements: readonly ExcalidrawElement[];
8
+ elementsMap: NonDeletedElementsMap | NonDeletedSceneElementsMap;
9
9
  renderAction: ActionManager["renderAction"];
10
10
  }) => JSX.Element;
11
11
  export declare const ShapesSwitcher: ({ activeTool, appState, app, UIOptions, }: {
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
- import { getNonDeletedElements } from "../element";
4
3
  import { t } from "../i18n";
5
4
  import { useDevice } from "./App";
6
5
  import { canChangeRoundness, canHaveArrowheads, getTargetElements, hasBackground, hasStrokeStyle, hasStrokeWidth, } from "../scene";
@@ -20,8 +19,8 @@ import DropdownMenu from "./dropdownMenu/DropdownMenu";
20
19
  import { EmbedIcon, extraToolsIcon, frameToolIcon, mermaidLogoIcon, laserPointerToolIcon, OpenAIIcon, MagicIcon, } from "./icons";
21
20
  import { KEYS } from "../keys";
22
21
  import { useTunnels } from "../context/tunnels";
23
- export const SelectedShapeActions = ({ appState, elements, renderAction, }) => {
24
- const targetElements = getTargetElements(getNonDeletedElements(elements), appState);
22
+ export const SelectedShapeActions = ({ appState, elementsMap, renderAction, }) => {
23
+ const targetElements = getTargetElements(elementsMap, appState);
25
24
  let isSingleElementBoundContainer = false;
26
25
  if (targetElements.length === 2 &&
27
26
  (hasBoundTextElement(targetElements[0]) ||
@@ -58,8 +57,8 @@ export const SelectedShapeActions = ({ appState, elements, renderAction, }) => {
58
57
  targetElements.some((element) => hasStrokeStyle(element.type))) && (_jsxs(_Fragment, { children: [renderAction("changeStrokeStyle"), renderAction("changeSloppiness")] })), (canChangeRoundness(appState.activeTool.type) ||
59
58
  targetElements.some((element) => canChangeRoundness(element.type))) && (_jsx(_Fragment, { children: renderAction("changeRoundness") })), (appState.activeTool.type === "text" ||
60
59
  targetElements.some(isTextElement)) && (_jsxs(_Fragment, { children: [renderAction("changeFontSize"), renderAction("changeFontFamily"), (appState.activeTool.type === "text" ||
61
- suppportsHorizontalAlign(targetElements)) &&
62
- renderAction("changeTextAlign")] })), shouldAllowVerticalAlign(targetElements) &&
60
+ suppportsHorizontalAlign(targetElements, elementsMap)) &&
61
+ renderAction("changeTextAlign")] })), shouldAllowVerticalAlign(targetElements, elementsMap) &&
63
62
  renderAction("changeVerticalAlign"), (canHaveArrowheads(appState.activeTool.type) ||
64
63
  targetElements.some((element) => canHaveArrowheads(element.type))) && (_jsx(_Fragment, { children: renderAction("changeArrowhead") })), renderAction("changeOpacity"), _jsxs("fieldset", { children: [_jsx("legend", { children: t("labels.layers") }), _jsxs("div", { className: "buttonList", children: [renderAction("sendToBack"), renderAction("sendBackward"), renderAction("bringToFront"), renderAction("bringForward")] })] }), targetElements.length > 1 && !isSingleElementBoundContainer && (_jsxs("fieldset", { children: [_jsx("legend", { children: t("labels.align") }), _jsxs("div", { className: "buttonList", children: [isRTL ? (_jsxs(_Fragment, { children: [renderAction("alignRight"), renderAction("alignHorizontallyCentered"), renderAction("alignLeft")] })) : (_jsxs(_Fragment, { children: [renderAction("alignLeft"), renderAction("alignHorizontallyCentered"), renderAction("alignRight")] })), targetElements.length > 2 &&
65
64
  renderAction("distributeHorizontally"), _jsx("div", { style: { flexBasis: "100%", height: 0 } }), _jsxs("div", { style: {
@@ -103,14 +102,26 @@ export const ShapesSwitcher = ({ activeTool, appState, app, UIOptions, }) => {
103
102
  app.setActiveTool({ type: value });
104
103
  }
105
104
  } }, value));
106
- }), _jsx("div", { className: "App-toolbar__divider" }), _jsxs(DropdownMenu, { open: isExtraToolsMenuOpen, children: [_jsx(DropdownMenu.Trigger, { className: clsx("App-toolbar__extra-tools-trigger", {
105
+ }), _jsx("div", { className: "App-toolbar__divider" }), _jsxs(DropdownMenu, { open: isExtraToolsMenuOpen, children: [_jsxs(DropdownMenu.Trigger, { className: clsx("App-toolbar__extra-tools-trigger", {
107
106
  "App-toolbar__extra-tools-trigger--selected": frameToolSelected ||
108
107
  embeddableToolSelected ||
109
108
  // in collab we're already highlighting the laser button
110
109
  // outside toolbar, so let's not highlight extra-tools button
111
110
  // on top of it
112
111
  (laserToolSelected && !app.props.isCollaborating),
113
- }), onToggle: () => setIsExtraToolsMenuOpen(!isExtraToolsMenuOpen), title: t("toolBar.extraTools"), children: extraToolsIcon }), _jsxs(DropdownMenu.Content, { onClickOutside: () => setIsExtraToolsMenuOpen(false), onSelect: () => setIsExtraToolsMenuOpen(false), className: "App-toolbar__extra-tools-dropdown", children: [_jsx(DropdownMenu.Item, { onSelect: () => app.setActiveTool({ type: "frame" }), icon: frameToolIcon, shortcut: KEYS.F.toLocaleUpperCase(), "data-testid": "toolbar-frame", selected: frameToolSelected, children: t("toolBar.frame") }), _jsx(DropdownMenu.Item, { onSelect: () => app.setActiveTool({ type: "embeddable" }), icon: EmbedIcon, "data-testid": "toolbar-embeddable", selected: embeddableToolSelected, children: t("toolBar.embeddable") }), _jsx(DropdownMenu.Item, { onSelect: () => app.setActiveTool({ type: "laser" }), icon: laserPointerToolIcon, "data-testid": "toolbar-laser", selected: laserToolSelected, shortcut: KEYS.K.toLocaleUpperCase(), children: t("toolBar.laser") }), _jsx("div", { style: { margin: "6px 0", fontSize: 14, fontWeight: 600 }, children: "Generate" }), app.props.aiEnabled !== false && _jsx(TTDDialogTriggerTunnel.Out, {}), _jsx(DropdownMenu.Item, { onSelect: () => app.setOpenDialog({ name: "ttd", tab: "mermaid" }), icon: mermaidLogoIcon, "data-testid": "toolbar-embeddable", children: t("toolBar.mermaidToExcalidraw") }), app.props.aiEnabled !== false && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenu.Item, { onSelect: () => app.onMagicframeToolSelect(), icon: MagicIcon, "data-testid": "toolbar-magicframe", children: [t("toolBar.magicframe"), _jsx(DropdownMenu.Item.Badge, { children: "AI" })] }), _jsx(DropdownMenu.Item, { onSelect: () => {
112
+ }), onToggle: () => setIsExtraToolsMenuOpen(!isExtraToolsMenuOpen), title: t("toolBar.extraTools"), children: [extraToolsIcon, app.props.aiEnabled !== false && (_jsx("div", { style: {
113
+ display: "inline-flex",
114
+ marginLeft: "auto",
115
+ padding: "2px 4px",
116
+ borderRadius: 6,
117
+ fontSize: 8,
118
+ fontFamily: "Cascadia, monospace",
119
+ position: "absolute",
120
+ background: "pink",
121
+ color: "black",
122
+ bottom: 3,
123
+ right: 4,
124
+ }, children: "AI" }))] }), _jsxs(DropdownMenu.Content, { onClickOutside: () => setIsExtraToolsMenuOpen(false), onSelect: () => setIsExtraToolsMenuOpen(false), className: "App-toolbar__extra-tools-dropdown", children: [_jsx(DropdownMenu.Item, { onSelect: () => app.setActiveTool({ type: "frame" }), icon: frameToolIcon, shortcut: KEYS.F.toLocaleUpperCase(), "data-testid": "toolbar-frame", selected: frameToolSelected, children: t("toolBar.frame") }), _jsx(DropdownMenu.Item, { onSelect: () => app.setActiveTool({ type: "embeddable" }), icon: EmbedIcon, "data-testid": "toolbar-embeddable", selected: embeddableToolSelected, children: t("toolBar.embeddable") }), _jsx(DropdownMenu.Item, { onSelect: () => app.setActiveTool({ type: "laser" }), icon: laserPointerToolIcon, "data-testid": "toolbar-laser", selected: laserToolSelected, shortcut: KEYS.K.toLocaleUpperCase(), children: t("toolBar.laser") }), _jsx("div", { style: { margin: "6px 0", fontSize: 14, fontWeight: 600 }, children: "Generate" }), app.props.aiEnabled !== false && _jsx(TTDDialogTriggerTunnel.Out, {}), _jsx(DropdownMenu.Item, { onSelect: () => app.setOpenDialog({ name: "ttd", tab: "mermaid" }), icon: mermaidLogoIcon, "data-testid": "toolbar-embeddable", children: t("toolBar.mermaidToExcalidraw") }), app.props.aiEnabled !== false && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenu.Item, { onSelect: () => app.onMagicframeToolSelect(), icon: MagicIcon, "data-testid": "toolbar-magicframe", children: [t("toolBar.magicframe"), _jsx(DropdownMenu.Item.Badge, { children: "AI" })] }), _jsx(DropdownMenu.Item, { onSelect: () => {
114
125
  trackEvent("ai", "open-settings", "d2c");
115
126
  app.setOpenDialog({
116
127
  name: "settings",
@@ -4,14 +4,16 @@ import { ActionManager } from "../actions/manager";
4
4
  import { EXPORT_IMAGE_TYPES } from "../constants";
5
5
  import { ExportedElements } from "../data";
6
6
  import { LinearElementEditor } from "../element/linearElementEditor";
7
- import { ExcalidrawElement, NonDeleted, NonDeletedExcalidrawElement, ExcalidrawFrameLikeElement, ExcalidrawIframeElement } from "../element/types";
7
+ import { ExcalidrawElement, NonDeleted, NonDeletedExcalidrawElement, ExcalidrawFrameLikeElement, ExcalidrawIframeElement, ExcalidrawEmbeddableElement } from "../element/types";
8
8
  import History from "../history";
9
9
  import Scene from "../scene/Scene";
10
10
  import { AppClassProperties, AppProps, AppState, ExcalidrawImperativeAPI, BinaryFiles, LibraryItems, SceneData, Device, FrameNameBoundsCache, SidebarName, SidebarTabName, ToolType, OnUserFollowedPayload } from "../types";
11
11
  import { FileSystemHandle } from "../data/filesystem";
12
12
  import { Renderer } from "../scene/Renderer";
13
- import { LaserPathManager } from "./LaserTool/LaserPathManager";
14
13
  import { Emitter } from "../emitter";
14
+ import { AnimationFrameHandler } from "../animation-frame-handler";
15
+ import { AnimatedTrail } from "../animated-trail";
16
+ import { LaserTrails } from "../laser-trails";
15
17
  export declare const ExcalidrawContainerContext: React.Context<{
16
18
  container: HTMLDivElement | null;
17
19
  id: string | null;
@@ -58,6 +60,17 @@ declare class App extends React.Component<AppProps, AppState> {
58
60
  files: BinaryFiles;
59
61
  imageCache: AppClassProperties["imageCache"];
60
62
  private iFrameRefs;
63
+ /**
64
+ * Indicates whether the embeddable's url has been validated for rendering.
65
+ * If value not set, indicates that the validation is pending.
66
+ * Initially or on url change the flag is not reset so that we can guarantee
67
+ * the validation came from a trusted source (the editor).
68
+ **/
69
+ private embedsValidationStatus;
70
+ /** embeds that have been inserted to DOM (as a perf optim, we don't want to
71
+ * insert to DOM before user initially scrolls to them) */
72
+ private initializedEmbeds;
73
+ private elementsPendingErasure;
61
74
  hitLinkElement?: NonDeletedExcalidrawElement;
62
75
  lastPointerDownEvent: React.PointerEvent<HTMLElement> | null;
63
76
  lastPointerUpEvent: React.PointerEvent<HTMLElement> | PointerEvent | null;
@@ -66,7 +79,9 @@ declare class App extends React.Component<AppProps, AppState> {
66
79
  x: number;
67
80
  y: number;
68
81
  };
69
- laserPathManager: LaserPathManager;
82
+ animationFrameHandler: AnimationFrameHandler;
83
+ laserTrails: LaserTrails;
84
+ eraserTrail: AnimatedTrail;
70
85
  onChangeEmitter: Emitter<[elements: readonly ExcalidrawElement[], appState: AppState, files: BinaryFiles]>;
71
86
  onPointerDownEmitter: Emitter<[activeTool: {
72
87
  lastActiveTool: import("../types").ActiveTool | null;
@@ -131,12 +146,6 @@ declare class App extends React.Component<AppProps, AppState> {
131
146
  boxSelection: {
132
147
  hasOccurred: boolean;
133
148
  };
134
- elementIdsToErase: {
135
- [key: string]: {
136
- opacity: number;
137
- erase: boolean;
138
- };
139
- };
140
149
  }>, event: React.PointerEvent<HTMLElement>]>;
141
150
  onPointerUpEmitter: Emitter<[activeTool: {
142
151
  lastActiveTool: import("../types").ActiveTool | null;
@@ -201,12 +210,6 @@ declare class App extends React.Component<AppProps, AppState> {
201
210
  boxSelection: {
202
211
  hasOccurred: boolean;
203
212
  };
204
- elementIdsToErase: {
205
- [key: string]: {
206
- opacity: number;
207
- erase: boolean;
208
- };
209
- };
210
213
  }>, event: PointerEvent]>;
211
214
  onUserFollowEmitter: Emitter<[payload: OnUserFollowedPayload]>;
212
215
  onScrollChangeEmitter: Emitter<[scrollX: number, scrollY: number, zoom: Readonly<{
@@ -220,11 +223,13 @@ declare class App extends React.Component<AppProps, AppState> {
220
223
  private getHTMLIFrameElement;
221
224
  private handleEmbeddableCenterClick;
222
225
  private isIframeLikeElementCenter;
226
+ private updateEmbedValidationStatus;
223
227
  private updateEmbeddables;
224
228
  private renderEmbeddables;
225
229
  private getFrameNameDOMId;
226
230
  frameNameBoundsCache: FrameNameBoundsCache;
227
231
  private renderFrameNames;
232
+ private toggleOverscrollBehavior;
228
233
  render(): JSX.Element;
229
234
  focusContainer: AppClassProperties["focusContainer"];
230
235
  getSceneElementsIncludingDeleted: () => readonly ExcalidrawElement[];
@@ -370,6 +375,7 @@ declare class App extends React.Component<AppProps, AppState> {
370
375
  * GestureEvent is standardized.
371
376
  */
372
377
  private isTouchScreenMultiTouchGesture;
378
+ getName: () => string;
373
379
  private onGestureStart;
374
380
  private onGestureChange;
375
381
  private onGestureEnd;
@@ -420,7 +426,7 @@ declare class App extends React.Component<AppProps, AppState> {
420
426
  sceneX: number;
421
427
  sceneY: number;
422
428
  link: string;
423
- }) => NonDeleted<import("../element/types").ExcalidrawEmbeddableElement> | undefined;
429
+ }) => NonDeleted<ExcalidrawEmbeddableElement> | undefined;
424
430
  private createImageElement;
425
431
  private handleLinearElementOnPointerDown;
426
432
  private getCurrentItemRoundness;
@@ -483,4 +489,5 @@ declare global {
483
489
  };
484
490
  }
485
491
  }
492
+ export declare const createTestHook: () => void;
486
493
  export default App;