@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.
- package/CHANGELOG.md +52 -2
- package/dist/browser/dev/excalidraw-assets-dev/chunk-5VWQDKDR.js +20279 -0
- package/dist/browser/dev/excalidraw-assets-dev/chunk-5VWQDKDR.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{chunk-2W5GQUR4.js → chunk-IM4WTX2M.js} +12 -6
- package/dist/browser/dev/excalidraw-assets-dev/chunk-IM4WTX2M.js.map +7 -0
- package/dist/browser/dev/excalidraw-assets-dev/{en-OC6JWP3X.js → en-IOBA4CS2.js} +4 -2
- 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/{image-5TVMINCA.js → image-VKDAL6BQ.js} +2 -4
- 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 +34708 -37
- package/dist/browser/dev/index.js.map +4 -4
- package/dist/browser/prod/excalidraw-assets/chunk-LIG3S5TN.js +11 -0
- package/dist/browser/prod/excalidraw-assets/chunk-N2C5DK3B.js +55 -0
- package/dist/browser/prod/excalidraw-assets/en-WFZVQ7I6.js +1 -0
- package/dist/browser/prod/excalidraw-assets/image-4AT7LYMR.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-TDNWCAOT.json} +9 -5
- package/dist/dev/index.css +189 -129
- package/dist/dev/index.css.map +3 -3
- package/dist/dev/index.js +39078 -40080
- 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/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 +0 -1
- package/dist/excalidraw/element/index.js +0 -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 +18 -20
- package/dist/excalidraw/element/textElement.js +80 -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 +8 -9
- package/dist/excalidraw/index.js +15 -11
- package/dist/excalidraw/laser-trails.d.ts +19 -0
- package/dist/excalidraw/laser-trails.js +95 -0
- package/dist/excalidraw/locales/en.json +9 -5
- 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 +10 -11
- package/dist/excalidraw/utility-types.d.ts +5 -0
- package/dist/excalidraw/utils.d.ts +18 -15
- package/dist/excalidraw/utils.js +37 -45
- package/dist/{dev/en-RLIAOBCI.json → prod/en-TDNWCAOT.json} +9 -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-IOBA4CS2.js.map} +0 -0
- /package/dist/browser/dev/excalidraw-assets-dev/{image-5TVMINCA.js.map → image-VKDAL6BQ.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Point } from "../types";
|
|
2
2
|
import { FONT_FAMILY, ROUNDNESS, TEXT_ALIGN, THEME, VERTICAL_ALIGN } from "../constants";
|
|
3
|
-
import { MarkNonNullable, ValueOf } from "../utility-types";
|
|
3
|
+
import { MakeBrand, MarkNonNullable, ValueOf } from "../utility-types";
|
|
4
4
|
import { MagicCacheData } from "../data/magic";
|
|
5
5
|
export type ChartType = "bar" | "line";
|
|
6
6
|
export type FillStyle = "hachure" | "cross-hatch" | "solid" | "zigzag";
|
|
@@ -76,14 +76,6 @@ export type ExcalidrawEllipseElement = _ExcalidrawElementBase & {
|
|
|
76
76
|
};
|
|
77
77
|
export type ExcalidrawEmbeddableElement = _ExcalidrawElementBase & Readonly<{
|
|
78
78
|
type: "embeddable";
|
|
79
|
-
/**
|
|
80
|
-
* indicates whether the embeddable src (url) has been validated for rendering.
|
|
81
|
-
* null value indicates that the validation is pending. We reset the
|
|
82
|
-
* value on each restore (or url change) so that we can guarantee
|
|
83
|
-
* the validation came from a trusted source (the editor). Also because we
|
|
84
|
-
* may not have access to host-app supplied url validator during restore.
|
|
85
|
-
*/
|
|
86
|
-
validated: boolean | null;
|
|
87
79
|
}>;
|
|
88
80
|
export type ExcalidrawIframeElement = _ExcalidrawElementBase & Readonly<{
|
|
89
81
|
type: "iframe";
|
|
@@ -97,7 +89,7 @@ export type IframeData = ({
|
|
|
97
89
|
w: number;
|
|
98
90
|
h: number;
|
|
99
91
|
};
|
|
100
|
-
|
|
92
|
+
error?: Error;
|
|
101
93
|
} & ({
|
|
102
94
|
type: "video" | "generic";
|
|
103
95
|
link: string;
|
|
@@ -142,7 +134,6 @@ export type ExcalidrawTextElement = _ExcalidrawElementBase & Readonly<{
|
|
|
142
134
|
fontSize: number;
|
|
143
135
|
fontFamily: FontFamilyValues;
|
|
144
136
|
text: string;
|
|
145
|
-
baseline: number;
|
|
146
137
|
textAlign: TextAlign;
|
|
147
138
|
verticalAlign: VerticalAlign;
|
|
148
139
|
containerId: ExcalidrawGenericElement["id"] | null;
|
|
@@ -189,4 +180,26 @@ export type FileId = string & {
|
|
|
189
180
|
_brand: "FileId";
|
|
190
181
|
};
|
|
191
182
|
export type ExcalidrawElementType = ExcalidrawElement["type"];
|
|
183
|
+
/**
|
|
184
|
+
* Map of excalidraw elements.
|
|
185
|
+
* Unspecified whether deleted or non-deleted.
|
|
186
|
+
* Can be a subset of Scene elements.
|
|
187
|
+
*/
|
|
188
|
+
export type ElementsMap = Map<ExcalidrawElement["id"], ExcalidrawElement>;
|
|
189
|
+
/**
|
|
190
|
+
* Map of non-deleted elements.
|
|
191
|
+
* Can be a subset of Scene elements.
|
|
192
|
+
*/
|
|
193
|
+
export type NonDeletedElementsMap = Map<ExcalidrawElement["id"], NonDeletedExcalidrawElement> & MakeBrand<"NonDeletedElementsMap">;
|
|
194
|
+
/**
|
|
195
|
+
* Map of all excalidraw Scene elements, including deleted.
|
|
196
|
+
* Not a subset. Use this type when you need access to current Scene elements.
|
|
197
|
+
*/
|
|
198
|
+
export type SceneElementsMap = Map<ExcalidrawElement["id"], ExcalidrawElement> & MakeBrand<"SceneElementsMap">;
|
|
199
|
+
/**
|
|
200
|
+
* Map of all non-deleted Scene elements.
|
|
201
|
+
* Not a subset. Use this type when you need access to current Scene elements.
|
|
202
|
+
*/
|
|
203
|
+
export type NonDeletedSceneElementsMap = Map<ExcalidrawElement["id"], NonDeletedExcalidrawElement> & MakeBrand<"NonDeletedSceneElementsMap">;
|
|
204
|
+
export type ElementsMapOrArray = readonly ExcalidrawElement[] | Readonly<ElementsMap>;
|
|
192
205
|
export {};
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import { ExcalidrawElement, ExcalidrawFrameLikeElement, NonDeleted, NonDeletedExcalidrawElement } from "./element/types";
|
|
1
|
+
import { ElementsMap, ElementsMapOrArray, ExcalidrawElement, ExcalidrawFrameLikeElement, NonDeleted, NonDeletedExcalidrawElement } from "./element/types";
|
|
2
2
|
import { AppClassProperties, AppState, StaticCanvasAppState } from "./types";
|
|
3
|
-
import { ExcalidrawElementsIncludingDeleted } from "./scene/Scene";
|
|
3
|
+
import type { ExcalidrawElementsIncludingDeleted } from "./scene/Scene";
|
|
4
|
+
import { ReadonlySetLike } from "./utility-types";
|
|
4
5
|
export declare const bindElementsToFramesAfterDuplication: (nextElements: ExcalidrawElement[], oldElements: readonly ExcalidrawElement[], oldIdToDuplicatedId: Map<ExcalidrawElement["id"], ExcalidrawElement["id"]>) => void;
|
|
5
|
-
export declare function isElementIntersectingFrame(element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement): boolean;
|
|
6
|
-
export declare const getElementsCompletelyInFrame: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => ExcalidrawElement[];
|
|
7
|
-
export declare const isElementContainingFrame: (elements: readonly ExcalidrawElement[], element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement) => boolean;
|
|
6
|
+
export declare function isElementIntersectingFrame(element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap): boolean;
|
|
7
|
+
export declare const getElementsCompletelyInFrame: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => ExcalidrawElement[];
|
|
8
|
+
export declare const isElementContainingFrame: (elements: readonly ExcalidrawElement[], element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => boolean;
|
|
8
9
|
export declare const getElementsIntersectingFrame: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => ExcalidrawElement[];
|
|
9
|
-
export declare const elementsAreInFrameBounds: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => boolean;
|
|
10
|
-
export declare const elementOverlapsWithFrame: (element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement) => boolean;
|
|
10
|
+
export declare const elementsAreInFrameBounds: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => boolean;
|
|
11
|
+
export declare const elementOverlapsWithFrame: (element: ExcalidrawElement, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => boolean;
|
|
11
12
|
export declare const isCursorInFrame: (cursorCoords: {
|
|
12
13
|
x: number;
|
|
13
14
|
y: number;
|
|
14
|
-
}, frame: NonDeleted<ExcalidrawFrameLikeElement
|
|
15
|
+
}, frame: NonDeleted<ExcalidrawFrameLikeElement>, elementsMap: ElementsMap) => boolean;
|
|
15
16
|
export declare const groupsAreAtLeastIntersectingTheFrame: (elements: readonly NonDeletedExcalidrawElement[], groupIds: readonly string[], frame: ExcalidrawFrameLikeElement) => boolean;
|
|
16
17
|
export declare const groupsAreCompletelyOutOfFrame: (elements: readonly NonDeletedExcalidrawElement[], groupIds: readonly string[], frame: ExcalidrawFrameLikeElement) => boolean;
|
|
17
18
|
/**
|
|
18
19
|
* Returns a map of frameId to frame elements. Includes empty frames.
|
|
19
20
|
*/
|
|
20
21
|
export declare const groupByFrameLikes: (elements: readonly ExcalidrawElement[]) => Map<string, ExcalidrawElement[]>;
|
|
21
|
-
export declare const getFrameChildren: (allElements:
|
|
22
|
+
export declare const getFrameChildren: (allElements: ElementsMapOrArray, frameId: string) => ExcalidrawElement[];
|
|
22
23
|
export declare const getFrameLikeElements: (allElements: ExcalidrawElementsIncludingDeleted) => ExcalidrawFrameLikeElement[];
|
|
23
24
|
/**
|
|
24
25
|
* Returns ExcalidrawFrameElements and non-frame-children elements.
|
|
@@ -29,29 +30,34 @@ export declare const getFrameLikeElements: (allElements: ExcalidrawElementsInclu
|
|
|
29
30
|
* Considers non-frame bound elements (container or arrow labels) as root.
|
|
30
31
|
*/
|
|
31
32
|
export declare const getRootElements: (allElements: ExcalidrawElementsIncludingDeleted) => ExcalidrawElement[];
|
|
32
|
-
export declare const getElementsInResizingFrame: (allElements: ExcalidrawElementsIncludingDeleted, frame: ExcalidrawFrameLikeElement, appState: AppState) => ExcalidrawElement[];
|
|
33
|
-
export declare const getElementsInNewFrame: (
|
|
34
|
-
export declare const getContainingFrame: (element: ExcalidrawElement, elementsMap
|
|
33
|
+
export declare const getElementsInResizingFrame: (allElements: ExcalidrawElementsIncludingDeleted, frame: ExcalidrawFrameLikeElement, appState: AppState, elementsMap: ElementsMap) => ExcalidrawElement[];
|
|
34
|
+
export declare const getElementsInNewFrame: (elements: ExcalidrawElementsIncludingDeleted, frame: ExcalidrawFrameLikeElement, elementsMap: ElementsMap) => ExcalidrawElement[];
|
|
35
|
+
export declare const getContainingFrame: (element: ExcalidrawElement, elementsMap: ElementsMap) => ExcalidrawFrameLikeElement | null;
|
|
36
|
+
/** */
|
|
37
|
+
export declare const filterElementsEligibleAsFrameChildren: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => ExcalidrawElement[];
|
|
35
38
|
/**
|
|
36
39
|
* Retains (or repairs for target frame) the ordering invriant where children
|
|
37
40
|
* elements come right before the parent frame:
|
|
38
41
|
* [el, el, child, child, frame, el]
|
|
42
|
+
*
|
|
43
|
+
* @returns mutated allElements (same data structure)
|
|
39
44
|
*/
|
|
40
|
-
export declare const addElementsToFrame: (allElements:
|
|
41
|
-
export declare const removeElementsFromFrame: (
|
|
42
|
-
export declare const removeAllElementsFromFrame: (allElements:
|
|
43
|
-
export declare const replaceAllElementsInFrame: (allElements:
|
|
45
|
+
export declare const addElementsToFrame: <T extends ElementsMapOrArray>(allElements: T, elementsToAdd: NonDeletedExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => T;
|
|
46
|
+
export declare const removeElementsFromFrame: (elementsToRemove: ReadonlySetLike<NonDeletedExcalidrawElement>, elementsMap: ElementsMap) => void;
|
|
47
|
+
export declare const removeAllElementsFromFrame: <T extends ExcalidrawElement>(allElements: readonly T[], frame: ExcalidrawFrameLikeElement) => readonly T[];
|
|
48
|
+
export declare const replaceAllElementsInFrame: <T extends ExcalidrawElement>(allElements: readonly T[], nextElementsInFrame: ExcalidrawElement[], frame: ExcalidrawFrameLikeElement, app: AppClassProperties) => T[];
|
|
44
49
|
/** does not mutate elements, but returns new ones */
|
|
45
|
-
export declare const updateFrameMembershipOfSelectedElements: (allElements:
|
|
50
|
+
export declare const updateFrameMembershipOfSelectedElements: <T extends ElementsMapOrArray>(allElements: T, appState: AppState, app: AppClassProperties) => T;
|
|
46
51
|
/**
|
|
47
52
|
* filters out elements that are inside groups that contain a frame element
|
|
48
53
|
* anywhere in the group tree
|
|
49
54
|
*/
|
|
50
|
-
export declare const omitGroupsContainingFrameLikes: (allElements:
|
|
55
|
+
export declare const omitGroupsContainingFrameLikes: (allElements: ElementsMapOrArray, selectedElements?: readonly ExcalidrawElement[]) => ExcalidrawElement[];
|
|
51
56
|
/**
|
|
52
57
|
* depending on the appState, return target frame, which is the frame the given element
|
|
53
58
|
* is going to be added to or remove from
|
|
54
59
|
*/
|
|
55
|
-
export declare const getTargetFrame: (element: ExcalidrawElement, appState: StaticCanvasAppState) => import("./element/types").ExcalidrawFrameElement | import("./element/types").ExcalidrawMagicFrameElement | null;
|
|
56
|
-
export declare const isElementInFrame: (element: ExcalidrawElement,
|
|
60
|
+
export declare const getTargetFrame: (element: ExcalidrawElement, elementsMap: ElementsMap, appState: StaticCanvasAppState) => import("./element/types").ExcalidrawFrameElement | import("./element/types").ExcalidrawMagicFrameElement | null;
|
|
61
|
+
export declare const isElementInFrame: (element: ExcalidrawElement, allElementsMap: ElementsMap, appState: StaticCanvasAppState) => boolean;
|
|
57
62
|
export declare const getFrameLikeTitle: (element: ExcalidrawFrameLikeElement, frameIdx: number) => string;
|
|
63
|
+
export declare const getElementsOverlappingFrame: (elements: readonly ExcalidrawElement[], frame: ExcalidrawFrameLikeElement) => NonDeletedExcalidrawElement[];
|
package/dist/excalidraw/frame.js
CHANGED
|
@@ -5,9 +5,8 @@ import { arrayToMap } from "./utils";
|
|
|
5
5
|
import { mutateElement } from "./element/mutateElement";
|
|
6
6
|
import { getElementsWithinSelection, getSelectedElements } from "./scene";
|
|
7
7
|
import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups";
|
|
8
|
-
import Scene from "./scene/Scene";
|
|
9
8
|
import { getElementLineSegments } from "./element/bounds";
|
|
10
|
-
import { doLineSegmentsIntersect } from "../utils/
|
|
9
|
+
import { doLineSegmentsIntersect, elementsOverlappingBBox } from "../utils/";
|
|
11
10
|
import { isFrameElement, isFrameLikeElement } from "./element/typeChecks";
|
|
12
11
|
// --------------------------- Frame State ------------------------------------
|
|
13
12
|
export const bindElementsToFramesAfterDuplication = (nextElements, oldElements, oldIdToDuplicatedId) => {
|
|
@@ -28,50 +27,55 @@ export const bindElementsToFramesAfterDuplication = (nextElements, oldElements,
|
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
29
|
};
|
|
31
|
-
export function isElementIntersectingFrame(element, frame) {
|
|
32
|
-
const frameLineSegments = getElementLineSegments(frame);
|
|
33
|
-
const elementLineSegments = getElementLineSegments(element);
|
|
30
|
+
export function isElementIntersectingFrame(element, frame, elementsMap) {
|
|
31
|
+
const frameLineSegments = getElementLineSegments(frame, elementsMap);
|
|
32
|
+
const elementLineSegments = getElementLineSegments(element, elementsMap);
|
|
34
33
|
const intersecting = frameLineSegments.some((frameLineSegment) => elementLineSegments.some((elementLineSegment) => doLineSegmentsIntersect(frameLineSegment, elementLineSegment)));
|
|
35
34
|
return intersecting;
|
|
36
35
|
}
|
|
37
|
-
export const getElementsCompletelyInFrame = (elements, frame) => omitGroupsContainingFrameLikes(getElementsWithinSelection(elements, frame, false)).filter((element) => (!isFrameLikeElement(element) && !element.frameId) ||
|
|
36
|
+
export const getElementsCompletelyInFrame = (elements, frame, elementsMap) => omitGroupsContainingFrameLikes(getElementsWithinSelection(elements, frame, elementsMap, false)).filter((element) => (!isFrameLikeElement(element) && !element.frameId) ||
|
|
38
37
|
element.frameId === frame.id);
|
|
39
|
-
export const isElementContainingFrame = (elements, element, frame) => {
|
|
40
|
-
return getElementsWithinSelection(elements, element).some((e) => e.id === frame.id);
|
|
38
|
+
export const isElementContainingFrame = (elements, element, frame, elementsMap) => {
|
|
39
|
+
return getElementsWithinSelection(elements, element, elementsMap).some((e) => e.id === frame.id);
|
|
41
40
|
};
|
|
42
|
-
export const getElementsIntersectingFrame = (elements, frame) =>
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
export const getElementsIntersectingFrame = (elements, frame) => {
|
|
42
|
+
const elementsMap = arrayToMap(elements);
|
|
43
|
+
return elements.filter((element) => isElementIntersectingFrame(element, frame, elementsMap));
|
|
44
|
+
};
|
|
45
|
+
export const elementsAreInFrameBounds = (elements, frame, elementsMap) => {
|
|
46
|
+
const [frameX1, frameY1, frameX2, frameY2] = getElementAbsoluteCoords(frame, elementsMap);
|
|
45
47
|
const [elementX1, elementY1, elementX2, elementY2] = getCommonBounds(elements);
|
|
46
|
-
return (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
return (frameX1 <= elementX1 &&
|
|
49
|
+
frameY1 <= elementY1 &&
|
|
50
|
+
frameX2 >= elementX2 &&
|
|
51
|
+
frameY2 >= elementY2);
|
|
50
52
|
};
|
|
51
|
-
export const elementOverlapsWithFrame = (element, frame) => {
|
|
52
|
-
return (elementsAreInFrameBounds([element], frame) ||
|
|
53
|
-
isElementIntersectingFrame(element, frame) ||
|
|
54
|
-
isElementContainingFrame([frame], element, frame));
|
|
53
|
+
export const elementOverlapsWithFrame = (element, frame, elementsMap) => {
|
|
54
|
+
return (elementsAreInFrameBounds([element], frame, elementsMap) ||
|
|
55
|
+
isElementIntersectingFrame(element, frame, elementsMap) ||
|
|
56
|
+
isElementContainingFrame([frame], element, frame, elementsMap));
|
|
55
57
|
};
|
|
56
|
-
export const isCursorInFrame = (cursorCoords, frame) => {
|
|
57
|
-
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame);
|
|
58
|
+
export const isCursorInFrame = (cursorCoords, frame, elementsMap) => {
|
|
59
|
+
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame, elementsMap);
|
|
58
60
|
return isPointWithinBounds([fx1, fy1], [cursorCoords.x, cursorCoords.y], [fx2, fy2]);
|
|
59
61
|
};
|
|
60
62
|
export const groupsAreAtLeastIntersectingTheFrame = (elements, groupIds, frame) => {
|
|
63
|
+
const elementsMap = arrayToMap(elements);
|
|
61
64
|
const elementsInGroup = groupIds.flatMap((groupId) => getElementsInGroup(elements, groupId));
|
|
62
65
|
if (elementsInGroup.length === 0) {
|
|
63
66
|
return true;
|
|
64
67
|
}
|
|
65
|
-
return !!elementsInGroup.find((element) => elementsAreInFrameBounds([element], frame) ||
|
|
66
|
-
isElementIntersectingFrame(element, frame));
|
|
68
|
+
return !!elementsInGroup.find((element) => elementsAreInFrameBounds([element], frame, elementsMap) ||
|
|
69
|
+
isElementIntersectingFrame(element, frame, elementsMap));
|
|
67
70
|
};
|
|
68
71
|
export const groupsAreCompletelyOutOfFrame = (elements, groupIds, frame) => {
|
|
72
|
+
const elementsMap = arrayToMap(elements);
|
|
69
73
|
const elementsInGroup = groupIds.flatMap((groupId) => getElementsInGroup(elements, groupId));
|
|
70
74
|
if (elementsInGroup.length === 0) {
|
|
71
75
|
return true;
|
|
72
76
|
}
|
|
73
|
-
return (elementsInGroup.find((element) => elementsAreInFrameBounds([element], frame) ||
|
|
74
|
-
isElementIntersectingFrame(element, frame)) === undefined);
|
|
77
|
+
return (elementsInGroup.find((element) => elementsAreInFrameBounds([element], frame, elementsMap) ||
|
|
78
|
+
isElementIntersectingFrame(element, frame, elementsMap)) === undefined);
|
|
75
79
|
};
|
|
76
80
|
// --------------------------- Frame Utils ------------------------------------
|
|
77
81
|
/**
|
|
@@ -87,7 +91,15 @@ export const groupByFrameLikes = (elements) => {
|
|
|
87
91
|
}
|
|
88
92
|
return frameElementsMap;
|
|
89
93
|
};
|
|
90
|
-
export const getFrameChildren = (allElements, frameId) =>
|
|
94
|
+
export const getFrameChildren = (allElements, frameId) => {
|
|
95
|
+
const frameChildren = [];
|
|
96
|
+
for (const element of allElements.values()) {
|
|
97
|
+
if (element.frameId === frameId) {
|
|
98
|
+
frameChildren.push(element);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return frameChildren;
|
|
102
|
+
};
|
|
91
103
|
export const getFrameLikeElements = (allElements) => {
|
|
92
104
|
return allElements.filter((element) => isFrameLikeElement(element));
|
|
93
105
|
};
|
|
@@ -105,12 +117,12 @@ export const getRootElements = (allElements) => {
|
|
|
105
117
|
!element.frameId ||
|
|
106
118
|
!frameElements.has(element.frameId));
|
|
107
119
|
};
|
|
108
|
-
export const getElementsInResizingFrame = (allElements, frame, appState) => {
|
|
120
|
+
export const getElementsInResizingFrame = (allElements, frame, appState, elementsMap) => {
|
|
109
121
|
const prevElementsInFrame = getFrameChildren(allElements, frame.id);
|
|
110
122
|
const nextElementsInFrame = new Set(prevElementsInFrame);
|
|
111
123
|
const elementsCompletelyInFrame = new Set([
|
|
112
|
-
...getElementsCompletelyInFrame(allElements, frame),
|
|
113
|
-
...prevElementsInFrame.filter((element) => isElementContainingFrame(allElements, element, frame)),
|
|
124
|
+
...getElementsCompletelyInFrame(allElements, frame, elementsMap),
|
|
125
|
+
...prevElementsInFrame.filter((element) => isElementContainingFrame(allElements, element, frame, elementsMap)),
|
|
114
126
|
]);
|
|
115
127
|
const elementsNotCompletelyInFrame = prevElementsInFrame.filter((element) => !elementsCompletelyInFrame.has(element));
|
|
116
128
|
// for elements that are completely in the frame
|
|
@@ -118,7 +130,7 @@ export const getElementsInResizingFrame = (allElements, frame, appState) => {
|
|
|
118
130
|
// considered to belong to the frame
|
|
119
131
|
const groupsToKeep = new Set(Array.from(elementsCompletelyInFrame).flatMap((element) => element.groupIds));
|
|
120
132
|
for (const element of elementsNotCompletelyInFrame) {
|
|
121
|
-
if (!isElementIntersectingFrame(element, frame)) {
|
|
133
|
+
if (!isElementIntersectingFrame(element, frame, elementsMap)) {
|
|
122
134
|
if (element.groupIds.length === 0) {
|
|
123
135
|
nextElementsInFrame.delete(element);
|
|
124
136
|
}
|
|
@@ -154,7 +166,7 @@ export const getElementsInResizingFrame = (allElements, frame, appState) => {
|
|
|
154
166
|
for (const [id, isSelected] of Object.entries(groupIds)) {
|
|
155
167
|
if (isSelected) {
|
|
156
168
|
const elementsInGroup = getElementsInGroup(allElements, id);
|
|
157
|
-
if (elementsAreInFrameBounds(elementsInGroup, frame)) {
|
|
169
|
+
if (elementsAreInFrameBounds(elementsInGroup, frame, elementsMap)) {
|
|
158
170
|
for (const element of elementsInGroup) {
|
|
159
171
|
nextElementsInFrame.add(element);
|
|
160
172
|
}
|
|
@@ -165,49 +177,91 @@ export const getElementsInResizingFrame = (allElements, frame, appState) => {
|
|
|
165
177
|
return !(isTextElement(element) && element.containerId);
|
|
166
178
|
});
|
|
167
179
|
};
|
|
168
|
-
export const getElementsInNewFrame = (
|
|
169
|
-
return omitGroupsContainingFrameLikes(
|
|
180
|
+
export const getElementsInNewFrame = (elements, frame, elementsMap) => {
|
|
181
|
+
return omitGroupsContainingFrameLikes(elements, getElementsCompletelyInFrame(elements, frame, elementsMap));
|
|
170
182
|
};
|
|
171
|
-
export const getContainingFrame = (element,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
* Takes precedence over Scene elements, even if the element exists
|
|
175
|
-
* in Scene elements and not the supplied elements map.
|
|
176
|
-
*/
|
|
177
|
-
elementsMap) => {
|
|
178
|
-
if (element.frameId) {
|
|
179
|
-
if (elementsMap) {
|
|
180
|
-
return (elementsMap.get(element.frameId) ||
|
|
181
|
-
null);
|
|
182
|
-
}
|
|
183
|
-
return (Scene.getScene(element)?.getElement(element.frameId) || null);
|
|
183
|
+
export const getContainingFrame = (element, elementsMap) => {
|
|
184
|
+
if (!element.frameId) {
|
|
185
|
+
return null;
|
|
184
186
|
}
|
|
185
|
-
return
|
|
187
|
+
return (elementsMap.get(element.frameId) ||
|
|
188
|
+
null);
|
|
186
189
|
};
|
|
187
190
|
// --------------------------- Frame Operations -------------------------------
|
|
191
|
+
/** */
|
|
192
|
+
export const filterElementsEligibleAsFrameChildren = (elements, frame) => {
|
|
193
|
+
const otherFrames = new Set();
|
|
194
|
+
const elementsMap = arrayToMap(elements);
|
|
195
|
+
elements = omitGroupsContainingFrameLikes(elements);
|
|
196
|
+
for (const element of elements) {
|
|
197
|
+
if (isFrameLikeElement(element) && element.id !== frame.id) {
|
|
198
|
+
otherFrames.add(element.id);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const processedGroups = new Set();
|
|
202
|
+
const eligibleElements = [];
|
|
203
|
+
for (const element of elements) {
|
|
204
|
+
// don't add frames or their children
|
|
205
|
+
if (isFrameLikeElement(element) ||
|
|
206
|
+
(element.frameId && otherFrames.has(element.frameId))) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (element.groupIds.length) {
|
|
210
|
+
const shallowestGroupId = element.groupIds.at(-1);
|
|
211
|
+
if (!processedGroups.has(shallowestGroupId)) {
|
|
212
|
+
processedGroups.add(shallowestGroupId);
|
|
213
|
+
const groupElements = getElementsInGroup(elements, shallowestGroupId);
|
|
214
|
+
if (groupElements.some((el) => elementOverlapsWithFrame(el, frame, elementsMap))) {
|
|
215
|
+
for (const child of groupElements) {
|
|
216
|
+
eligibleElements.push(child);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
const overlaps = elementOverlapsWithFrame(element, frame, elementsMap);
|
|
223
|
+
if (overlaps) {
|
|
224
|
+
eligibleElements.push(element);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return eligibleElements;
|
|
229
|
+
};
|
|
188
230
|
/**
|
|
189
231
|
* Retains (or repairs for target frame) the ordering invriant where children
|
|
190
232
|
* elements come right before the parent frame:
|
|
191
233
|
* [el, el, child, child, frame, el]
|
|
234
|
+
*
|
|
235
|
+
* @returns mutated allElements (same data structure)
|
|
192
236
|
*/
|
|
193
237
|
export const addElementsToFrame = (allElements, elementsToAdd, frame) => {
|
|
194
|
-
const
|
|
238
|
+
const elementsMap = arrayToMap(allElements);
|
|
239
|
+
const currTargetFrameChildrenMap = new Map();
|
|
240
|
+
for (const element of allElements.values()) {
|
|
195
241
|
if (element.frameId === frame.id) {
|
|
196
|
-
|
|
242
|
+
currTargetFrameChildrenMap.set(element.id, true);
|
|
197
243
|
}
|
|
198
|
-
|
|
199
|
-
}, {
|
|
200
|
-
currTargetFrameChildrenMap: new Map(),
|
|
201
|
-
});
|
|
244
|
+
}
|
|
202
245
|
const suppliedElementsToAddSet = new Set(elementsToAdd.map((el) => el.id));
|
|
203
246
|
const finalElementsToAdd = [];
|
|
247
|
+
const otherFrames = new Set();
|
|
248
|
+
for (const element of elementsToAdd) {
|
|
249
|
+
if (isFrameLikeElement(element) && element.id !== frame.id) {
|
|
250
|
+
otherFrames.add(element.id);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
204
253
|
// - add bound text elements if not already in the array
|
|
205
254
|
// - filter out elements that are already in the frame
|
|
206
255
|
for (const element of omitGroupsContainingFrameLikes(allElements, elementsToAdd)) {
|
|
256
|
+
// don't add frames or their children
|
|
257
|
+
if (isFrameLikeElement(element) ||
|
|
258
|
+
(element.frameId && otherFrames.has(element.frameId))) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
207
261
|
if (!currTargetFrameChildrenMap.has(element.id)) {
|
|
208
262
|
finalElementsToAdd.push(element);
|
|
209
263
|
}
|
|
210
|
-
const boundTextElement = getBoundTextElement(element);
|
|
264
|
+
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
211
265
|
if (boundTextElement &&
|
|
212
266
|
!suppliedElementsToAddSet.has(boundTextElement.id) &&
|
|
213
267
|
!currTargetFrameChildrenMap.has(boundTextElement.id)) {
|
|
@@ -219,9 +273,9 @@ export const addElementsToFrame = (allElements, elementsToAdd, frame) => {
|
|
|
219
273
|
frameId: frame.id,
|
|
220
274
|
}, false);
|
|
221
275
|
}
|
|
222
|
-
return allElements
|
|
276
|
+
return allElements;
|
|
223
277
|
};
|
|
224
|
-
export const removeElementsFromFrame = (
|
|
278
|
+
export const removeElementsFromFrame = (elementsToRemove, elementsMap) => {
|
|
225
279
|
const _elementsToRemove = new Map();
|
|
226
280
|
const toRemoveElementsByFrame = new Map();
|
|
227
281
|
for (const element of elementsToRemove) {
|
|
@@ -229,7 +283,7 @@ export const removeElementsFromFrame = (allElements, elementsToRemove, appState)
|
|
|
229
283
|
_elementsToRemove.set(element.id, element);
|
|
230
284
|
const arr = toRemoveElementsByFrame.get(element.frameId) || [];
|
|
231
285
|
arr.push(element);
|
|
232
|
-
const boundTextElement = getBoundTextElement(element);
|
|
286
|
+
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
233
287
|
if (boundTextElement) {
|
|
234
288
|
_elementsToRemove.set(boundTextElement.id, boundTextElement);
|
|
235
289
|
arr.push(boundTextElement);
|
|
@@ -242,14 +296,14 @@ export const removeElementsFromFrame = (allElements, elementsToRemove, appState)
|
|
|
242
296
|
frameId: null,
|
|
243
297
|
}, false);
|
|
244
298
|
}
|
|
245
|
-
return allElements.slice();
|
|
246
299
|
};
|
|
247
|
-
export const removeAllElementsFromFrame = (allElements, frame
|
|
300
|
+
export const removeAllElementsFromFrame = (allElements, frame) => {
|
|
248
301
|
const elementsInFrame = getFrameChildren(allElements, frame.id);
|
|
249
|
-
|
|
302
|
+
removeElementsFromFrame(elementsInFrame, arrayToMap(allElements));
|
|
303
|
+
return allElements;
|
|
250
304
|
};
|
|
251
|
-
export const replaceAllElementsInFrame = (allElements, nextElementsInFrame, frame,
|
|
252
|
-
return addElementsToFrame(removeAllElementsFromFrame(allElements, frame
|
|
305
|
+
export const replaceAllElementsInFrame = (allElements, nextElementsInFrame, frame, app) => {
|
|
306
|
+
return addElementsToFrame(removeAllElementsFromFrame(allElements, frame), nextElementsInFrame, frame).slice();
|
|
253
307
|
};
|
|
254
308
|
/** does not mutate elements, but returns new ones */
|
|
255
309
|
export const updateFrameMembershipOfSelectedElements = (allElements, appState, app) => {
|
|
@@ -272,16 +326,18 @@ export const updateFrameMembershipOfSelectedElements = (allElements, appState, a
|
|
|
272
326
|
}
|
|
273
327
|
}
|
|
274
328
|
const elementsToRemove = new Set();
|
|
329
|
+
const elementsMap = arrayToMap(allElements);
|
|
275
330
|
elementsToFilter.forEach((element) => {
|
|
276
331
|
if (element.frameId &&
|
|
277
332
|
!isFrameLikeElement(element) &&
|
|
278
|
-
!isElementInFrame(element,
|
|
333
|
+
!isElementInFrame(element, elementsMap, appState)) {
|
|
279
334
|
elementsToRemove.add(element);
|
|
280
335
|
}
|
|
281
336
|
});
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
337
|
+
if (elementsToRemove.size > 0) {
|
|
338
|
+
removeElementsFromFrame(elementsToRemove, elementsMap);
|
|
339
|
+
}
|
|
340
|
+
return allElements;
|
|
285
341
|
};
|
|
286
342
|
/**
|
|
287
343
|
* filters out elements that are inside groups that contain a frame element
|
|
@@ -293,7 +349,8 @@ export const omitGroupsContainingFrameLikes = (allElements,
|
|
|
293
349
|
*/
|
|
294
350
|
selectedElements) => {
|
|
295
351
|
const uniqueGroupIds = new Set();
|
|
296
|
-
|
|
352
|
+
const elements = selectedElements || allElements;
|
|
353
|
+
for (const el of elements.values()) {
|
|
297
354
|
const topMostGroupId = el.groupIds[el.groupIds.length - 1];
|
|
298
355
|
if (topMostGroupId) {
|
|
299
356
|
uniqueGroupIds.add(topMostGroupId);
|
|
@@ -305,27 +362,33 @@ selectedElements) => {
|
|
|
305
362
|
rejectedGroupIds.add(groupId);
|
|
306
363
|
}
|
|
307
364
|
}
|
|
308
|
-
|
|
365
|
+
const ret = [];
|
|
366
|
+
for (const element of elements.values()) {
|
|
367
|
+
if (!rejectedGroupIds.has(element.groupIds[element.groupIds.length - 1])) {
|
|
368
|
+
ret.push(element);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return ret;
|
|
309
372
|
};
|
|
310
373
|
/**
|
|
311
374
|
* depending on the appState, return target frame, which is the frame the given element
|
|
312
375
|
* is going to be added to or remove from
|
|
313
376
|
*/
|
|
314
|
-
export const getTargetFrame = (element, appState) => {
|
|
377
|
+
export const getTargetFrame = (element, elementsMap, appState) => {
|
|
315
378
|
const _element = isTextElement(element)
|
|
316
|
-
? getContainerElement(element) || element
|
|
379
|
+
? getContainerElement(element, elementsMap) || element
|
|
317
380
|
: element;
|
|
318
381
|
return appState.selectedElementIds[_element.id] &&
|
|
319
382
|
appState.selectedElementsAreBeingDragged
|
|
320
383
|
? appState.frameToHighlight
|
|
321
|
-
: getContainingFrame(_element);
|
|
384
|
+
: getContainingFrame(_element, elementsMap);
|
|
322
385
|
};
|
|
323
386
|
// TODO: this a huge bottleneck for large scenes, optimise
|
|
324
387
|
// given an element, return if the element is in some frame
|
|
325
|
-
export const isElementInFrame = (element,
|
|
326
|
-
const frame = getTargetFrame(element, appState);
|
|
388
|
+
export const isElementInFrame = (element, allElementsMap, appState) => {
|
|
389
|
+
const frame = getTargetFrame(element, allElementsMap, appState);
|
|
327
390
|
const _element = isTextElement(element)
|
|
328
|
-
? getContainerElement(element) || element
|
|
391
|
+
? getContainerElement(element, allElementsMap) || element
|
|
329
392
|
: element;
|
|
330
393
|
if (frame) {
|
|
331
394
|
// Perf improvement:
|
|
@@ -337,11 +400,11 @@ export const isElementInFrame = (element, allElements, appState) => {
|
|
|
337
400
|
return true;
|
|
338
401
|
}
|
|
339
402
|
if (_element.groupIds.length === 0) {
|
|
340
|
-
return elementOverlapsWithFrame(_element, frame);
|
|
403
|
+
return elementOverlapsWithFrame(_element, frame, allElementsMap);
|
|
341
404
|
}
|
|
342
|
-
const allElementsInGroup = new Set(_element.groupIds.flatMap((gid) => getElementsInGroup(
|
|
405
|
+
const allElementsInGroup = new Set(_element.groupIds.flatMap((gid) => getElementsInGroup(allElementsMap, gid)));
|
|
343
406
|
if (appState.editingGroupId && appState.selectedElementsAreBeingDragged) {
|
|
344
|
-
const selectedElements = new Set(getSelectedElements(
|
|
407
|
+
const selectedElements = new Set(getSelectedElements(allElementsMap, appState));
|
|
345
408
|
const editingGroupOverlapsFrame = appState.frameToHighlight !== null;
|
|
346
409
|
if (editingGroupOverlapsFrame) {
|
|
347
410
|
return true;
|
|
@@ -356,7 +419,7 @@ export const isElementInFrame = (element, allElements, appState) => {
|
|
|
356
419
|
}
|
|
357
420
|
}
|
|
358
421
|
for (const elementInGroup of allElementsInGroup) {
|
|
359
|
-
if (elementOverlapsWithFrame(elementInGroup, frame)) {
|
|
422
|
+
if (elementOverlapsWithFrame(elementInGroup, frame, allElementsMap)) {
|
|
360
423
|
return true;
|
|
361
424
|
}
|
|
362
425
|
}
|
|
@@ -364,10 +427,20 @@ export const isElementInFrame = (element, allElements, appState) => {
|
|
|
364
427
|
return false;
|
|
365
428
|
};
|
|
366
429
|
export const getFrameLikeTitle = (element, frameIdx) => {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
430
|
+
// TODO name frames "AI" only if specific to AI frames
|
|
431
|
+
return element.name === null
|
|
432
|
+
? isFrameElement(element)
|
|
433
|
+
? `Frame ${frameIdx}`
|
|
434
|
+
: `AI Frame $${frameIdx}`
|
|
435
|
+
: element.name;
|
|
436
|
+
};
|
|
437
|
+
export const getElementsOverlappingFrame = (elements, frame) => {
|
|
438
|
+
return (elementsOverlappingBBox({
|
|
439
|
+
elements,
|
|
440
|
+
bounds: frame,
|
|
441
|
+
type: "overlap",
|
|
442
|
+
})
|
|
443
|
+
// removes elements who are overlapping, but are in a different frame,
|
|
444
|
+
// and thus invisible in target frame
|
|
445
|
+
.filter((el) => !el.frameId || el.frameId === frame.id));
|
|
373
446
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GroupId, ExcalidrawElement, NonDeleted, NonDeletedExcalidrawElement } from "./element/types";
|
|
1
|
+
import { GroupId, ExcalidrawElement, NonDeleted, NonDeletedExcalidrawElement, ElementsMapOrArray, ElementsMap } from "./element/types";
|
|
2
2
|
import { AppClassProperties, AppState, InteractiveCanvasAppState } from "./types";
|
|
3
3
|
import { Mutable } from "./utility-types";
|
|
4
4
|
export declare const selectGroup: (groupId: GroupId, appState: InteractiveCanvasAppState, elements: readonly NonDeleted<ExcalidrawElement>[]) => Pick<InteractiveCanvasAppState, "selectedGroupIds" | "selectedElementIds" | "editingGroupId">;
|
|
@@ -18,7 +18,7 @@ export declare const selectGroupsFromGivenElements: (elements: readonly NonDelet
|
|
|
18
18
|
};
|
|
19
19
|
export declare const editGroupForSelectedElement: (appState: AppState, element: NonDeleted<ExcalidrawElement>) => AppState;
|
|
20
20
|
export declare const isElementInGroup: (element: ExcalidrawElement, groupId: string) => boolean;
|
|
21
|
-
export declare const getElementsInGroup: (elements:
|
|
21
|
+
export declare const getElementsInGroup: (elements: ElementsMapOrArray, groupId: string) => ExcalidrawElement[];
|
|
22
22
|
export declare const getSelectedGroupIdForElement: (element: ExcalidrawElement, selectedGroupIds: {
|
|
23
23
|
[groupId: string]: boolean;
|
|
24
24
|
}) => string | undefined;
|
|
@@ -27,5 +27,5 @@ export declare const addToGroup: (prevGroupIds: ExcalidrawElement["groupIds"], n
|
|
|
27
27
|
export declare const removeFromSelectedGroups: (groupIds: ExcalidrawElement["groupIds"], selectedGroupIds: {
|
|
28
28
|
[groupId: string]: boolean;
|
|
29
29
|
}) => string[];
|
|
30
|
-
export declare const getMaximumGroups: (elements: ExcalidrawElement[]) => ExcalidrawElement[][];
|
|
30
|
+
export declare const getMaximumGroups: (elements: ExcalidrawElement[], elementsMap: ElementsMap) => ExcalidrawElement[][];
|
|
31
31
|
export declare const elementsAreInSameGroup: (elements: ExcalidrawElement[]) => boolean;
|
|
@@ -171,7 +171,15 @@ export const editGroupForSelectedElement = (appState, element) => {
|
|
|
171
171
|
};
|
|
172
172
|
};
|
|
173
173
|
export const isElementInGroup = (element, groupId) => element.groupIds.includes(groupId);
|
|
174
|
-
export const getElementsInGroup = (elements, groupId) =>
|
|
174
|
+
export const getElementsInGroup = (elements, groupId) => {
|
|
175
|
+
const elementsInGroup = [];
|
|
176
|
+
for (const element of elements.values()) {
|
|
177
|
+
if (isElementInGroup(element, groupId)) {
|
|
178
|
+
elementsInGroup.push(element);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return elementsInGroup;
|
|
182
|
+
};
|
|
175
183
|
export const getSelectedGroupIdForElement = (element, selectedGroupIds) => element.groupIds.find((groupId) => selectedGroupIds[groupId]);
|
|
176
184
|
export const getNewGroupIdsForDuplication = (groupIds, editingGroupId, mapper) => {
|
|
177
185
|
const copy = [...groupIds];
|
|
@@ -195,7 +203,7 @@ export const addToGroup = (prevGroupIds, newGroupId, editingGroupId) => {
|
|
|
195
203
|
return groupIds;
|
|
196
204
|
};
|
|
197
205
|
export const removeFromSelectedGroups = (groupIds, selectedGroupIds) => groupIds.filter((groupId) => !selectedGroupIds[groupId]);
|
|
198
|
-
export const getMaximumGroups = (elements) => {
|
|
206
|
+
export const getMaximumGroups = (elements, elementsMap) => {
|
|
199
207
|
const groups = new Map();
|
|
200
208
|
elements.forEach((element) => {
|
|
201
209
|
const groupId = element.groupIds.length === 0
|
|
@@ -203,7 +211,7 @@ export const getMaximumGroups = (elements) => {
|
|
|
203
211
|
: element.groupIds[element.groupIds.length - 1];
|
|
204
212
|
const currentGroupMembers = groups.get(groupId) || [];
|
|
205
213
|
// Include bound text if present when grouping
|
|
206
|
-
const boundTextElement = getBoundTextElement(element);
|
|
214
|
+
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
207
215
|
if (boundTextElement) {
|
|
208
216
|
currentGroupMembers.push(boundTextElement);
|
|
209
217
|
}
|
|
@@ -14,7 +14,7 @@ declare const clearAppStatePropertiesForHistory: (appState: AppState) => {
|
|
|
14
14
|
viewBackgroundColor: string;
|
|
15
15
|
editingLinearElement: import("./element/linearElementEditor").LinearElementEditor | null;
|
|
16
16
|
editingGroupId: string | null;
|
|
17
|
-
name: string;
|
|
17
|
+
name: string | null;
|
|
18
18
|
};
|
|
19
19
|
declare class History {
|
|
20
20
|
private elementCache;
|
|
@@ -2,7 +2,7 @@ import { atom, useAtom } from "jotai";
|
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
import { COLOR_PALETTE } from "../colors";
|
|
4
4
|
import { jotaiScope } from "../jotai";
|
|
5
|
-
import { exportToSvg } from "../../utils/
|
|
5
|
+
import { exportToSvg } from "../../utils/export";
|
|
6
6
|
export const libraryItemSvgsCache = atom(new Map());
|
|
7
7
|
const exportLibraryItemToSvg = async (elements) => {
|
|
8
8
|
return await exportToSvg({
|