@excalidraw/excalidraw 0.17.1-7500-ac247a0 → 0.17.1-b7babe5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -2
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-2W5GQUR4.js → chunk-6NMK7JTV.js} +13 -6
- package/dist/browser/dev/excalidraw-assets-dev/chunk-6NMK7JTV.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/chunk-CX3RATXT.js +20324 -0
- package/dist/browser/dev/excalidraw-assets-dev/chunk-CX3RATXT.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{en-OC6JWP3X.js → en-BZY7JRTM.js} +4 -2
- package/dist/browser/dev/excalidraw-assets-dev/{image-5TVMINCA.js → image-CVN3YKRW.js} +2 -4
- package/dist/browser/dev/excalidraw-assets-dev/image-LK4UNFRZ.css +6 -0
- package/dist/browser/dev/excalidraw-assets-dev/image-LK4UNFRZ.css.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/roundRect-T5BX56ZF.js +161 -0
- package/dist/browser/dev/excalidraw-assets-dev/roundRect-T5BX56ZF.js.map +7 -0
- package/dist/browser/dev/index.css +189 -129
- package/dist/browser/dev/index.css.map +3 -3
- package/dist/browser/dev/index.js +34964 -37
- package/dist/browser/dev/index.js.map +4 -4
- package/dist/browser/prod/excalidraw-assets/chunk-VJAIK3AX.js +55 -0
- package/dist/browser/prod/excalidraw-assets/chunk-YYO5DFUW.js +11 -0
- package/dist/browser/prod/excalidraw-assets/en-O2YCQM2W.js +1 -0
- package/dist/browser/prod/excalidraw-assets/image-6FKY54X5.js +1 -0
- package/dist/browser/prod/excalidraw-assets/image-X66R2EM5.css +1 -0
- package/dist/browser/prod/excalidraw-assets/roundRect-2ACQK4DA.js +1 -0
- package/dist/browser/prod/index.css +1 -1
- package/dist/browser/prod/index.js +203 -1
- package/dist/{prod/en-RLIAOBCI.json → dev/en-EY7E2L5O.json} +10 -5
- package/dist/dev/index.css +189 -129
- package/dist/dev/index.css.map +3 -3
- package/dist/dev/index.js +38702 -39409
- package/dist/dev/index.js.map +4 -4
- package/dist/excalidraw/actions/actionAddToLibrary.d.ts +15 -15
- package/dist/excalidraw/actions/actionAlign.d.ts +6 -6
- package/dist/excalidraw/actions/actionAlign.js +2 -1
- package/dist/excalidraw/actions/actionBoundText.d.ts +10 -10
- package/dist/excalidraw/actions/actionBoundText.js +8 -8
- package/dist/excalidraw/actions/actionCanvas.d.ts +58 -58
- package/dist/excalidraw/actions/actionClipboard.d.ts +34 -34
- package/dist/excalidraw/actions/actionClipboard.js +9 -2
- package/dist/excalidraw/actions/actionDeleteSelected.d.ts +15 -15
- package/dist/excalidraw/actions/actionDeleteSelected.js +3 -2
- package/dist/excalidraw/actions/actionDistribute.d.ts +2 -2
- package/dist/excalidraw/actions/actionDistribute.js +1 -1
- package/dist/excalidraw/actions/actionDuplicateSelection.d.ts +1 -1
- package/dist/excalidraw/actions/actionDuplicateSelection.js +4 -3
- package/dist/excalidraw/actions/actionElementLock.d.ts +10 -10
- package/dist/excalidraw/actions/actionExport.d.ts +43 -43
- package/dist/excalidraw/actions/actionExport.js +4 -4
- package/dist/excalidraw/actions/actionFinalize.d.ts +9 -9
- package/dist/excalidraw/actions/actionFinalize.js +7 -6
- package/dist/excalidraw/actions/actionFlip.d.ts +2 -2
- package/dist/excalidraw/actions/actionFlip.js +11 -11
- package/dist/excalidraw/actions/actionFrame.d.ts +16 -16
- package/dist/excalidraw/actions/actionFrame.js +1 -1
- package/dist/excalidraw/actions/actionGroup.d.ts +10 -10
- package/dist/excalidraw/actions/actionGroup.js +3 -2
- package/dist/excalidraw/actions/actionLinearEditor.d.ts +5 -5
- package/dist/excalidraw/actions/actionLinearEditor.js +1 -1
- package/dist/excalidraw/{element/Hyperlink.d.ts → actions/actionLink.d.ts} +29 -51
- package/dist/excalidraw/actions/actionLink.js +40 -0
- package/dist/excalidraw/actions/actionMenu.d.ts +13 -13
- package/dist/excalidraw/actions/actionNavigate.d.ts +10 -10
- package/dist/excalidraw/actions/actionNavigate.js +1 -1
- package/dist/excalidraw/actions/actionProperties.d.ts +77 -77
- package/dist/excalidraw/actions/actionProperties.js +32 -27
- package/dist/excalidraw/actions/actionSelectAll.d.ts +5 -5
- package/dist/excalidraw/actions/actionSelectAll.js +1 -1
- package/dist/excalidraw/actions/actionStyles.d.ts +7 -7
- package/dist/excalidraw/actions/actionStyles.js +4 -4
- package/dist/excalidraw/actions/actionToggleGridMode.d.ts +5 -5
- package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +5 -5
- package/dist/excalidraw/actions/actionToggleStats.d.ts +5 -5
- package/dist/excalidraw/actions/actionToggleViewMode.d.ts +5 -5
- package/dist/excalidraw/actions/actionToggleZenMode.d.ts +5 -5
- package/dist/excalidraw/actions/index.d.ts +1 -1
- package/dist/excalidraw/actions/index.js +1 -1
- package/dist/excalidraw/actions/manager.js +2 -1
- package/dist/excalidraw/align.d.ts +2 -2
- package/dist/excalidraw/align.js +2 -2
- package/dist/excalidraw/animated-trail.d.ts +33 -0
- package/dist/excalidraw/animated-trail.js +96 -0
- package/dist/excalidraw/animation-frame-handler.d.ts +16 -0
- package/dist/excalidraw/animation-frame-handler.js +55 -0
- package/dist/excalidraw/appState.d.ts +1 -1
- package/dist/excalidraw/appState.js +1 -3
- package/dist/excalidraw/clipboard.js +5 -5
- package/dist/excalidraw/components/Actions.d.ts +3 -3
- package/dist/excalidraw/components/Actions.js +18 -7
- package/dist/excalidraw/components/App.d.ts +23 -16
- package/dist/excalidraw/components/App.js +387 -272
- package/dist/excalidraw/components/Button.d.ts +1 -1
- package/dist/excalidraw/components/FilledButton.d.ts +2 -2
- package/dist/excalidraw/components/FilledButton.js +27 -3
- package/dist/excalidraw/components/FollowMode/FollowMode.js +1 -1
- package/dist/excalidraw/components/ImageExportDialog.d.ts +2 -1
- package/dist/excalidraw/components/ImageExportDialog.js +17 -13
- package/dist/excalidraw/components/JSONExportDialog.js +1 -1
- package/dist/excalidraw/components/{LaserTool/LaserPointerButton.d.ts → LaserPointerButton.d.ts} +1 -1
- package/dist/excalidraw/components/{LaserTool/LaserPointerButton.js → LaserPointerButton.js} +2 -2
- package/dist/excalidraw/components/LayerUI.js +3 -3
- package/dist/excalidraw/components/MobileMenu.js +1 -1
- package/dist/excalidraw/components/ProjectName.d.ts +0 -1
- package/dist/excalidraw/components/ProjectName.js +1 -1
- package/dist/excalidraw/components/PublishLibrary.js +1 -1
- package/dist/excalidraw/components/SVGLayer.d.ts +8 -0
- package/dist/excalidraw/components/SVGLayer.js +20 -0
- package/dist/excalidraw/components/ShareableLinkDialog.js +10 -10
- package/dist/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
- package/dist/excalidraw/components/Stack.d.ts +2 -2
- package/dist/excalidraw/components/TTDDialog/common.js +10 -1
- package/dist/excalidraw/components/TextField.d.ts +5 -2
- package/dist/excalidraw/components/TextField.js +6 -3
- package/dist/excalidraw/components/Toast.d.ts +3 -2
- package/dist/excalidraw/components/Toast.js +2 -2
- package/dist/excalidraw/components/ToolButton.js +2 -1
- package/dist/excalidraw/components/canvases/InteractiveCanvas.d.ts +2 -2
- package/dist/excalidraw/components/canvases/InteractiveCanvas.js +6 -5
- package/dist/excalidraw/components/canvases/StaticCanvas.d.ts +4 -3
- package/dist/excalidraw/components/canvases/StaticCanvas.js +7 -5
- package/dist/excalidraw/components/dropdownMenu/DropdownMenuContent.js +22 -2
- package/dist/excalidraw/components/hyperlink/Hyperlink.d.ts +19 -0
- package/dist/excalidraw/{element → components/hyperlink}/Hyperlink.js +40 -115
- package/dist/excalidraw/components/hyperlink/helpers.d.ts +7 -0
- package/dist/excalidraw/components/hyperlink/helpers.js +49 -0
- package/dist/excalidraw/components/icons.d.ts +2 -1
- package/dist/excalidraw/components/icons.js +2 -1
- package/dist/excalidraw/components/live-collaboration/LiveCollaborationTrigger.js +3 -2
- package/dist/excalidraw/components/main-menu/DefaultItems.js +5 -2
- package/dist/excalidraw/constants.d.ts +6 -0
- package/dist/excalidraw/constants.js +6 -0
- package/dist/excalidraw/data/blob.js +13 -14
- package/dist/excalidraw/data/filesystem.d.ts +1 -1
- package/dist/excalidraw/data/index.d.ts +2 -1
- package/dist/excalidraw/data/index.js +20 -16
- package/dist/excalidraw/data/json.d.ts +1 -1
- package/dist/excalidraw/data/json.js +5 -3
- package/dist/excalidraw/data/library.d.ts +60 -8
- package/dist/excalidraw/data/library.js +302 -33
- package/dist/excalidraw/data/resave.d.ts +1 -1
- package/dist/excalidraw/data/resave.js +2 -2
- package/dist/excalidraw/data/restore.js +8 -13
- package/dist/excalidraw/data/transform.js +13 -9
- package/dist/excalidraw/distribute.d.ts +2 -2
- package/dist/excalidraw/distribute.js +2 -2
- package/dist/excalidraw/element/ElementCanvasButtons.d.ts +3 -2
- package/dist/excalidraw/element/ElementCanvasButtons.js +4 -4
- package/dist/excalidraw/element/binding.d.ts +9 -9
- package/dist/excalidraw/element/binding.js +61 -59
- package/dist/excalidraw/element/bounds.d.ts +5 -5
- package/dist/excalidraw/element/bounds.js +29 -32
- package/dist/excalidraw/element/collision.d.ts +11 -11
- package/dist/excalidraw/element/collision.js +49 -46
- package/dist/excalidraw/element/containerCache.d.ts +11 -0
- package/dist/excalidraw/element/containerCache.js +14 -0
- package/dist/excalidraw/element/dragElements.js +10 -19
- package/dist/excalidraw/element/embeddable.d.ts +12 -13
- package/dist/excalidraw/element/embeddable.js +17 -27
- package/dist/excalidraw/element/image.js +1 -2
- package/dist/excalidraw/element/index.d.ts +8 -1
- package/dist/excalidraw/element/index.js +23 -1
- package/dist/excalidraw/element/linearElementEditor.d.ts +36 -36
- package/dist/excalidraw/element/linearElementEditor.js +79 -80
- package/dist/excalidraw/element/newElement.d.ts +4 -6
- package/dist/excalidraw/element/newElement.js +11 -16
- package/dist/excalidraw/element/resizeElements.d.ts +6 -6
- package/dist/excalidraw/element/resizeElements.js +40 -46
- package/dist/excalidraw/element/resizeTest.d.ts +3 -3
- package/dist/excalidraw/element/resizeTest.js +4 -4
- package/dist/excalidraw/element/sizeHelpers.d.ts +2 -2
- package/dist/excalidraw/element/sizeHelpers.js +2 -2
- package/dist/excalidraw/element/textElement.d.ts +34 -21
- package/dist/excalidraw/element/textElement.js +87 -111
- package/dist/excalidraw/element/textWysiwyg.d.ts +1 -6
- package/dist/excalidraw/element/textWysiwyg.js +15 -37
- package/dist/excalidraw/element/transformHandles.d.ts +4 -4
- package/dist/excalidraw/element/transformHandles.js +6 -6
- package/dist/excalidraw/element/typeChecks.js +4 -1
- package/dist/excalidraw/element/types.d.ts +24 -11
- package/dist/excalidraw/frame.d.ts +26 -20
- package/dist/excalidraw/frame.js +157 -84
- package/dist/excalidraw/groups.d.ts +3 -3
- package/dist/excalidraw/groups.js +11 -3
- package/dist/excalidraw/history.d.ts +1 -1
- package/dist/excalidraw/hooks/useLibraryItemSvg.js +1 -1
- package/dist/excalidraw/index.d.ts +9 -10
- package/dist/excalidraw/index.js +16 -12
- package/dist/excalidraw/laser-trails.d.ts +19 -0
- package/dist/excalidraw/laser-trails.js +95 -0
- package/dist/excalidraw/locales/en.json +10 -5
- package/dist/excalidraw/queue.d.ts +9 -0
- package/dist/excalidraw/queue.js +27 -0
- package/dist/excalidraw/reactUtils.d.ts +14 -0
- package/dist/excalidraw/reactUtils.js +45 -0
- package/dist/excalidraw/renderer/helpers.d.ts +13 -0
- package/dist/excalidraw/renderer/helpers.js +39 -0
- package/dist/excalidraw/renderer/interactiveScene.d.ts +20 -0
- package/dist/excalidraw/renderer/{renderScene.js → interactiveScene.js} +199 -474
- package/dist/excalidraw/renderer/renderElement.d.ts +6 -6
- package/dist/excalidraw/renderer/renderElement.js +54 -366
- package/dist/excalidraw/renderer/staticScene.d.ts +11 -0
- package/dist/excalidraw/renderer/staticScene.js +205 -0
- package/dist/excalidraw/renderer/staticSvgScene.d.ts +5 -0
- package/dist/excalidraw/renderer/staticSvgScene.js +385 -0
- package/dist/excalidraw/scene/Fonts.js +2 -1
- package/dist/excalidraw/scene/Renderer.d.ts +1 -1
- package/dist/excalidraw/scene/Renderer.js +32 -20
- package/dist/excalidraw/scene/Scene.d.ts +10 -9
- package/dist/excalidraw/scene/Scene.js +45 -21
- package/dist/excalidraw/scene/Shape.d.ts +3 -1
- package/dist/excalidraw/scene/Shape.js +7 -5
- package/dist/excalidraw/scene/ShapeCache.d.ts +2 -1
- package/dist/excalidraw/scene/ShapeCache.js +1 -0
- package/dist/excalidraw/scene/comparisons.js +2 -1
- package/dist/excalidraw/scene/export.d.ts +3 -0
- package/dist/excalidraw/scene/export.js +20 -40
- package/dist/excalidraw/scene/index.d.ts +0 -1
- package/dist/excalidraw/scene/index.js +0 -1
- package/dist/excalidraw/scene/scrollbars.d.ts +1 -1
- package/dist/excalidraw/scene/scrollbars.js +1 -1
- package/dist/excalidraw/scene/selection.d.ts +5 -5
- package/dist/excalidraw/scene/selection.js +16 -14
- package/dist/excalidraw/scene/types.d.ts +11 -5
- package/dist/excalidraw/snapping.d.ts +7 -7
- package/dist/excalidraw/snapping.js +21 -20
- package/dist/excalidraw/types.d.ts +16 -17
- package/dist/excalidraw/utility-types.d.ts +7 -0
- package/dist/excalidraw/utils.d.ts +21 -16
- package/dist/excalidraw/utils.js +43 -45
- package/dist/{dev/en-RLIAOBCI.json → prod/en-EY7E2L5O.json} +10 -5
- package/dist/prod/index.css +1 -1
- package/dist/prod/index.js +42 -42
- package/dist/utils/bbox.d.ts +2 -2
- package/dist/utils/export.d.ts +3 -3
- package/dist/utils/export.js +3 -13
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +2 -2
- package/dist/utils/withinBounds.d.ts +1 -1
- package/dist/utils/withinBounds.js +5 -2
- package/package.json +4 -4
- package/dist/browser/dev/excalidraw-assets-dev/chunk-2W5GQUR4.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/chunk-KGZXLFLR.js +0 -53497
- package/dist/browser/dev/excalidraw-assets-dev/chunk-KGZXLFLR.js.map +0 -7
- package/dist/browser/dev/excalidraw-assets-dev/image-3MFRCKYM.css +0 -5797
- package/dist/browser/dev/excalidraw-assets-dev/image-3MFRCKYM.css.map +0 -7
- package/dist/browser/prod/excalidraw-assets/chunk-4YN2HN3S.js +0 -257
- package/dist/browser/prod/excalidraw-assets/chunk-OWLL6VOG.js +0 -11
- package/dist/browser/prod/excalidraw-assets/en-ERQOR3OC.js +0 -1
- package/dist/browser/prod/excalidraw-assets/image-LTLHTTSE.js +0 -1
- package/dist/browser/prod/excalidraw-assets/image-QBL334OA.css +0 -1
- package/dist/excalidraw/components/LaserTool/LaserPathManager.d.ts +0 -28
- package/dist/excalidraw/components/LaserTool/LaserPathManager.js +0 -225
- package/dist/excalidraw/components/LaserTool/LaserTool.d.ts +0 -8
- package/dist/excalidraw/components/LaserTool/LaserTool.js +0 -15
- package/dist/excalidraw/renderer/renderScene.d.ts +0 -25
- package/dist/excalidraw/vite.config.d.mts +0 -2
- package/dist/excalidraw/vite.config.mjs +0 -13
- /package/dist/browser/dev/excalidraw-assets-dev/{en-OC6JWP3X.js.map → en-BZY7JRTM.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{image-5TVMINCA.js.map → image-CVN3YKRW.js.map} +0 -0
|
@@ -1,50 +1,61 @@
|
|
|
1
1
|
import { isElementInViewport } from "../element/sizeHelpers";
|
|
2
2
|
import { isImageElement } from "../element/typeChecks";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { renderInteractiveSceneThrottled } from "../renderer/interactiveScene";
|
|
4
|
+
import { renderStaticSceneThrottled } from "../renderer/staticScene";
|
|
5
|
+
import { memoize, toBrandedType } from "../utils";
|
|
5
6
|
export class Renderer {
|
|
6
7
|
scene;
|
|
7
8
|
constructor(scene) {
|
|
8
9
|
this.scene = scene;
|
|
9
10
|
}
|
|
10
11
|
getRenderableElements = (() => {
|
|
11
|
-
const getVisibleCanvasElements = ({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
const getVisibleCanvasElements = ({ elementsMap, zoom, offsetLeft, offsetTop, scrollX, scrollY, height, width, }) => {
|
|
13
|
+
const visibleElements = [];
|
|
14
|
+
for (const element of elementsMap.values()) {
|
|
15
|
+
if (isElementInViewport(element, width, height, {
|
|
16
|
+
zoom,
|
|
17
|
+
offsetLeft,
|
|
18
|
+
offsetTop,
|
|
19
|
+
scrollX,
|
|
20
|
+
scrollY,
|
|
21
|
+
}, elementsMap)) {
|
|
22
|
+
visibleElements.push(element);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return visibleElements;
|
|
19
26
|
};
|
|
20
|
-
const
|
|
21
|
-
|
|
27
|
+
const getRenderableElements = ({ elements, editingElement, pendingImageElementId, }) => {
|
|
28
|
+
const elementsMap = toBrandedType(new Map());
|
|
29
|
+
for (const element of elements) {
|
|
22
30
|
if (isImageElement(element)) {
|
|
23
31
|
if (
|
|
24
32
|
// => not placed on canvas yet (but in elements array)
|
|
25
33
|
pendingImageElementId === element.id) {
|
|
26
|
-
|
|
34
|
+
continue;
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
37
|
// we don't want to render text element that's being currently edited
|
|
30
38
|
// (it's rendered on remote only)
|
|
31
|
-
|
|
39
|
+
if (!editingElement ||
|
|
32
40
|
editingElement.type !== "text" ||
|
|
33
|
-
element.id !== editingElement.id)
|
|
34
|
-
|
|
41
|
+
element.id !== editingElement.id) {
|
|
42
|
+
elementsMap.set(element.id, element);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return elementsMap;
|
|
35
46
|
};
|
|
36
47
|
return memoize(({ zoom, offsetLeft, offsetTop, scrollX, scrollY, height, width, editingElement, pendingImageElementId,
|
|
37
48
|
// unused but serves we cache on it to invalidate elements if they
|
|
38
49
|
// get mutated
|
|
39
50
|
versionNonce: _versionNonce, }) => {
|
|
40
51
|
const elements = this.scene.getNonDeletedElements();
|
|
41
|
-
const
|
|
52
|
+
const elementsMap = getRenderableElements({
|
|
42
53
|
elements,
|
|
43
54
|
editingElement,
|
|
44
55
|
pendingImageElementId,
|
|
45
56
|
});
|
|
46
57
|
const visibleElements = getVisibleCanvasElements({
|
|
47
|
-
|
|
58
|
+
elementsMap,
|
|
48
59
|
zoom,
|
|
49
60
|
offsetLeft,
|
|
50
61
|
offsetTop,
|
|
@@ -53,13 +64,14 @@ export class Renderer {
|
|
|
53
64
|
height,
|
|
54
65
|
width,
|
|
55
66
|
});
|
|
56
|
-
return {
|
|
67
|
+
return { elementsMap, visibleElements };
|
|
57
68
|
});
|
|
58
69
|
})();
|
|
59
70
|
// NOTE Doesn't destroy everything (scene, rc, etc.) because it may not be
|
|
60
71
|
// safe to break TS contract here (for upstream cases)
|
|
61
72
|
destroy() {
|
|
62
|
-
|
|
73
|
+
renderInteractiveSceneThrottled.cancel();
|
|
74
|
+
renderStaticSceneThrottled.cancel();
|
|
63
75
|
this.getRenderableElements.clear();
|
|
64
76
|
}
|
|
65
77
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExcalidrawElement, NonDeletedExcalidrawElement, NonDeleted, ExcalidrawFrameLikeElement } from "../element/types";
|
|
1
|
+
import { ExcalidrawElement, NonDeletedExcalidrawElement, NonDeleted, ExcalidrawFrameLikeElement, ElementsMapOrArray } from "../element/types";
|
|
2
2
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
|
3
3
|
import { AppState } from "../types";
|
|
4
4
|
type ElementIdKey = InstanceType<typeof LinearElementEditor>["elementId"];
|
|
@@ -9,21 +9,19 @@ export type ExcalidrawElementsIncludingDeleted = readonly ExcalidrawElement[];
|
|
|
9
9
|
declare class Scene {
|
|
10
10
|
private static sceneMapByElement;
|
|
11
11
|
private static sceneMapById;
|
|
12
|
-
static mapElementToScene(elementKey: ElementKey, scene: Scene
|
|
13
|
-
/**
|
|
14
|
-
* needed because of frame exporting hack.
|
|
15
|
-
* elementId:Scene mapping will be removed completely, soon.
|
|
16
|
-
*/
|
|
17
|
-
mapElementIds?: boolean): void;
|
|
12
|
+
static mapElementToScene(elementKey: ElementKey, scene: Scene): void;
|
|
18
13
|
static getScene(elementKey: ElementKey): Scene | null;
|
|
19
14
|
private callbacks;
|
|
20
15
|
private nonDeletedElements;
|
|
16
|
+
private nonDeletedElementsMap;
|
|
21
17
|
private elements;
|
|
22
18
|
private nonDeletedFramesLikes;
|
|
23
19
|
private frames;
|
|
24
20
|
private elementsMap;
|
|
25
21
|
private selectedElementsCache;
|
|
26
22
|
private versionNonce;
|
|
23
|
+
getElementsMapIncludingDeleted(): Map<string, ExcalidrawElement> & import("../utility-types").MakeBrand<"SceneElementsMap">;
|
|
24
|
+
getNonDeletedElementsMap(): Map<string, NonDeletedExcalidrawElement> & import("../utility-types").MakeBrand<"NonDeletedSceneElementsMap">;
|
|
27
25
|
getElementsIncludingDeleted(): readonly ExcalidrawElement[];
|
|
28
26
|
getNonDeletedElements(): readonly NonDeletedExcalidrawElement[];
|
|
29
27
|
getFramesIncludingDeleted(): readonly ExcalidrawFrameLikeElement[];
|
|
@@ -34,7 +32,7 @@ declare class Scene {
|
|
|
34
32
|
* scene state. This in effect will likely result in cache-miss, and
|
|
35
33
|
* the cache won't be updated in this case.
|
|
36
34
|
*/
|
|
37
|
-
elements?:
|
|
35
|
+
elements?: ElementsMapOrArray;
|
|
38
36
|
includeBoundTextElement?: boolean;
|
|
39
37
|
includeElementsInFrames?: boolean;
|
|
40
38
|
}): NonDeleted<ExcalidrawElement>[];
|
|
@@ -55,7 +53,7 @@ declare class Scene {
|
|
|
55
53
|
* @returns whether a change was made
|
|
56
54
|
*/
|
|
57
55
|
mapElements(iteratee: (element: ExcalidrawElement) => ExcalidrawElement): boolean;
|
|
58
|
-
replaceAllElements(nextElements:
|
|
56
|
+
replaceAllElements(nextElements: ElementsMapOrArray): void;
|
|
59
57
|
informMutation(): void;
|
|
60
58
|
addCallback(cb: SceneStateCallback): SceneStateCallbackRemover;
|
|
61
59
|
destroy(): void;
|
|
@@ -63,5 +61,8 @@ declare class Scene {
|
|
|
63
61
|
insertElementsAtIndex(elements: ExcalidrawElement[], index: number): void;
|
|
64
62
|
addNewElement: (element: ExcalidrawElement) => void;
|
|
65
63
|
getElementIndex(elementId: string): number;
|
|
64
|
+
getContainerElement: (element: (ExcalidrawElement & {
|
|
65
|
+
containerId: ExcalidrawElement["id"] | null;
|
|
66
|
+
}) | null) => ExcalidrawElement | null;
|
|
66
67
|
}
|
|
67
68
|
export default Scene;
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isNonDeletedElement } from "../element";
|
|
2
2
|
import { isFrameLikeElement } from "../element/typeChecks";
|
|
3
3
|
import { getSelectedElements } from "./selection";
|
|
4
4
|
import { randomInteger } from "../random";
|
|
5
|
+
import { toBrandedType } from "../utils";
|
|
6
|
+
const getNonDeletedElements = (allElements) => {
|
|
7
|
+
const elementsMap = new Map();
|
|
8
|
+
const elements = [];
|
|
9
|
+
for (const element of allElements) {
|
|
10
|
+
if (!element.isDeleted) {
|
|
11
|
+
elements.push(element);
|
|
12
|
+
elementsMap.set(element.id, element);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return { elementsMap, elements };
|
|
16
|
+
};
|
|
5
17
|
const hashSelectionOpts = (opts) => {
|
|
6
18
|
const keys = ["includeBoundTextElement", "includeElementsInFrames"];
|
|
7
19
|
let hash = "";
|
|
@@ -22,27 +34,17 @@ class Scene {
|
|
|
22
34
|
// ---------------------------------------------------------------------------
|
|
23
35
|
static sceneMapByElement = new WeakMap();
|
|
24
36
|
static sceneMapById = new Map();
|
|
25
|
-
static mapElementToScene(elementKey, scene
|
|
26
|
-
/**
|
|
27
|
-
* needed because of frame exporting hack.
|
|
28
|
-
* elementId:Scene mapping will be removed completely, soon.
|
|
29
|
-
*/
|
|
30
|
-
mapElementIds = true) {
|
|
37
|
+
static mapElementToScene(elementKey, scene) {
|
|
31
38
|
if (isIdKey(elementKey)) {
|
|
32
|
-
if (!mapElementIds) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
39
|
// for cases where we don't have access to the element object
|
|
36
40
|
// (e.g. restore serialized appState with id references)
|
|
37
41
|
this.sceneMapById.set(elementKey, scene);
|
|
38
42
|
}
|
|
39
43
|
else {
|
|
40
44
|
this.sceneMapByElement.set(elementKey, scene);
|
|
41
|
-
if
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
this.sceneMapById.set(elementKey.id, scene);
|
|
45
|
-
}
|
|
45
|
+
// if mapping element objects, also cache the id string when later
|
|
46
|
+
// looking up by id alone
|
|
47
|
+
this.sceneMapById.set(elementKey.id, scene);
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
static getScene(elementKey) {
|
|
@@ -56,16 +58,23 @@ class Scene {
|
|
|
56
58
|
// ---------------------------------------------------------------------------
|
|
57
59
|
callbacks = new Set();
|
|
58
60
|
nonDeletedElements = [];
|
|
61
|
+
nonDeletedElementsMap = toBrandedType(new Map());
|
|
59
62
|
elements = [];
|
|
60
63
|
nonDeletedFramesLikes = [];
|
|
61
64
|
frames = [];
|
|
62
|
-
elementsMap = new Map();
|
|
65
|
+
elementsMap = toBrandedType(new Map());
|
|
63
66
|
selectedElementsCache = {
|
|
64
67
|
selectedElementIds: null,
|
|
65
68
|
elements: null,
|
|
66
69
|
cache: new Map(),
|
|
67
70
|
};
|
|
68
71
|
versionNonce;
|
|
72
|
+
getElementsMapIncludingDeleted() {
|
|
73
|
+
return this.elementsMap;
|
|
74
|
+
}
|
|
75
|
+
getNonDeletedElementsMap() {
|
|
76
|
+
return this.nonDeletedElementsMap;
|
|
77
|
+
}
|
|
69
78
|
getElementsIncludingDeleted() {
|
|
70
79
|
return this.elements;
|
|
71
80
|
}
|
|
@@ -141,20 +150,26 @@ class Scene {
|
|
|
141
150
|
}
|
|
142
151
|
return didChange;
|
|
143
152
|
}
|
|
144
|
-
replaceAllElements(nextElements
|
|
145
|
-
this.elements =
|
|
153
|
+
replaceAllElements(nextElements) {
|
|
154
|
+
this.elements =
|
|
155
|
+
// ts doesn't like `Array.isArray` of `instanceof Map`
|
|
156
|
+
nextElements instanceof Array
|
|
157
|
+
? nextElements
|
|
158
|
+
: Array.from(nextElements.values());
|
|
146
159
|
const nextFrameLikes = [];
|
|
147
160
|
this.elementsMap.clear();
|
|
148
|
-
|
|
161
|
+
this.elements.forEach((element) => {
|
|
149
162
|
if (isFrameLikeElement(element)) {
|
|
150
163
|
nextFrameLikes.push(element);
|
|
151
164
|
}
|
|
152
165
|
this.elementsMap.set(element.id, element);
|
|
153
166
|
Scene.mapElementToScene(element, this);
|
|
154
167
|
});
|
|
155
|
-
|
|
168
|
+
const nonDeletedElements = getNonDeletedElements(this.elements);
|
|
169
|
+
this.nonDeletedElements = nonDeletedElements.elements;
|
|
170
|
+
this.nonDeletedElementsMap = nonDeletedElements.elementsMap;
|
|
156
171
|
this.frames = nextFrameLikes;
|
|
157
|
-
this.nonDeletedFramesLikes = getNonDeletedElements(this.frames);
|
|
172
|
+
this.nonDeletedFramesLikes = getNonDeletedElements(this.frames).elements;
|
|
158
173
|
this.informMutation();
|
|
159
174
|
}
|
|
160
175
|
informMutation() {
|
|
@@ -226,5 +241,14 @@ class Scene {
|
|
|
226
241
|
getElementIndex(elementId) {
|
|
227
242
|
return this.elements.findIndex((element) => element.id === elementId);
|
|
228
243
|
}
|
|
244
|
+
getContainerElement = (element) => {
|
|
245
|
+
if (!element) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
if (element.containerId) {
|
|
249
|
+
return this.getElement(element.containerId) || null;
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
};
|
|
229
253
|
}
|
|
230
254
|
export default Scene;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Drawable, Options } from "roughjs/bin/core";
|
|
2
2
|
import type { RoughGenerator } from "roughjs/bin/generator";
|
|
3
3
|
import type { ExcalidrawElement, NonDeletedExcalidrawElement, ExcalidrawSelectionElement } from "../element/types";
|
|
4
|
+
import { EmbedsValidationStatus } from "../types";
|
|
4
5
|
export declare const generateRoughOptions: (element: ExcalidrawElement, continuousPath?: boolean) => Options;
|
|
5
6
|
/**
|
|
6
7
|
* Generates the roughjs shape for given element.
|
|
@@ -9,7 +10,8 @@ export declare const generateRoughOptions: (element: ExcalidrawElement, continuo
|
|
|
9
10
|
*
|
|
10
11
|
* @private
|
|
11
12
|
*/
|
|
12
|
-
export declare const _generateElementShape: (element: Exclude<NonDeletedExcalidrawElement, ExcalidrawSelectionElement>, generator: RoughGenerator, { isExporting, canvasBackgroundColor, }: {
|
|
13
|
+
export declare const _generateElementShape: (element: Exclude<NonDeletedExcalidrawElement, ExcalidrawSelectionElement>, generator: RoughGenerator, { isExporting, canvasBackgroundColor, embedsValidationStatus, }: {
|
|
13
14
|
isExporting: boolean;
|
|
14
15
|
canvasBackgroundColor: string;
|
|
16
|
+
embedsValidationStatus: EmbedsValidationStatus | null;
|
|
15
17
|
}) => Drawable | Drawable[] | null;
|
|
@@ -84,9 +84,11 @@ export const generateRoughOptions = (element, continuousPath = false) => {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
|
-
const modifyIframeLikeForRoughOptions = (element, isExporting) => {
|
|
87
|
+
const modifyIframeLikeForRoughOptions = (element, isExporting, embedsValidationStatus) => {
|
|
88
88
|
if (isIframeLikeElement(element) &&
|
|
89
|
-
(isExporting ||
|
|
89
|
+
(isExporting ||
|
|
90
|
+
(isEmbeddableElement(element) &&
|
|
91
|
+
embedsValidationStatus?.get(element.id) !== true)) &&
|
|
90
92
|
isTransparent(element.backgroundColor) &&
|
|
91
93
|
isTransparent(element.strokeColor)) {
|
|
92
94
|
return {
|
|
@@ -204,7 +206,7 @@ const getArrowheadShapes = (element, shape, position, arrowhead, generator, opti
|
|
|
204
206
|
*
|
|
205
207
|
* @private
|
|
206
208
|
*/
|
|
207
|
-
export const _generateElementShape = (element, generator, { isExporting, canvasBackgroundColor, }) => {
|
|
209
|
+
export const _generateElementShape = (element, generator, { isExporting, canvasBackgroundColor, embedsValidationStatus, }) => {
|
|
208
210
|
switch (element.type) {
|
|
209
211
|
case "rectangle":
|
|
210
212
|
case "iframe":
|
|
@@ -216,10 +218,10 @@ export const _generateElementShape = (element, generator, { isExporting, canvasB
|
|
|
216
218
|
const w = element.width;
|
|
217
219
|
const h = element.height;
|
|
218
220
|
const r = getCornerRadius(Math.min(w, h), element);
|
|
219
|
-
shape = generator.path(`M ${r} 0 L ${w - r} 0 Q ${w} 0, ${w} ${r} L ${w} ${h - r} Q ${w} ${h}, ${w - r} ${h} L ${r} ${h} Q 0 ${h}, 0 ${h - r} L 0 ${r} Q 0 0, ${r} 0`, generateRoughOptions(modifyIframeLikeForRoughOptions(element, isExporting), true));
|
|
221
|
+
shape = generator.path(`M ${r} 0 L ${w - r} 0 Q ${w} 0, ${w} ${r} L ${w} ${h - r} Q ${w} ${h}, ${w - r} ${h} L ${r} ${h} Q 0 ${h}, 0 ${h - r} L 0 ${r} Q 0 0, ${r} 0`, generateRoughOptions(modifyIframeLikeForRoughOptions(element, isExporting, embedsValidationStatus), true));
|
|
220
222
|
}
|
|
221
223
|
else {
|
|
222
|
-
shape = generator.rectangle(0, 0, element.width, element.height, generateRoughOptions(modifyIframeLikeForRoughOptions(element, isExporting), false));
|
|
224
|
+
shape = generator.rectangle(0, 0, element.width, element.height, generateRoughOptions(modifyIframeLikeForRoughOptions(element, isExporting, embedsValidationStatus), false));
|
|
223
225
|
}
|
|
224
226
|
return shape;
|
|
225
227
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Drawable } from "roughjs/bin/core";
|
|
2
2
|
import { ExcalidrawElement } from "../element/types";
|
|
3
3
|
import { ElementShape, ElementShapes } from "./types";
|
|
4
|
-
import { AppState } from "../types";
|
|
4
|
+
import { AppState, EmbedsValidationStatus } from "../types";
|
|
5
5
|
export declare class ShapeCache {
|
|
6
6
|
private static rg;
|
|
7
7
|
private static cache;
|
|
@@ -20,5 +20,6 @@ export declare class ShapeCache {
|
|
|
20
20
|
static generateElementShape: <T extends import("../element/types").ExcalidrawRectangleElement | import("../element/types").ExcalidrawDiamondElement | import("../element/types").ExcalidrawEllipseElement | import("../element/types").ExcalidrawTextElement | import("../element/types").ExcalidrawLinearElement | import("../element/types").ExcalidrawFreeDrawElement | import("../element/types").ExcalidrawImageElement | import("../element/types").ExcalidrawFrameElement | import("../element/types").ExcalidrawMagicFrameElement | import("../element/types").ExcalidrawIframeElement | import("../element/types").ExcalidrawEmbeddableElement>(element: T, renderConfig: {
|
|
21
21
|
isExporting: boolean;
|
|
22
22
|
canvasBackgroundColor: AppState["viewBackgroundColor"];
|
|
23
|
+
embedsValidationStatus: EmbedsValidationStatus;
|
|
23
24
|
} | null) => ((T["type"] extends keyof ElementShapes ? ElementShapes[T["type"]] | undefined : ElementShape | undefined) & ({} | null)) | (T["type"] extends keyof ElementShapes ? ElementShapes[T["type"]] : Drawable | null);
|
|
24
25
|
}
|
|
@@ -35,6 +35,7 @@ export class ShapeCache {
|
|
|
35
35
|
const shape = _generateElementShape(element, ShapeCache.rg, renderConfig || {
|
|
36
36
|
isExporting: false,
|
|
37
37
|
canvasBackgroundColor: COLOR_PALETTE.white,
|
|
38
|
+
embedsValidationStatus: null,
|
|
38
39
|
});
|
|
39
40
|
ShapeCache.cache.set(element, shape);
|
|
40
41
|
return shape;
|
|
@@ -27,7 +27,8 @@ export const canChangeRoundness = (type) => type === "rectangle" ||
|
|
|
27
27
|
type === "embeddable" ||
|
|
28
28
|
type === "arrow" ||
|
|
29
29
|
type === "line" ||
|
|
30
|
-
type === "diamond"
|
|
30
|
+
type === "diamond" ||
|
|
31
|
+
type === "image";
|
|
31
32
|
export const canHaveArrowheads = (type) => type === "arrow";
|
|
32
33
|
export const getElementAtPosition = (elements, isAtPositionFn) => {
|
|
33
34
|
let hitElement = null;
|
|
@@ -18,6 +18,9 @@ export declare const exportToSvg: (elements: readonly NonDeletedExcalidrawElemen
|
|
|
18
18
|
exportEmbedScene?: boolean;
|
|
19
19
|
frameRendering?: AppState["frameRendering"];
|
|
20
20
|
}, files: BinaryFiles | null, opts?: {
|
|
21
|
+
/**
|
|
22
|
+
* if true, all embeddables passed in will be rendered when possible.
|
|
23
|
+
*/
|
|
21
24
|
renderEmbeddables?: boolean;
|
|
22
25
|
exportingFrame?: ExcalidrawFrameLikeElement | null;
|
|
23
26
|
}) => Promise<SVGSVGElement>;
|
|
@@ -1,38 +1,17 @@
|
|
|
1
1
|
import rough from "roughjs/bin/rough";
|
|
2
2
|
import { getCommonBounds, getElementAbsoluteCoords, } from "../element/bounds";
|
|
3
|
-
import { renderSceneToSvg
|
|
4
|
-
import {
|
|
3
|
+
import { renderSceneToSvg } from "../renderer/staticSvgScene";
|
|
4
|
+
import { arrayToMap, distance, getFontString, toBrandedType } from "../utils";
|
|
5
5
|
import { DEFAULT_EXPORT_PADDING, FONT_FAMILY, FRAME_STYLE, SVG_NS, THEME_FILTER, } from "../constants";
|
|
6
6
|
import { getDefaultAppState } from "../appState";
|
|
7
7
|
import { serializeAsJSON } from "../data/json";
|
|
8
8
|
import { getInitializedImageElements, updateImageCache, } from "../element/image";
|
|
9
|
-
import {
|
|
10
|
-
import { getFrameLikeElements, getFrameLikeTitle, getRootElements, } from "../frame";
|
|
9
|
+
import { getElementsOverlappingFrame, getFrameLikeElements, getFrameLikeTitle, getRootElements, } from "../frame";
|
|
11
10
|
import { newTextElement } from "../element";
|
|
12
11
|
import { newElementWith } from "../element/mutateElement";
|
|
13
|
-
import Scene from "./Scene";
|
|
14
12
|
import { isFrameElement, isFrameLikeElement } from "../element/typeChecks";
|
|
13
|
+
import { renderStaticScene } from "../renderer/staticScene";
|
|
15
14
|
const SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;
|
|
16
|
-
// getContainerElement and getBoundTextElement and potentially other helpers
|
|
17
|
-
// depend on `Scene` which will not be available when these pure utils are
|
|
18
|
-
// called outside initialized Excalidraw editor instance or even if called
|
|
19
|
-
// from inside Excalidraw if the elements were never cached by Scene (e.g.
|
|
20
|
-
// for library elements).
|
|
21
|
-
//
|
|
22
|
-
// As such, before passing the elements down, we need to initialize a custom
|
|
23
|
-
// Scene instance and assign them to it.
|
|
24
|
-
//
|
|
25
|
-
// FIXME This is a super hacky workaround and we'll need to rewrite this soon.
|
|
26
|
-
const __createSceneForElementsHack__ = (elements) => {
|
|
27
|
-
const scene = new Scene();
|
|
28
|
-
// we can't duplicate elements to regenerate ids because we need the
|
|
29
|
-
// orig ids when embedding. So we do another hack of not mapping element
|
|
30
|
-
// ids to Scene instances so that we don't override the editor elements
|
|
31
|
-
// mapping.
|
|
32
|
-
// We still need to clone the objects themselves to regen references.
|
|
33
|
-
scene.replaceAllElements(cloneJSON(elements), false);
|
|
34
|
-
return scene;
|
|
35
|
-
};
|
|
36
15
|
const truncateText = (element, maxWidth) => {
|
|
37
16
|
if (element.width <= maxWidth) {
|
|
38
17
|
return element;
|
|
@@ -109,11 +88,7 @@ const getFrameRenderingConfig = (exportingFrame, frameRendering) => {
|
|
|
109
88
|
const prepareElementsForRender = ({ elements, exportingFrame, frameRendering, exportWithDarkMode, }) => {
|
|
110
89
|
let nextElements;
|
|
111
90
|
if (exportingFrame) {
|
|
112
|
-
nextElements =
|
|
113
|
-
elements,
|
|
114
|
-
bounds: exportingFrame,
|
|
115
|
-
type: "overlap",
|
|
116
|
-
});
|
|
91
|
+
nextElements = getElementsOverlappingFrame(elements, exportingFrame);
|
|
117
92
|
}
|
|
118
93
|
else if (frameRendering.enabled && frameRendering.name) {
|
|
119
94
|
nextElements = addFrameLabelsAsTextElements(elements, {
|
|
@@ -131,8 +106,6 @@ export const exportToCanvas = async (elements, appState, files, { exportBackgrou
|
|
|
131
106
|
canvas.height = height * appState.exportScale;
|
|
132
107
|
return { canvas, scale: appState.exportScale };
|
|
133
108
|
}) => {
|
|
134
|
-
const tempScene = __createSceneForElementsHack__(elements);
|
|
135
|
-
elements = tempScene.getNonDeletedElements();
|
|
136
109
|
const frameRendering = getFrameRenderingConfig(exportingFrame ?? null, appState.frameRendering ?? null);
|
|
137
110
|
const elementsForRender = prepareElementsForRender({
|
|
138
111
|
elements,
|
|
@@ -154,7 +127,8 @@ export const exportToCanvas = async (elements, appState, files, { exportBackgrou
|
|
|
154
127
|
renderStaticScene({
|
|
155
128
|
canvas,
|
|
156
129
|
rc: rough.canvas(canvas),
|
|
157
|
-
|
|
130
|
+
elementsMap: toBrandedType(arrayToMap(elementsForRender)),
|
|
131
|
+
allElementsMap: toBrandedType(arrayToMap(elements)),
|
|
158
132
|
visibleElements: elementsForRender,
|
|
159
133
|
scale,
|
|
160
134
|
appState: {
|
|
@@ -172,14 +146,14 @@ export const exportToCanvas = async (elements, appState, files, { exportBackgrou
|
|
|
172
146
|
imageCache,
|
|
173
147
|
renderGrid: false,
|
|
174
148
|
isExporting: true,
|
|
149
|
+
// empty disables embeddable rendering
|
|
150
|
+
embedsValidationStatus: new Map(),
|
|
151
|
+
elementsPendingErasure: new Set(),
|
|
175
152
|
},
|
|
176
153
|
});
|
|
177
|
-
tempScene.destroy();
|
|
178
154
|
return canvas;
|
|
179
155
|
};
|
|
180
156
|
export const exportToSvg = async (elements, appState, files, opts) => {
|
|
181
|
-
const tempScene = __createSceneForElementsHack__(elements);
|
|
182
|
-
elements = tempScene.getNonDeletedElements();
|
|
183
157
|
const frameRendering = getFrameRenderingConfig(opts?.exportingFrame ?? null, appState.frameRendering ?? null);
|
|
184
158
|
let { exportPadding = DEFAULT_EXPORT_PADDING, exportWithDarkMode = false, viewBackgroundColor, exportScale = 1, exportEmbedScene, } = appState;
|
|
185
159
|
const { exportingFrame = null } = opts || {};
|
|
@@ -235,8 +209,9 @@ export const exportToSvg = async (elements, appState, files, opts) => {
|
|
|
235
209
|
const offsetY = -minY + exportPadding;
|
|
236
210
|
const frameElements = getFrameLikeElements(elements);
|
|
237
211
|
let exportingFrameClipPath = "";
|
|
212
|
+
const elementsMap = arrayToMap(elements);
|
|
238
213
|
for (const frame of frameElements) {
|
|
239
|
-
const [x1, y1, x2, y2] = getElementAbsoluteCoords(frame);
|
|
214
|
+
const [x1, y1, x2, y2] = getElementAbsoluteCoords(frame, elementsMap);
|
|
240
215
|
const cx = (x2 - x1) / 2 - (frame.x - x1);
|
|
241
216
|
const cy = (y2 - y1) / 2 - (frame.y - y1);
|
|
242
217
|
exportingFrameClipPath += `<clipPath id=${frame.id}>
|
|
@@ -279,16 +254,21 @@ export const exportToSvg = async (elements, appState, files, opts) => {
|
|
|
279
254
|
svgRoot.appendChild(rect);
|
|
280
255
|
}
|
|
281
256
|
const rsvg = rough.svg(svgRoot);
|
|
282
|
-
|
|
257
|
+
const renderEmbeddables = opts?.renderEmbeddables ?? false;
|
|
258
|
+
renderSceneToSvg(elementsForRender, toBrandedType(arrayToMap(elementsForRender)), rsvg, svgRoot, files || {}, {
|
|
283
259
|
offsetX,
|
|
284
260
|
offsetY,
|
|
285
261
|
isExporting: true,
|
|
286
262
|
exportWithDarkMode,
|
|
287
|
-
renderEmbeddables
|
|
263
|
+
renderEmbeddables,
|
|
288
264
|
frameRendering,
|
|
289
265
|
canvasBackgroundColor: viewBackgroundColor,
|
|
266
|
+
embedsValidationStatus: renderEmbeddables
|
|
267
|
+
? new Map(elementsForRender
|
|
268
|
+
.filter((element) => isFrameLikeElement(element))
|
|
269
|
+
.map((element) => [element.id, true]))
|
|
270
|
+
: new Map(),
|
|
290
271
|
});
|
|
291
|
-
tempScene.destroy();
|
|
292
272
|
return svgRoot;
|
|
293
273
|
};
|
|
294
274
|
// calculate smallest area to fit the contents in
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { isOverScrollBars } from "./scrollbars";
|
|
2
1
|
export { isSomeElementSelected, getElementsWithinSelection, getCommonAttributeOfSelectedElements, getSelectedElements, getTargetElements, } from "./selection";
|
|
3
2
|
export { calculateScrollCenter } from "./scroll";
|
|
4
3
|
export { hasBackground, hasStrokeWidth, hasStrokeStyle, canHaveArrowheads, canChangeRoundness, getElementAtPosition, getElementsAtPosition, } from "./comparisons";
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { isOverScrollBars } from "./scrollbars";
|
|
2
1
|
export { isSomeElementSelected, getElementsWithinSelection, getCommonAttributeOfSelectedElements, getSelectedElements, getTargetElements, } from "./selection";
|
|
3
2
|
export { calculateScrollCenter } from "./scroll";
|
|
4
3
|
export { hasBackground, hasStrokeWidth, hasStrokeStyle, canHaveArrowheads, canChangeRoundness, getElementAtPosition, getElementsAtPosition, } from "./comparisons";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ExcalidrawElement } from "../element/types";
|
|
2
1
|
import { InteractiveCanvasAppState } from "../types";
|
|
3
2
|
import { ScrollBars } from "./types";
|
|
3
|
+
import { ExcalidrawElement } from "../element/types";
|
|
4
4
|
export declare const SCROLLBAR_MARGIN = 4;
|
|
5
5
|
export declare const SCROLLBAR_WIDTH = 6;
|
|
6
6
|
export declare const SCROLLBAR_COLOR = "rgba(0,0,0,0.3)";
|
|
@@ -5,7 +5,7 @@ export const SCROLLBAR_MARGIN = 4;
|
|
|
5
5
|
export const SCROLLBAR_WIDTH = 6;
|
|
6
6
|
export const SCROLLBAR_COLOR = "rgba(0,0,0,0.3)";
|
|
7
7
|
export const getScrollBars = (elements, viewportWidth, viewportHeight, appState) => {
|
|
8
|
-
if (elements.length
|
|
8
|
+
if (!elements.length) {
|
|
9
9
|
return {
|
|
10
10
|
horizontal: null,
|
|
11
11
|
vertical: null,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExcalidrawElement, NonDeletedExcalidrawElement } from "../element/types";
|
|
1
|
+
import { ElementsMap, ElementsMapOrArray, ExcalidrawElement, NonDeletedExcalidrawElement } from "../element/types";
|
|
2
2
|
import { AppState, InteractiveCanvasAppState } from "../types";
|
|
3
3
|
/**
|
|
4
4
|
* Frames and their containing elements are not to be selected at the same time.
|
|
@@ -7,8 +7,8 @@ import { AppState, InteractiveCanvasAppState } from "../types";
|
|
|
7
7
|
* @param selectedElements
|
|
8
8
|
*/
|
|
9
9
|
export declare const excludeElementsInFramesFromSelection: <T extends ExcalidrawElement>(selectedElements: readonly T[]) => T[];
|
|
10
|
-
export declare const getElementsWithinSelection: (elements: readonly NonDeletedExcalidrawElement[], selection: NonDeletedExcalidrawElement, excludeElementsInFrames?: boolean) => NonDeletedExcalidrawElement[];
|
|
11
|
-
export declare const getVisibleAndNonSelectedElements: (elements: readonly NonDeletedExcalidrawElement[], selectedElements: readonly NonDeletedExcalidrawElement[], appState: AppState) => NonDeletedExcalidrawElement[];
|
|
10
|
+
export declare const getElementsWithinSelection: (elements: readonly NonDeletedExcalidrawElement[], selection: NonDeletedExcalidrawElement, elementsMap: ElementsMap, excludeElementsInFrames?: boolean) => NonDeletedExcalidrawElement[];
|
|
11
|
+
export declare const getVisibleAndNonSelectedElements: (elements: readonly NonDeletedExcalidrawElement[], selectedElements: readonly NonDeletedExcalidrawElement[], appState: AppState, elementsMap: ElementsMap) => NonDeletedExcalidrawElement[];
|
|
12
12
|
export declare const isSomeElementSelected: {
|
|
13
13
|
(elements: readonly NonDeletedExcalidrawElement[], appState: Pick<AppState, "selectedElementIds">): boolean;
|
|
14
14
|
clearCache(): void;
|
|
@@ -18,11 +18,11 @@ export declare const isSomeElementSelected: {
|
|
|
18
18
|
* elements. If elements don't share the same value, returns `null`.
|
|
19
19
|
*/
|
|
20
20
|
export declare const getCommonAttributeOfSelectedElements: <T>(elements: readonly NonDeletedExcalidrawElement[], appState: Pick<AppState, "selectedElementIds">, getAttribute: (element: ExcalidrawElement) => T) => T | null;
|
|
21
|
-
export declare const getSelectedElements: (elements:
|
|
21
|
+
export declare const getSelectedElements: (elements: ElementsMapOrArray, appState: Pick<InteractiveCanvasAppState, "selectedElementIds">, opts?: {
|
|
22
22
|
includeBoundTextElement?: boolean;
|
|
23
23
|
includeElementsInFrames?: boolean;
|
|
24
24
|
}) => ExcalidrawElement[];
|
|
25
|
-
export declare const getTargetElements: (elements:
|
|
25
|
+
export declare const getTargetElements: (elements: ElementsMapOrArray, appState: Pick<AppState, "selectedElementIds" | "editingElement">) => ExcalidrawElement[];
|
|
26
26
|
/**
|
|
27
27
|
* returns prevState's selectedElementids if no change from previous, so as to
|
|
28
28
|
* retain reference identity for memoization
|
|
@@ -23,13 +23,13 @@ export const excludeElementsInFramesFromSelection = (selectedElements) => {
|
|
|
23
23
|
return true;
|
|
24
24
|
});
|
|
25
25
|
};
|
|
26
|
-
export const getElementsWithinSelection = (elements, selection, excludeElementsInFrames = true) => {
|
|
27
|
-
const [selectionX1, selectionY1, selectionX2, selectionY2] = getElementAbsoluteCoords(selection);
|
|
26
|
+
export const getElementsWithinSelection = (elements, selection, elementsMap, excludeElementsInFrames = true) => {
|
|
27
|
+
const [selectionX1, selectionY1, selectionX2, selectionY2] = getElementAbsoluteCoords(selection, elementsMap);
|
|
28
28
|
let elementsInSelection = elements.filter((element) => {
|
|
29
|
-
let [elementX1, elementY1, elementX2, elementY2] = getElementBounds(element);
|
|
30
|
-
const containingFrame = getContainingFrame(element);
|
|
29
|
+
let [elementX1, elementY1, elementX2, elementY2] = getElementBounds(element, elementsMap);
|
|
30
|
+
const containingFrame = getContainingFrame(element, elementsMap);
|
|
31
31
|
if (containingFrame) {
|
|
32
|
-
const [fx1, fy1, fx2, fy2] = getElementBounds(containingFrame);
|
|
32
|
+
const [fx1, fy1, fx2, fy2] = getElementBounds(containingFrame, elementsMap);
|
|
33
33
|
elementX1 = Math.max(fx1, elementX1);
|
|
34
34
|
elementY1 = Math.max(fy1, elementY1);
|
|
35
35
|
elementX2 = Math.min(fx2, elementX2);
|
|
@@ -47,18 +47,18 @@ export const getElementsWithinSelection = (elements, selection, excludeElementsI
|
|
|
47
47
|
? excludeElementsInFramesFromSelection(elementsInSelection)
|
|
48
48
|
: elementsInSelection;
|
|
49
49
|
elementsInSelection = elementsInSelection.filter((element) => {
|
|
50
|
-
const containingFrame = getContainingFrame(element);
|
|
50
|
+
const containingFrame = getContainingFrame(element, elementsMap);
|
|
51
51
|
if (containingFrame) {
|
|
52
|
-
return elementOverlapsWithFrame(element, containingFrame);
|
|
52
|
+
return elementOverlapsWithFrame(element, containingFrame, elementsMap);
|
|
53
53
|
}
|
|
54
54
|
return true;
|
|
55
55
|
});
|
|
56
56
|
return elementsInSelection;
|
|
57
57
|
};
|
|
58
|
-
export const getVisibleAndNonSelectedElements = (elements, selectedElements, appState) => {
|
|
58
|
+
export const getVisibleAndNonSelectedElements = (elements, selectedElements, appState, elementsMap) => {
|
|
59
59
|
const selectedElementsSet = new Set(selectedElements.map((element) => element.id));
|
|
60
60
|
return elements.filter((element) => {
|
|
61
|
-
const isVisible = isElementInViewport(element, appState.width, appState.height, appState);
|
|
61
|
+
const isVisible = isElementInViewport(element, appState.width, appState.height, appState, elementsMap);
|
|
62
62
|
return !selectedElementsSet.has(element.id) && isVisible;
|
|
63
63
|
});
|
|
64
64
|
};
|
|
@@ -94,17 +94,19 @@ export const getCommonAttributeOfSelectedElements = (elements, appState, getAttr
|
|
|
94
94
|
return attributes.length === 1 ? attributes[0] : null;
|
|
95
95
|
};
|
|
96
96
|
export const getSelectedElements = (elements, appState, opts) => {
|
|
97
|
-
const selectedElements =
|
|
97
|
+
const selectedElements = [];
|
|
98
|
+
for (const element of elements.values()) {
|
|
98
99
|
if (appState.selectedElementIds[element.id]) {
|
|
99
|
-
|
|
100
|
+
selectedElements.push(element);
|
|
101
|
+
continue;
|
|
100
102
|
}
|
|
101
103
|
if (opts?.includeBoundTextElement &&
|
|
102
104
|
isBoundToContainer(element) &&
|
|
103
105
|
appState.selectedElementIds[element?.containerId]) {
|
|
104
|
-
|
|
106
|
+
selectedElements.push(element);
|
|
107
|
+
continue;
|
|
105
108
|
}
|
|
106
|
-
|
|
107
|
-
});
|
|
109
|
+
}
|
|
108
110
|
if (opts?.includeElementsInFrames) {
|
|
109
111
|
const elementsToInclude = [];
|
|
110
112
|
selectedElements.forEach((element) => {
|