@tldraw/editor 5.4.0-next.09eca5dee30d → 5.4.0-next.0a83c4ec44f1
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/dist-cjs/index.d.ts +114 -47
- package/dist-cjs/index.js +4 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +7 -2
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +6 -8
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js +1 -3
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +1 -1
- package/dist-cjs/lib/config/TLUserPreferences.js +6 -2
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +1 -1
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +181 -294
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js +7 -3
- package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +3 -3
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +8 -8
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -1
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +79 -6
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +7 -0
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +0 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +6 -3
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +12 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/OverlayManager.js +3 -7
- package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js +0 -1
- package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -1
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +1 -0
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +1 -1
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +3 -2
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/globals/editors.js +57 -0
- package/dist-cjs/lib/globals/editors.js.map +7 -0
- package/dist-cjs/lib/globals/menus.js +9 -4
- package/dist-cjs/lib/globals/menus.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -0
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useDocumentEvents.js +39 -9
- package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useLocalStore.js +10 -6
- package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +1 -0
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +2 -1
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/license/LicenseManager.js +9 -2
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/license/LicenseProvider.js +16 -3
- package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
- package/dist-cjs/lib/license/useLicenseManagerState.js +5 -4
- package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +2 -1
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +4 -3
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Group2d.js +63 -21
- package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +2 -1
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/deepLinks.js +5 -1
- package/dist-cjs/lib/utils/deepLinks.js.map +2 -2
- package/dist-cjs/lib/utils/normalizeWheel.js +2 -0
- package/dist-cjs/lib/utils/normalizeWheel.js.map +2 -2
- package/dist-cjs/lib/utils/rotation.js +1 -9
- package/dist-cjs/lib/utils/rotation.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +17 -0
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/lib/utils/sync/alerts.js +1 -1
- package/dist-cjs/lib/utils/sync/alerts.js.map +1 -1
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +114 -47
- package/dist-esm/index.mjs +9 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +9 -4
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +6 -8
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +1 -3
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +1 -1
- package/dist-esm/lib/config/TLUserPreferences.mjs +6 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +1 -1
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +189 -295
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs +7 -3
- package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +3 -3
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +9 -9
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -1
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +81 -8
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +7 -0
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +0 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -3
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +6 -3
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +12 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs +3 -7
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs +0 -1
- package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -1
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +1 -0
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +1 -1
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +3 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/globals/editors.mjs +37 -0
- package/dist-esm/lib/globals/editors.mjs.map +7 -0
- package/dist-esm/lib/globals/menus.mjs +9 -4
- package/dist-esm/lib/globals/menus.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -0
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useDocumentEvents.mjs +40 -10
- package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useLocalStore.mjs +11 -7
- package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +1 -0
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +2 -1
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseManager.mjs +9 -2
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseProvider.mjs +16 -3
- package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
- package/dist-esm/lib/license/useLicenseManagerState.mjs +5 -4
- package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +2 -1
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +4 -3
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +63 -21
- package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +2 -1
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/deepLinks.mjs +5 -1
- package/dist-esm/lib/utils/deepLinks.mjs.map +2 -2
- package/dist-esm/lib/utils/normalizeWheel.mjs +2 -0
- package/dist-esm/lib/utils/normalizeWheel.mjs.map +2 -2
- package/dist-esm/lib/utils/rotation.mjs +1 -9
- package/dist-esm/lib/utils/rotation.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +17 -0
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/alerts.mjs +1 -1
- package/dist-esm/lib/utils/sync/alerts.mjs.map +1 -1
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +13 -7
- package/src/index.ts +6 -1
- package/src/lib/TldrawEditor.tsx +16 -4
- package/src/lib/components/MenuClickCapture.tsx +19 -18
- package/src/lib/components/default-components/CanvasOverlays.tsx +1 -3
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/config/TLUserPreferences.test.ts +18 -1
- package/src/lib/config/TLUserPreferences.ts +8 -4
- package/src/lib/config/createTLStore.ts +1 -1
- package/src/lib/editor/Editor.ts +266 -383
- package/src/lib/editor/derivations/shapeIdsInCurrentPage.ts +7 -3
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +5 -3
- package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +9 -9
- package/src/lib/editor/managers/FontManager/FontManager.ts +2 -1
- package/src/lib/editor/managers/InputsManager/InputsManager.test.ts +199 -3
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +128 -9
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +12 -1
- package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +0 -2
- package/src/lib/editor/managers/TextManager/TextManager.ts +2 -6
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +13 -0
- package/src/lib/editor/managers/TickManager/TickManager.ts +9 -3
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +64 -3
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +18 -1
- package/src/lib/editor/overlays/OverlayManager.ts +3 -7
- package/src/lib/editor/overlays/strokeShapeIndicators.ts +0 -1
- package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +5 -1
- package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +3 -0
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +4 -1
- package/src/lib/editor/tools/StateNode.test.ts +64 -0
- package/src/lib/editor/tools/StateNode.ts +12 -2
- package/src/lib/globals/editors.test.ts +76 -0
- package/src/lib/globals/editors.ts +53 -0
- package/src/lib/globals/menus.test.ts +33 -0
- package/src/lib/globals/menus.ts +11 -4
- package/src/lib/hooks/useCanvasEvents.ts +2 -0
- package/src/lib/hooks/useDocumentEvents.ts +60 -16
- package/src/lib/hooks/useLocalStore.ts +16 -8
- package/src/lib/hooks/usePassThroughWheelEvents.ts +3 -0
- package/src/lib/hooks/usePeerIds.ts +2 -1
- package/src/lib/license/LicenseManager.test.ts +160 -0
- package/src/lib/license/LicenseManager.ts +13 -4
- package/src/lib/license/LicenseProvider.tsx +24 -3
- package/src/lib/license/useLicenseManagerState.ts +8 -6
- package/src/lib/primitives/Box.test.ts +9 -1
- package/src/lib/primitives/Box.ts +3 -1
- package/src/lib/primitives/Vec.test.ts +10 -0
- package/src/lib/primitives/Vec.ts +4 -4
- package/src/lib/primitives/geometry/Arc2d.test.ts +226 -3
- package/src/lib/primitives/geometry/CubicBezier2d.test.ts +173 -3
- package/src/lib/primitives/geometry/CubicSpline2d.test.ts +160 -3
- package/src/lib/primitives/geometry/Ellipse2d.test.ts +243 -3
- package/src/lib/primitives/geometry/Geometry2d.test.ts +553 -1
- package/src/lib/primitives/geometry/Group2d.test.ts +398 -3
- package/src/lib/primitives/geometry/Group2d.ts +63 -27
- package/src/lib/primitives/geometry/Polyline2d.test.ts +207 -0
- package/src/lib/primitives/geometry/Stadium2d.test.ts +191 -3
- package/src/lib/primitives/utils.test.ts +10 -1
- package/src/lib/primitives/utils.ts +4 -1
- package/src/lib/test/useCanvasEvents.test.tsx +74 -0
- package/src/lib/test/useDocumentEvents.test.tsx +107 -0
- package/src/lib/test/usePassThroughWheelEvents.test.tsx +25 -2
- package/src/lib/utils/deepLinks.test.ts +15 -0
- package/src/lib/utils/deepLinks.ts +7 -1
- package/src/lib/utils/normalizeWheel.test.ts +39 -0
- package/src/lib/utils/normalizeWheel.ts +6 -0
- package/src/lib/utils/rotation.ts +4 -12
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +56 -0
- package/src/lib/utils/sync/TLLocalSyncClient.ts +24 -0
- package/src/lib/utils/sync/alerts.ts +1 -1
- package/src/version.ts +3 -3
- package/src/lib/primitives/geometry/Polyline.test.ts +0 -5
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
Result,
|
|
40
40
|
ZERO_INDEX_KEY,
|
|
41
41
|
annotateError,
|
|
42
|
+
areArraysShallowEqual,
|
|
42
43
|
assert,
|
|
43
44
|
assertExists,
|
|
44
45
|
bind,
|
|
@@ -83,6 +84,7 @@ import {
|
|
|
83
84
|
import { getOwnerWindow } from "../exports/domUtils.mjs";
|
|
84
85
|
import { exportToSvg } from "../exports/exportToSvg.mjs";
|
|
85
86
|
import { getSvgAsImageWithOptions, trimSvgToContent } from "../exports/getSvgAsImage.mjs";
|
|
87
|
+
import { registerMountedEditor, unregisterMountedEditor } from "../globals/editors.mjs";
|
|
86
88
|
import { tlmenus } from "../globals/menus.mjs";
|
|
87
89
|
import { tltime } from "../globals/time.mjs";
|
|
88
90
|
import { defaultTldrawOptions } from "../options.mjs";
|
|
@@ -91,7 +93,13 @@ import { EASINGS } from "../primitives/easings.mjs";
|
|
|
91
93
|
import { Group2d } from "../primitives/geometry/Group2d.mjs";
|
|
92
94
|
import { intersectPolygonPolygon } from "../primitives/intersect.mjs";
|
|
93
95
|
import { Mat } from "../primitives/Mat.mjs";
|
|
94
|
-
import {
|
|
96
|
+
import {
|
|
97
|
+
HALF_PI,
|
|
98
|
+
approximately,
|
|
99
|
+
areAnglesCompatible,
|
|
100
|
+
clamp,
|
|
101
|
+
pointInPolygon
|
|
102
|
+
} from "../primitives/utils.mjs";
|
|
95
103
|
import { Vec } from "../primitives/Vec.mjs";
|
|
96
104
|
import { areShapesContentEqual } from "../utils/areShapesContentEqual.mjs";
|
|
97
105
|
import { dataUrlToFile } from "../utils/assets.mjs";
|
|
@@ -289,6 +297,10 @@ class Editor extends EventEmitter {
|
|
|
289
297
|
if (!nextPageState) nextPageState = { ...prevPageState };
|
|
290
298
|
nextPageState.editingShapeId = null;
|
|
291
299
|
}
|
|
300
|
+
if (prevPageState.croppingShapeId && shapesNoLongerInPage.has(prevPageState.croppingShapeId)) {
|
|
301
|
+
if (!nextPageState) nextPageState = { ...prevPageState };
|
|
302
|
+
nextPageState.croppingShapeId = null;
|
|
303
|
+
}
|
|
292
304
|
const hintingShapeIds = prevPageState.hintingShapeIds.filter(
|
|
293
305
|
(id) => !shapesNoLongerInPage.has(id)
|
|
294
306
|
);
|
|
@@ -531,10 +543,11 @@ class Editor extends EventEmitter {
|
|
|
531
543
|
this.cancelDoubleClick();
|
|
532
544
|
}
|
|
533
545
|
if (prev?.selectedShapeIds !== next?.selectedShapeIds) {
|
|
546
|
+
const selectedShapeIds = new Set(next.selectedShapeIds);
|
|
534
547
|
const filtered = next.selectedShapeIds.filter((id) => {
|
|
535
548
|
let parentId = this.getShape(id)?.parentId;
|
|
536
549
|
while (isShapeId(parentId)) {
|
|
537
|
-
if (
|
|
550
|
+
if (selectedShapeIds.has(parentId)) {
|
|
538
551
|
return false;
|
|
539
552
|
}
|
|
540
553
|
parentId = this.getShape(parentId)?.parentId;
|
|
@@ -604,9 +617,11 @@ class Editor extends EventEmitter {
|
|
|
604
617
|
this.on("tick", this._flushEventsForTick);
|
|
605
618
|
this.on("mount", () => {
|
|
606
619
|
this._isMounted.set(true);
|
|
620
|
+
registerMountedEditor(this);
|
|
607
621
|
});
|
|
608
622
|
this.on("unmount", () => {
|
|
609
623
|
this._isMounted.set(false);
|
|
624
|
+
unregisterMountedEditor(this);
|
|
610
625
|
});
|
|
611
626
|
this.timers.requestAnimationFrame(() => {
|
|
612
627
|
this._tickManager.start();
|
|
@@ -616,7 +631,10 @@ class Editor extends EventEmitter {
|
|
|
616
631
|
const mode = this.store.props.collaboration.mode;
|
|
617
632
|
this.disposables.add(
|
|
618
633
|
react("update collaboration mode", () => {
|
|
619
|
-
|
|
634
|
+
const isReadonly = mode.get() === "readonly";
|
|
635
|
+
unsafe__withoutCapture(
|
|
636
|
+
() => this._updateInstanceState({ isReadonly }, { history: "ignore" })
|
|
637
|
+
);
|
|
620
638
|
})
|
|
621
639
|
);
|
|
622
640
|
}
|
|
@@ -646,6 +664,14 @@ class Editor extends EventEmitter {
|
|
|
646
664
|
);
|
|
647
665
|
}
|
|
648
666
|
options;
|
|
667
|
+
/**
|
|
668
|
+
* The license manager whose feature flags apply to this editor. Assigned by `<TldrawEditor />`
|
|
669
|
+
* when it creates the editor, so that UI rendered outside the editor tree can resolve the
|
|
670
|
+
* editor's license through the editor instance. Undefined for editors created directly.
|
|
671
|
+
*
|
|
672
|
+
* @internal
|
|
673
|
+
*/
|
|
674
|
+
licenseManager;
|
|
649
675
|
contextId = uniqueId();
|
|
650
676
|
/**
|
|
651
677
|
* The editor's store
|
|
@@ -840,6 +866,7 @@ class Editor extends EventEmitter {
|
|
|
840
866
|
if (this._isMounted.get()) {
|
|
841
867
|
this.emit("unmount");
|
|
842
868
|
}
|
|
869
|
+
unregisterMountedEditor(this);
|
|
843
870
|
this.stopCameraAnimation();
|
|
844
871
|
if (this.getInstanceState().followingUserId) {
|
|
845
872
|
this.stopFollowingUser();
|
|
@@ -965,7 +992,7 @@ class Editor extends EventEmitter {
|
|
|
965
992
|
getShapeUtil(arg) {
|
|
966
993
|
const type = typeof arg === "string" ? arg : arg.type;
|
|
967
994
|
const shapeUtil = getOwnProperty(this.shapeUtils, type);
|
|
968
|
-
|
|
995
|
+
if (!shapeUtil) throw new Error(`No shape util found for type "${type}"`);
|
|
969
996
|
return shapeUtil;
|
|
970
997
|
}
|
|
971
998
|
hasShapeUtil(arg) {
|
|
@@ -1754,7 +1781,9 @@ class Editor extends EventEmitter {
|
|
|
1754
1781
|
const selectedShapes = this.getSelectedShapes();
|
|
1755
1782
|
if (!selectedShapes.length) return;
|
|
1756
1783
|
const selectedShape = selectedShapes[0];
|
|
1757
|
-
const children =
|
|
1784
|
+
const children = compact(
|
|
1785
|
+
this.getSortedChildIdsForParent(selectedShape.id).map((id) => this.getShape(id))
|
|
1786
|
+
);
|
|
1758
1787
|
const sortedChildren = this._getShapesInReadingOrder(children);
|
|
1759
1788
|
if (sortedChildren.length === 0) return;
|
|
1760
1789
|
this._selectShapesAndZoom([sortedChildren[0].id]);
|
|
@@ -1821,18 +1850,13 @@ class Editor extends EventEmitter {
|
|
|
1821
1850
|
* @internal
|
|
1822
1851
|
*/
|
|
1823
1852
|
getShapesSharedRotation(shapeIds) {
|
|
1824
|
-
let foundFirst = false;
|
|
1825
1853
|
let rotation = 0;
|
|
1826
1854
|
for (let i = 0, n = shapeIds.length; i < n; i++) {
|
|
1827
|
-
const
|
|
1828
|
-
if (
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
}
|
|
1833
|
-
} else {
|
|
1834
|
-
foundFirst = true;
|
|
1835
|
-
rotation = pageTransform.rotation();
|
|
1855
|
+
const pageRotation = this.getShapePageTransform(shapeIds[i]).rotation();
|
|
1856
|
+
if (i === 0) {
|
|
1857
|
+
rotation = pageRotation;
|
|
1858
|
+
} else if (pageRotation !== rotation) {
|
|
1859
|
+
return 0;
|
|
1836
1860
|
}
|
|
1837
1861
|
}
|
|
1838
1862
|
return rotation;
|
|
@@ -1858,11 +1882,9 @@ class Editor extends EventEmitter {
|
|
|
1858
1882
|
return bounds;
|
|
1859
1883
|
}
|
|
1860
1884
|
const boxFromRotatedVertices = Box.FromPoints(
|
|
1861
|
-
shapeIds.flatMap(
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
return pageTransform.applyToPoints(this.getShapeGeometry(id).bounds.corners);
|
|
1865
|
-
}).map((p) => p.rot(-selectionRotation))
|
|
1885
|
+
shapeIds.flatMap(
|
|
1886
|
+
(id) => this.getShapePageTransform(id).applyToPoints(this.getShapeGeometry(id).bounds.corners)
|
|
1887
|
+
).map((p) => p.rot(-selectionRotation))
|
|
1866
1888
|
);
|
|
1867
1889
|
boxFromRotatedVertices.point = boxFromRotatedVertices.point.rot(selectionRotation);
|
|
1868
1890
|
return boxFromRotatedVertices;
|
|
@@ -1873,9 +1895,14 @@ class Editor extends EventEmitter {
|
|
|
1873
1895
|
getSelectionRotatedScreenBounds() {
|
|
1874
1896
|
const bounds = this.getSelectionRotatedPageBounds();
|
|
1875
1897
|
if (!bounds) return void 0;
|
|
1876
|
-
const
|
|
1877
|
-
const zoom = this.
|
|
1878
|
-
return new Box(
|
|
1898
|
+
const screenBounds = this.getViewportScreenBounds();
|
|
1899
|
+
const { x: cx, y: cy, z: zoom } = this.getCamera();
|
|
1900
|
+
return new Box(
|
|
1901
|
+
(bounds.x + cx) * zoom + screenBounds.x,
|
|
1902
|
+
(bounds.y + cy) * zoom + screenBounds.y,
|
|
1903
|
+
bounds.width * zoom,
|
|
1904
|
+
bounds.height * zoom
|
|
1905
|
+
);
|
|
1879
1906
|
}
|
|
1880
1907
|
getFocusedGroupId() {
|
|
1881
1908
|
return this.getCurrentPageState().focusedGroupId ?? this.getCurrentPageId();
|
|
@@ -1976,42 +2003,28 @@ class Editor extends EventEmitter {
|
|
|
1976
2003
|
*/
|
|
1977
2004
|
setEditingShape(shape) {
|
|
1978
2005
|
const id = typeof shape === "string" ? shape : shape?.id ?? null;
|
|
1979
|
-
if (!id)
|
|
2006
|
+
if (id && !this.canEditShape(id)) return this;
|
|
2007
|
+
this.run(() => {
|
|
2008
|
+
const prevEditingShapeId = this.getEditingShapeId();
|
|
2009
|
+
if (prevEditingShapeId) {
|
|
2010
|
+
const prevEditingShape = this.getShape(prevEditingShapeId);
|
|
2011
|
+
if (prevEditingShape) {
|
|
2012
|
+
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
1980
2015
|
this.run(
|
|
1981
2016
|
() => {
|
|
1982
|
-
const prevEditingShapeId = this.getEditingShapeId();
|
|
1983
|
-
if (prevEditingShapeId) {
|
|
1984
|
-
const prevEditingShape = this.getShape(prevEditingShapeId);
|
|
1985
|
-
if (prevEditingShape) {
|
|
1986
|
-
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
|
|
1987
|
-
}
|
|
1988
|
-
}
|
|
1989
2017
|
this._updateCurrentPageState({ editingShapeId: null });
|
|
1990
2018
|
this._currentRichTextEditor.set(null);
|
|
2019
|
+
if (!id) return;
|
|
2020
|
+
this.select(id);
|
|
2021
|
+
this._updateCurrentPageState({ editingShapeId: id });
|
|
2022
|
+
const nextEditingShape = this.getShape(id);
|
|
2023
|
+
this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
|
|
1991
2024
|
},
|
|
1992
2025
|
{ history: "ignore" }
|
|
1993
2026
|
);
|
|
1994
|
-
|
|
1995
|
-
}
|
|
1996
|
-
if (!this.canEditShape(id)) return this;
|
|
1997
|
-
this.run(
|
|
1998
|
-
() => {
|
|
1999
|
-
const prevEditingShapeId = this.getEditingShapeId();
|
|
2000
|
-
if (prevEditingShapeId) {
|
|
2001
|
-
const prevEditingShape = this.getShape(prevEditingShapeId);
|
|
2002
|
-
if (prevEditingShape) {
|
|
2003
|
-
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
|
|
2004
|
-
}
|
|
2005
|
-
}
|
|
2006
|
-
this._updateCurrentPageState({ editingShapeId: null });
|
|
2007
|
-
this._currentRichTextEditor.set(null);
|
|
2008
|
-
this.select(id);
|
|
2009
|
-
this._updateCurrentPageState({ editingShapeId: id });
|
|
2010
|
-
const nextEditingShape = this.getShape(id);
|
|
2011
|
-
this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
|
|
2012
|
-
},
|
|
2013
|
-
{ history: "ignore" }
|
|
2014
|
-
);
|
|
2027
|
+
});
|
|
2015
2028
|
return this;
|
|
2016
2029
|
}
|
|
2017
2030
|
// Rich text editor
|
|
@@ -2117,19 +2130,12 @@ class Editor extends EventEmitter {
|
|
|
2117
2130
|
* @public
|
|
2118
2131
|
*/
|
|
2119
2132
|
setErasingShapes(shapes) {
|
|
2120
|
-
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((shape) => shape.id);
|
|
2133
|
+
const ids = typeof shapes[0] === "string" ? shapes.slice() : shapes.map((shape) => shape.id);
|
|
2121
2134
|
ids.sort();
|
|
2122
2135
|
const erasingShapeIds = this.getErasingShapeIds();
|
|
2123
2136
|
this.run(
|
|
2124
2137
|
() => {
|
|
2125
|
-
if (ids
|
|
2126
|
-
for (let i = 0; i < ids.length; i++) {
|
|
2127
|
-
if (ids[i] !== erasingShapeIds[i]) {
|
|
2128
|
-
this._updateCurrentPageState({ erasingShapeIds: ids });
|
|
2129
|
-
break;
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
2132
|
-
} else {
|
|
2138
|
+
if (!areArraysShallowEqual(ids, erasingShapeIds)) {
|
|
2133
2139
|
this._updateCurrentPageState({ erasingShapeIds: ids });
|
|
2134
2140
|
}
|
|
2135
2141
|
},
|
|
@@ -2162,6 +2168,7 @@ class Editor extends EventEmitter {
|
|
|
2162
2168
|
if (!_shape) return false;
|
|
2163
2169
|
const util = this.getShapeUtil(_shape);
|
|
2164
2170
|
if (!util.canCrop(_shape)) return false;
|
|
2171
|
+
if (this.getIsReadonly()) return false;
|
|
2165
2172
|
if (this.isShapeOrAncestorLocked(_shape)) return false;
|
|
2166
2173
|
return true;
|
|
2167
2174
|
}
|
|
@@ -2226,11 +2233,11 @@ class Editor extends EventEmitter {
|
|
|
2226
2233
|
const collaborators = this.getCollaborators();
|
|
2227
2234
|
let leaderPresence = null;
|
|
2228
2235
|
while (targetUserId && !visited.includes(targetUserId)) {
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2236
|
+
const nextPresence = collaborators.find((c) => c.userId === targetUserId);
|
|
2237
|
+
if (!nextPresence) break;
|
|
2238
|
+
leaderPresence = nextPresence;
|
|
2239
|
+
targetUserId = nextPresence.followingUserId ?? null;
|
|
2240
|
+
visited.push(nextPresence.userId);
|
|
2234
2241
|
}
|
|
2235
2242
|
return leaderPresence;
|
|
2236
2243
|
}
|
|
@@ -2293,39 +2300,7 @@ class Editor extends EventEmitter {
|
|
|
2293
2300
|
*
|
|
2294
2301
|
* @public */
|
|
2295
2302
|
getInitialZoom() {
|
|
2296
|
-
|
|
2297
|
-
if (!cameraOptions.constraints) return 1;
|
|
2298
|
-
if (cameraOptions.constraints.initialZoom === "default") return 1;
|
|
2299
|
-
const { zx, zy } = getCameraFitXFitY(this, cameraOptions);
|
|
2300
|
-
switch (cameraOptions.constraints.initialZoom) {
|
|
2301
|
-
case "fit-min": {
|
|
2302
|
-
return Math.max(zx, zy);
|
|
2303
|
-
}
|
|
2304
|
-
case "fit-max": {
|
|
2305
|
-
return Math.min(zx, zy);
|
|
2306
|
-
}
|
|
2307
|
-
case "fit-x": {
|
|
2308
|
-
return zx;
|
|
2309
|
-
}
|
|
2310
|
-
case "fit-y": {
|
|
2311
|
-
return zy;
|
|
2312
|
-
}
|
|
2313
|
-
case "fit-min-100": {
|
|
2314
|
-
return Math.min(1, Math.max(zx, zy));
|
|
2315
|
-
}
|
|
2316
|
-
case "fit-max-100": {
|
|
2317
|
-
return Math.min(1, Math.min(zx, zy));
|
|
2318
|
-
}
|
|
2319
|
-
case "fit-x-100": {
|
|
2320
|
-
return Math.min(1, zx);
|
|
2321
|
-
}
|
|
2322
|
-
case "fit-y-100": {
|
|
2323
|
-
return Math.min(1, zy);
|
|
2324
|
-
}
|
|
2325
|
-
default: {
|
|
2326
|
-
throw exhaustiveSwitchError(cameraOptions.constraints.initialZoom);
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2303
|
+
return this._getFitZoom(this.getCameraOptions().constraints?.initialZoom ?? "default");
|
|
2329
2304
|
}
|
|
2330
2305
|
/**
|
|
2331
2306
|
* Get the camera's base level for calculating actual zoom levels based on the zoom steps.
|
|
@@ -2337,11 +2312,13 @@ class Editor extends EventEmitter {
|
|
|
2337
2312
|
*
|
|
2338
2313
|
* @public */
|
|
2339
2314
|
getBaseZoom() {
|
|
2315
|
+
return this._getFitZoom(this.getCameraOptions().constraints?.baseZoom ?? "default");
|
|
2316
|
+
}
|
|
2317
|
+
_getFitZoom(fit) {
|
|
2340
2318
|
const cameraOptions = this.getCameraOptions();
|
|
2341
|
-
if (!cameraOptions.constraints) return 1;
|
|
2342
|
-
if (cameraOptions.constraints.baseZoom === "default") return 1;
|
|
2319
|
+
if (!cameraOptions.constraints || fit === "default") return 1;
|
|
2343
2320
|
const { zx, zy } = getCameraFitXFitY(this, cameraOptions);
|
|
2344
|
-
switch (
|
|
2321
|
+
switch (fit) {
|
|
2345
2322
|
case "fit-min": {
|
|
2346
2323
|
return Math.max(zx, zy);
|
|
2347
2324
|
}
|
|
@@ -2367,7 +2344,7 @@ class Editor extends EventEmitter {
|
|
|
2367
2344
|
return Math.min(1, zy);
|
|
2368
2345
|
}
|
|
2369
2346
|
default: {
|
|
2370
|
-
throw exhaustiveSwitchError(
|
|
2347
|
+
throw exhaustiveSwitchError(fit);
|
|
2371
2348
|
}
|
|
2372
2349
|
}
|
|
2373
2350
|
}
|
|
@@ -2401,7 +2378,7 @@ class Editor extends EventEmitter {
|
|
|
2401
2378
|
...this._cameraOptions.__unsafe__getWithoutCapture(),
|
|
2402
2379
|
...opts
|
|
2403
2380
|
});
|
|
2404
|
-
if (next.zoomSteps
|
|
2381
|
+
if (!next.zoomSteps || next.zoomSteps.length < 1) next.zoomSteps = [1];
|
|
2405
2382
|
this._cameraOptions.set(next);
|
|
2406
2383
|
this.setCamera(this.getCamera());
|
|
2407
2384
|
return this;
|
|
@@ -2422,8 +2399,8 @@ class Editor extends EventEmitter {
|
|
|
2422
2399
|
const vsb = this.getViewportScreenBounds();
|
|
2423
2400
|
if (cameraOptions.constraints) {
|
|
2424
2401
|
const { constraints } = cameraOptions;
|
|
2425
|
-
const
|
|
2426
|
-
const
|
|
2402
|
+
const px = Math.min(constraints.padding.x, vsb.w / 2);
|
|
2403
|
+
const py = Math.min(constraints.padding.y, vsb.h / 2);
|
|
2427
2404
|
const bounds = Box.From(cameraOptions.constraints.bounds);
|
|
2428
2405
|
const zx = (vsb.w - px * 2) / bounds.w;
|
|
2429
2406
|
const zy = (vsb.h - py * 2) / bounds.h;
|
|
@@ -2462,12 +2439,12 @@ class Editor extends EventEmitter {
|
|
|
2462
2439
|
break;
|
|
2463
2440
|
}
|
|
2464
2441
|
case "inside": {
|
|
2465
|
-
if (z < zx) x = clamp(x, minX, (vsb.w - px) / z - bounds.w);
|
|
2442
|
+
if (z < zx) x = clamp(x, minX, (vsb.w - px) / z - bounds.w - bounds.x);
|
|
2466
2443
|
else x = clamp(x, minX + freeW, minX);
|
|
2467
2444
|
break;
|
|
2468
2445
|
}
|
|
2469
2446
|
case "outside": {
|
|
2470
|
-
x = clamp(x, px / z - bounds.w, (vsb.w - px) / z);
|
|
2447
|
+
x = clamp(x, px / z - bounds.w - bounds.x, (vsb.w - px) / z - bounds.x);
|
|
2471
2448
|
break;
|
|
2472
2449
|
}
|
|
2473
2450
|
case "free": {
|
|
@@ -2488,12 +2465,12 @@ class Editor extends EventEmitter {
|
|
|
2488
2465
|
break;
|
|
2489
2466
|
}
|
|
2490
2467
|
case "inside": {
|
|
2491
|
-
if (z < zy) y = clamp(y, minY, (vsb.h - py) / z - bounds.h);
|
|
2468
|
+
if (z < zy) y = clamp(y, minY, (vsb.h - py) / z - bounds.h - bounds.y);
|
|
2492
2469
|
else y = clamp(y, minY + freeH, minY);
|
|
2493
2470
|
break;
|
|
2494
2471
|
}
|
|
2495
2472
|
case "outside": {
|
|
2496
|
-
y = clamp(y, py / z - bounds.h, (vsb.h - py) / z);
|
|
2473
|
+
y = clamp(y, py / z - bounds.h - bounds.y, (vsb.h - py) / z - bounds.y);
|
|
2497
2474
|
break;
|
|
2498
2475
|
}
|
|
2499
2476
|
case "free": {
|
|
@@ -2861,9 +2838,9 @@ class Editor extends EventEmitter {
|
|
|
2861
2838
|
}
|
|
2862
2839
|
const remaining = duration - elapsed;
|
|
2863
2840
|
const t = easing(1 - remaining / duration);
|
|
2864
|
-
const left = start.minX
|
|
2865
|
-
const top = start.minY
|
|
2866
|
-
const right = start.maxX
|
|
2841
|
+
const left = lerp(start.minX, end.minX, t);
|
|
2842
|
+
const top = lerp(start.minY, end.minY, t);
|
|
2843
|
+
const right = lerp(start.maxX, end.maxX, t);
|
|
2867
2844
|
this._setCamera(new Vec(-left, -top, this.getViewportScreenBounds().width / (right - left)), {
|
|
2868
2845
|
force: true
|
|
2869
2846
|
});
|
|
@@ -2941,7 +2918,7 @@ class Editor extends EventEmitter {
|
|
|
2941
2918
|
let newCy = cy + dy;
|
|
2942
2919
|
let newCz = cz;
|
|
2943
2920
|
if (dirZ !== 0) {
|
|
2944
|
-
newCz = cz * (
|
|
2921
|
+
newCz = cz * Math.exp(dirZ * currentSpeed * elapsed);
|
|
2945
2922
|
const center = this.getViewportScreenCenter();
|
|
2946
2923
|
newCx += center.x / newCz - center.x / cz;
|
|
2947
2924
|
newCy += center.y / newCz - center.y / cz;
|
|
@@ -3379,12 +3356,12 @@ class Editor extends EventEmitter {
|
|
|
3379
3356
|
const renderingShapes = [];
|
|
3380
3357
|
let nextIndex = this.options.maxShapesPerPage * 2;
|
|
3381
3358
|
let nextBackgroundIndex = this.options.maxShapesPerPage;
|
|
3382
|
-
const erasingShapeIds = this.getErasingShapeIds();
|
|
3359
|
+
const erasingShapeIds = new Set(this.getErasingShapeIds());
|
|
3383
3360
|
const addShapeById = (id, opacity, isAncestorErasing) => {
|
|
3384
3361
|
const shape = this.getShape(id);
|
|
3385
3362
|
if (!shape) return;
|
|
3386
3363
|
if (this.isShapeHidden(shape)) {
|
|
3387
|
-
const isErasing = isAncestorErasing || erasingShapeIds.
|
|
3364
|
+
const isErasing = isAncestorErasing || erasingShapeIds.has(id);
|
|
3388
3365
|
for (const childId of this.getSortedChildIdsForParent(id)) {
|
|
3389
3366
|
addShapeById(childId, opacity, isErasing);
|
|
3390
3367
|
}
|
|
@@ -3394,7 +3371,7 @@ class Editor extends EventEmitter {
|
|
|
3394
3371
|
let isShapeErasing = false;
|
|
3395
3372
|
const util = this.getShapeUtil(shape);
|
|
3396
3373
|
if (useEditorState) {
|
|
3397
|
-
isShapeErasing = !isAncestorErasing && erasingShapeIds.
|
|
3374
|
+
isShapeErasing = !isAncestorErasing && erasingShapeIds.has(id);
|
|
3398
3375
|
if (isShapeErasing) {
|
|
3399
3376
|
opacity *= 0.32;
|
|
3400
3377
|
}
|
|
@@ -3986,10 +3963,8 @@ class Editor extends EventEmitter {
|
|
|
3986
3963
|
}
|
|
3987
3964
|
_getShapePageBoundsCache() {
|
|
3988
3965
|
return this.store.createComputedCache("pageBoundsCache", (shape) => {
|
|
3989
|
-
const pageTransform = this.getShapePageTransform(shape);
|
|
3990
|
-
if (!pageTransform) return void 0;
|
|
3991
3966
|
return Box.FromPoints(
|
|
3992
|
-
|
|
3967
|
+
this.getShapePageTransform(shape).applyToPoints(this.getShapeGeometry(shape).boundsVertices)
|
|
3993
3968
|
);
|
|
3994
3969
|
});
|
|
3995
3970
|
}
|
|
@@ -4107,7 +4082,9 @@ class Editor extends EventEmitter {
|
|
|
4107
4082
|
if (pageMask) {
|
|
4108
4083
|
if (pageMask.length === 0) return void 0;
|
|
4109
4084
|
const { corners } = pageBounds;
|
|
4110
|
-
if (corners.every((p, i) =>
|
|
4085
|
+
if (pageMask.length === corners.length && corners.every((p, i) => Vec.Equals(p, pageMask[i]))) {
|
|
4086
|
+
return pageBounds.clone();
|
|
4087
|
+
}
|
|
4111
4088
|
const intersection = intersectPolygonPolygon(pageMask, corners);
|
|
4112
4089
|
if (!intersection) return;
|
|
4113
4090
|
return Box.FromPoints(intersection);
|
|
@@ -4331,23 +4308,22 @@ class Editor extends EventEmitter {
|
|
|
4331
4308
|
let inMarginClosestToEdgeHit = null;
|
|
4332
4309
|
const searchMargin = Math.max(innerMargin, outerMargin, this.getHitTestMargin());
|
|
4333
4310
|
const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, searchMargin);
|
|
4334
|
-
const shapesToCheck =
|
|
4335
|
-
if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false;
|
|
4336
|
-
if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group"))
|
|
4337
|
-
return false;
|
|
4338
|
-
const pageMask = this.getShapeMask(shape);
|
|
4339
|
-
if (pageMask && !pointInPolygon(point, pageMask)) return false;
|
|
4340
|
-
if (filter && !filter(shape)) return false;
|
|
4341
|
-
return true;
|
|
4342
|
-
});
|
|
4311
|
+
const shapesToCheck = opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted();
|
|
4343
4312
|
for (let i = shapesToCheck.length - 1; i >= 0; i--) {
|
|
4344
4313
|
const shape = shapesToCheck[i];
|
|
4314
|
+
if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) continue;
|
|
4315
|
+
if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group")) {
|
|
4316
|
+
continue;
|
|
4317
|
+
}
|
|
4318
|
+
const pageMask = this.getShapeMask(shape);
|
|
4319
|
+
if (pageMask && !pointInPolygon(point, pageMask)) continue;
|
|
4320
|
+
if (filter && !filter(shape)) continue;
|
|
4345
4321
|
const geometry = this.getShapeGeometry(shape);
|
|
4346
4322
|
const isGroup = geometry instanceof Group2d;
|
|
4347
4323
|
const pointInShapeSpace = this.getPointInShapeSpace(shape, point);
|
|
4348
4324
|
const shapeUtil = this.getShapeUtil(shape);
|
|
4349
4325
|
const isShapeFrameLike = this.isShapeFrameLike(shape);
|
|
4350
|
-
if (isShapeFrameLike || (this.isShapeOfType(shape, "note") || this.isShapeOfType(shape, "arrow") || this.isShapeOfType(shape, "geo") && shape.props.fill === "none") && shapeUtil.getText(shape)?.trim()) {
|
|
4326
|
+
if (isGroup && (isShapeFrameLike || (this.isShapeOfType(shape, "note") || this.isShapeOfType(shape, "arrow") || this.isShapeOfType(shape, "geo") && shape.props.fill === "none") && shapeUtil.getText(shape)?.trim())) {
|
|
4351
4327
|
for (const childGeometry of geometry.children) {
|
|
4352
4328
|
if (childGeometry.isLabel && childGeometry.isPointInBounds(pointInShapeSpace)) {
|
|
4353
4329
|
return shape;
|
|
@@ -4446,11 +4422,15 @@ class Editor extends EventEmitter {
|
|
|
4446
4422
|
getShapesAtPoint(point, opts = {}) {
|
|
4447
4423
|
const margin = opts.margin ?? 0;
|
|
4448
4424
|
const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, margin);
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4425
|
+
const sorted = this.getCurrentPageShapesSorted();
|
|
4426
|
+
const result = [];
|
|
4427
|
+
for (let i = sorted.length - 1; i >= 0; i--) {
|
|
4428
|
+
const shape = sorted[i];
|
|
4429
|
+
if (this.isShapeHidden(shape)) continue;
|
|
4430
|
+
if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) continue;
|
|
4431
|
+
if (this.isPointInShape(shape, point, opts)) result.push(shape);
|
|
4432
|
+
}
|
|
4433
|
+
return result;
|
|
4454
4434
|
}
|
|
4455
4435
|
/**
|
|
4456
4436
|
* Get shape IDs within the given bounds.
|
|
@@ -4535,9 +4515,7 @@ class Editor extends EventEmitter {
|
|
|
4535
4515
|
const freshShape = this.getShape(id);
|
|
4536
4516
|
if (!freshShape) return new Vec(0, 0);
|
|
4537
4517
|
if (isPageId(freshShape.parentId)) return Vec.From(point);
|
|
4538
|
-
|
|
4539
|
-
if (!parentTransform) return Vec.From(point);
|
|
4540
|
-
return parentTransform.clone().invert().applyToPoint(point);
|
|
4518
|
+
return this.getShapePageTransform(freshShape.parentId).clone().invert().applyToPoint(point);
|
|
4541
4519
|
}
|
|
4542
4520
|
getCurrentPageShapes() {
|
|
4543
4521
|
return Array.from(this.getCurrentPageShapeIds(), (id) => this.store.get(id));
|
|
@@ -4649,23 +4627,7 @@ class Editor extends EventEmitter {
|
|
|
4649
4627
|
* @public
|
|
4650
4628
|
*/
|
|
4651
4629
|
isShapeInPage(shape, pageId = this.getCurrentPageId()) {
|
|
4652
|
-
|
|
4653
|
-
const shapeToCheck = this.getShape(id);
|
|
4654
|
-
if (!shapeToCheck) return false;
|
|
4655
|
-
let shapeIsInPage = false;
|
|
4656
|
-
if (shapeToCheck.parentId === pageId) {
|
|
4657
|
-
shapeIsInPage = true;
|
|
4658
|
-
} else {
|
|
4659
|
-
let parent = this.getShape(shapeToCheck.parentId);
|
|
4660
|
-
isInPageSearch: while (parent) {
|
|
4661
|
-
if (parent.parentId === pageId) {
|
|
4662
|
-
shapeIsInPage = true;
|
|
4663
|
-
break isInPageSearch;
|
|
4664
|
-
}
|
|
4665
|
-
parent = this.getShape(parent.parentId);
|
|
4666
|
-
}
|
|
4667
|
-
}
|
|
4668
|
-
return shapeIsInPage;
|
|
4630
|
+
return this.getAncestorPageId(shape) === pageId;
|
|
4669
4631
|
}
|
|
4670
4632
|
/**
|
|
4671
4633
|
* Get the id of the containing page for a given shape.
|
|
@@ -4746,10 +4708,7 @@ class Editor extends EventEmitter {
|
|
|
4746
4708
|
for (let i = 0; i < shapesToReparent.length; i++) {
|
|
4747
4709
|
const shape = shapesToReparent[i];
|
|
4748
4710
|
const pageTransform = this.getShapePageTransform(shape);
|
|
4749
|
-
|
|
4750
|
-
const pagePoint = pageTransform.point();
|
|
4751
|
-
if (!pagePoint) continue;
|
|
4752
|
-
const newPoint = invertedParentTransform.applyToPoint(pagePoint);
|
|
4711
|
+
const newPoint = invertedParentTransform.applyToPoint(pageTransform.point());
|
|
4753
4712
|
const newRotation = pageTransform.rotation() - parentPageRotation;
|
|
4754
4713
|
if (shape.id === parentId) {
|
|
4755
4714
|
throw Error("Attempted to reparent a shape to itself!");
|
|
@@ -4838,7 +4797,7 @@ class Editor extends EventEmitter {
|
|
|
4838
4797
|
*/
|
|
4839
4798
|
getShapeAndDescendantIds(ids) {
|
|
4840
4799
|
const shapeIds = /* @__PURE__ */ new Set();
|
|
4841
|
-
for (const shape of ids.map((id) => this.getShape(id)).sort(sortByIndex)) {
|
|
4800
|
+
for (const shape of compact(ids.map((id) => this.getShape(id))).sort(sortByIndex)) {
|
|
4842
4801
|
shapeIds.add(shape.id);
|
|
4843
4802
|
this.visitDescendants(shape, (descendantId) => {
|
|
4844
4803
|
shapeIds.add(descendantId);
|
|
@@ -4860,11 +4819,12 @@ class Editor extends EventEmitter {
|
|
|
4860
4819
|
const draggingShapes = compact(droppingShapes.map((s) => this.getShape(s))).filter(
|
|
4861
4820
|
(s) => !s.isLocked && !this.isShapeHidden(s)
|
|
4862
4821
|
);
|
|
4822
|
+
const excludedIds = this.getShapeAndDescendantIds(draggingShapes.map((s) => s.id));
|
|
4863
4823
|
const maybeDraggingOverShapes = this.getShapesAtPoint(point, {
|
|
4864
4824
|
hitInside: true,
|
|
4865
4825
|
margin: 0
|
|
4866
4826
|
}).filter(
|
|
4867
|
-
(s) => !droppingShapes.includes(s) && !s.isLocked && !this.isShapeHidden(s) && !
|
|
4827
|
+
(s) => !droppingShapes.includes(s) && !s.isLocked && !this.isShapeHidden(s) && !excludedIds.has(s.id)
|
|
4868
4828
|
);
|
|
4869
4829
|
for (const maybeDraggingOverShape of maybeDraggingOverShapes) {
|
|
4870
4830
|
const shapeUtil = this.getShapeUtil(maybeDraggingOverShape);
|
|
@@ -5117,8 +5077,7 @@ class Editor extends EventEmitter {
|
|
|
5117
5077
|
for (const id of ids) {
|
|
5118
5078
|
const shape = this.getShape(id);
|
|
5119
5079
|
const localDelta = Vec.From(offset);
|
|
5120
|
-
|
|
5121
|
-
if (parentTransform) localDelta.rot(-parentTransform.rotation());
|
|
5080
|
+
localDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5122
5081
|
changes.push(this.getChangesToTranslateShape(shape, localDelta.add(shape)));
|
|
5123
5082
|
}
|
|
5124
5083
|
this.updateShapes(changes);
|
|
@@ -5173,7 +5132,7 @@ class Editor extends EventEmitter {
|
|
|
5173
5132
|
if (!originalShape) continue;
|
|
5174
5133
|
let ox = 0;
|
|
5175
5134
|
let oy = 0;
|
|
5176
|
-
if (offset && initialIds.has(originalId)) {
|
|
5135
|
+
if (offset && initialIds.has(originalId) && !shapeIdSet.has(originalShape.parentId)) {
|
|
5177
5136
|
const parentTransform = this.getShapeParentTransform(originalShape);
|
|
5178
5137
|
const vec = new Vec(offset.x, offset.y).rot(-parentTransform.rotation());
|
|
5179
5138
|
ox = vec.x;
|
|
@@ -5287,26 +5246,17 @@ class Editor extends EventEmitter {
|
|
|
5287
5246
|
toggleLock(shapes) {
|
|
5288
5247
|
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
5289
5248
|
if (this.getIsReadonly() || ids.length === 0) return this;
|
|
5290
|
-
let allLocked = true
|
|
5249
|
+
let allLocked = true;
|
|
5291
5250
|
const shapesToToggle = [];
|
|
5292
5251
|
for (const id of ids) {
|
|
5293
5252
|
const shape = this.getShape(id);
|
|
5294
5253
|
if (shape) {
|
|
5295
5254
|
shapesToToggle.push(shape);
|
|
5296
|
-
if (shape.isLocked)
|
|
5297
|
-
allUnlocked = false;
|
|
5298
|
-
} else {
|
|
5299
|
-
allLocked = false;
|
|
5300
|
-
}
|
|
5255
|
+
if (!shape.isLocked) allLocked = false;
|
|
5301
5256
|
}
|
|
5302
5257
|
}
|
|
5303
5258
|
this.run(() => {
|
|
5304
|
-
if (
|
|
5305
|
-
this.updateShapes(
|
|
5306
|
-
shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: true }))
|
|
5307
|
-
);
|
|
5308
|
-
this.setSelectedShapes([]);
|
|
5309
|
-
} else if (allLocked) {
|
|
5259
|
+
if (allLocked) {
|
|
5310
5260
|
this.updateShapes(
|
|
5311
5261
|
shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: false }))
|
|
5312
5262
|
);
|
|
@@ -5314,6 +5264,7 @@ class Editor extends EventEmitter {
|
|
|
5314
5264
|
this.updateShapes(
|
|
5315
5265
|
shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: true }))
|
|
5316
5266
|
);
|
|
5267
|
+
this.setSelectedShapes([]);
|
|
5317
5268
|
}
|
|
5318
5269
|
});
|
|
5319
5270
|
return this;
|
|
@@ -5424,9 +5375,10 @@ class Editor extends EventEmitter {
|
|
|
5424
5375
|
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
5425
5376
|
let freshShapes = compact(ids.map((id) => this.getShape(id)));
|
|
5426
5377
|
if (opts?.filterAxisAligned) {
|
|
5427
|
-
freshShapes = freshShapes.filter(
|
|
5428
|
-
|
|
5429
|
-
|
|
5378
|
+
freshShapes = freshShapes.filter((s) => {
|
|
5379
|
+
const remainder = Math.abs(this.getShapePageTransform(s).rotation() % HALF_PI);
|
|
5380
|
+
return Math.min(remainder, HALF_PI - remainder) < 1e-9;
|
|
5381
|
+
});
|
|
5430
5382
|
}
|
|
5431
5383
|
const clusters = [];
|
|
5432
5384
|
const allBounds = [];
|
|
@@ -5591,9 +5543,9 @@ class Editor extends EventEmitter {
|
|
|
5591
5543
|
dim = "height";
|
|
5592
5544
|
}
|
|
5593
5545
|
let shapeGap = 0;
|
|
5546
|
+
shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
|
|
5594
5547
|
if (_gap === 0) {
|
|
5595
5548
|
const gaps = {};
|
|
5596
|
-
shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
|
|
5597
5549
|
for (let i = 0; i < len - 1; i++) {
|
|
5598
5550
|
const currCluster = shapeClustersToStack[i];
|
|
5599
5551
|
const nextCluster = shapeClustersToStack[i + 1];
|
|
@@ -5631,8 +5583,7 @@ class Editor extends EventEmitter {
|
|
|
5631
5583
|
const shapeDelta = delta.clone();
|
|
5632
5584
|
const parent = this.getShapeParent(shape);
|
|
5633
5585
|
if (parent) {
|
|
5634
|
-
|
|
5635
|
-
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5586
|
+
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5636
5587
|
}
|
|
5637
5588
|
shapeDelta.add(shape);
|
|
5638
5589
|
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
@@ -5670,7 +5621,7 @@ class Editor extends EventEmitter {
|
|
|
5670
5621
|
}
|
|
5671
5622
|
const commonBounds = Box.Common(allBounds);
|
|
5672
5623
|
const maxWidth = commonBounds.width;
|
|
5673
|
-
shapeClustersToPack.sort((a, b) =>
|
|
5624
|
+
shapeClustersToPack.sort((a, b) => b.pageBounds.width - a.pageBounds.width).sort((a, b) => b.pageBounds.height - a.pageBounds.height);
|
|
5674
5625
|
const startWidth = Math.max(Math.ceil(Math.sqrt(area / 0.95)), maxWidth);
|
|
5675
5626
|
const spaces = [new Box(commonBounds.x, commonBounds.y, startWidth, Infinity)];
|
|
5676
5627
|
let width = 0;
|
|
@@ -5718,8 +5669,7 @@ class Editor extends EventEmitter {
|
|
|
5718
5669
|
const shapeDelta = delta.clone();
|
|
5719
5670
|
const parent = this.getShapeParent(shape);
|
|
5720
5671
|
if (parent) {
|
|
5721
|
-
|
|
5722
|
-
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5672
|
+
shapeDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5723
5673
|
}
|
|
5724
5674
|
shapeDelta.add(shape);
|
|
5725
5675
|
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
@@ -5785,8 +5735,7 @@ class Editor extends EventEmitter {
|
|
|
5785
5735
|
const shapeDelta = delta.clone();
|
|
5786
5736
|
const parent = this.getShapeParent(shape);
|
|
5787
5737
|
if (parent) {
|
|
5788
|
-
|
|
5789
|
-
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5738
|
+
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5790
5739
|
}
|
|
5791
5740
|
shapeDelta.add(shape);
|
|
5792
5741
|
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
@@ -5860,8 +5809,7 @@ class Editor extends EventEmitter {
|
|
|
5860
5809
|
const shapeDelta = delta.clone();
|
|
5861
5810
|
const parent = this.getShapeParent(shape);
|
|
5862
5811
|
if (parent) {
|
|
5863
|
-
|
|
5864
|
-
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5812
|
+
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5865
5813
|
}
|
|
5866
5814
|
shapeDelta.add(shape);
|
|
5867
5815
|
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
@@ -5916,8 +5864,7 @@ class Editor extends EventEmitter {
|
|
|
5916
5864
|
scale[val] = commonBounds[dim] / pageBounds[dim];
|
|
5917
5865
|
for (const shape of shapes2) {
|
|
5918
5866
|
const shapeLocalOffset = localOffset.clone();
|
|
5919
|
-
|
|
5920
|
-
if (parentTransform) shapeLocalOffset.rot(-parentTransform.rotation());
|
|
5867
|
+
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5921
5868
|
shapeLocalOffset.add(shape);
|
|
5922
5869
|
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5923
5870
|
this.updateShape(changes);
|
|
@@ -5973,8 +5920,7 @@ class Editor extends EventEmitter {
|
|
|
5973
5920
|
);
|
|
5974
5921
|
for (const shape of shapes2) {
|
|
5975
5922
|
const shapeLocalOffset = localOffset.clone();
|
|
5976
|
-
|
|
5977
|
-
if (parentTransform) shapeLocalOffset.rot(-parentTransform.rotation());
|
|
5923
|
+
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5978
5924
|
shapeLocalOffset.add(shape);
|
|
5979
5925
|
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5980
5926
|
this.updateShape(changes);
|
|
@@ -6023,9 +5969,7 @@ class Editor extends EventEmitter {
|
|
|
6023
5969
|
const scaleOrigin = opts.scaleOrigin ?? this.getShapePageBounds(id)?.center;
|
|
6024
5970
|
if (!scaleOrigin) return null;
|
|
6025
5971
|
const pageTransform = opts.initialPageTransform ? Mat.Cast(opts.initialPageTransform) : this.getShapePageTransform(id);
|
|
6026
|
-
if (!pageTransform) return null;
|
|
6027
5972
|
const pageRotation = pageTransform.rotation();
|
|
6028
|
-
if (pageRotation == null) return null;
|
|
6029
5973
|
const scaleAxisRotation = opts.scaleAxisRotation ?? pageRotation;
|
|
6030
5974
|
const initialBounds = opts.initialBounds ?? this.getShapeGeometry(id).bounds;
|
|
6031
5975
|
if (!initialBounds) return null;
|
|
@@ -6176,7 +6120,6 @@ class Editor extends EventEmitter {
|
|
|
6176
6120
|
const currentLocalBounds = this.getShapeGeometry(id).bounds;
|
|
6177
6121
|
const currentPageCenter = Mat.applyToPoint(pageTransform, currentLocalBounds.center);
|
|
6178
6122
|
const shapePageTransformOrigin = pageTransform.point();
|
|
6179
|
-
if (!currentPageCenter || !shapePageTransformOrigin) return this;
|
|
6180
6123
|
const pageDelta = Vec.Sub(postScaleShapePageCenter, currentPageCenter);
|
|
6181
6124
|
const postScaleShapePagePoint = Vec.Add(shapePageTransformOrigin, pageDelta);
|
|
6182
6125
|
const { x, y } = this.getPointInParentSpace(id, postScaleShapePagePoint);
|
|
@@ -6435,10 +6378,10 @@ class Editor extends EventEmitter {
|
|
|
6435
6378
|
if (animationIdForShape !== animationId) continue;
|
|
6436
6379
|
updates.push({
|
|
6437
6380
|
...end,
|
|
6438
|
-
x: start.x
|
|
6439
|
-
y: start.y
|
|
6440
|
-
opacity: start.opacity
|
|
6441
|
-
rotation: start.rotation
|
|
6381
|
+
x: lerp(start.x, end.x, t),
|
|
6382
|
+
y: lerp(start.y, end.y, t),
|
|
6383
|
+
opacity: lerp(start.opacity, end.opacity, t),
|
|
6384
|
+
rotation: lerp(start.rotation, end.rotation, t),
|
|
6442
6385
|
props: this.getShapeUtil(end).getInterpolatedProps?.(start, end, t) ?? end.props
|
|
6443
6386
|
});
|
|
6444
6387
|
}
|
|
@@ -6564,7 +6507,7 @@ class Editor extends EventEmitter {
|
|
|
6564
6507
|
* @public
|
|
6565
6508
|
*/
|
|
6566
6509
|
updateShapes(partials) {
|
|
6567
|
-
const compactedPartials =
|
|
6510
|
+
const compactedPartials = [];
|
|
6568
6511
|
for (let i = 0, n = partials.length; i < n; i++) {
|
|
6569
6512
|
const partial = partials[i];
|
|
6570
6513
|
if (!partial) continue;
|
|
@@ -6635,28 +6578,32 @@ class Editor extends EventEmitter {
|
|
|
6635
6578
|
}
|
|
6636
6579
|
/* --------------------- Styles --------------------- */
|
|
6637
6580
|
/**
|
|
6638
|
-
*
|
|
6581
|
+
* Groups have no styles of their own: a style read or write on a selection applies to the
|
|
6582
|
+
* non-group shapes beneath each group, however deeply nested. Returns those shapes.
|
|
6639
6583
|
*
|
|
6640
6584
|
* @internal
|
|
6641
6585
|
*/
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
if (
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6586
|
+
_getStyleableShapes(shapes) {
|
|
6587
|
+
const result = [];
|
|
6588
|
+
const visit = (shape) => {
|
|
6589
|
+
if (this.isShapeOfType(shape, "group")) {
|
|
6590
|
+
for (const childId of this.getSortedChildIdsForParent(shape.id)) {
|
|
6591
|
+
const child = this.getShape(childId);
|
|
6592
|
+
if (child) visit(child);
|
|
6593
|
+
}
|
|
6594
|
+
} else {
|
|
6595
|
+
result.push(shape);
|
|
6652
6596
|
}
|
|
6653
|
-
}
|
|
6597
|
+
};
|
|
6598
|
+
for (const shape of shapes) visit(shape);
|
|
6599
|
+
return result;
|
|
6654
6600
|
}
|
|
6655
6601
|
_getSelectionSharedStyles() {
|
|
6656
|
-
const selectedShapes = this.getSelectedShapes();
|
|
6657
6602
|
const sharedStyles = new SharedStyleMap();
|
|
6658
|
-
for (const
|
|
6659
|
-
|
|
6603
|
+
for (const shape of this._getStyleableShapes(this.getSelectedShapes())) {
|
|
6604
|
+
for (const [style, propKey] of this.styleProps[shape.type]) {
|
|
6605
|
+
sharedStyles.applyValue(style, getOwnProperty(shape.props, propKey));
|
|
6606
|
+
}
|
|
6660
6607
|
}
|
|
6661
6608
|
return sharedStyles;
|
|
6662
6609
|
}
|
|
@@ -6688,38 +6635,16 @@ class Editor extends EventEmitter {
|
|
|
6688
6635
|
const styles = new SharedStyleMap();
|
|
6689
6636
|
if (!currentTool) return styles;
|
|
6690
6637
|
if (currentTool.shapeType) {
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
if (style.id === "tldraw:color") continue;
|
|
6694
|
-
styles.applyValue(style, this.getStyleForNextShape(style));
|
|
6695
|
-
}
|
|
6696
|
-
} else {
|
|
6697
|
-
for (const style of this.styleProps[currentTool.shapeType].keys()) {
|
|
6698
|
-
styles.applyValue(style, this.getStyleForNextShape(style));
|
|
6699
|
-
}
|
|
6638
|
+
for (const style of this.styleProps[currentTool.shapeType].keys()) {
|
|
6639
|
+
styles.applyValue(style, this.getStyleForNextShape(style));
|
|
6700
6640
|
}
|
|
6701
6641
|
}
|
|
6702
6642
|
return styles;
|
|
6703
6643
|
}
|
|
6704
6644
|
getSharedOpacity() {
|
|
6705
6645
|
if (this.isIn("select") && this.getSelectedShapeIds().length > 0) {
|
|
6706
|
-
const shapesToCheck = [];
|
|
6707
|
-
const addShape = (shapeId) => {
|
|
6708
|
-
const shape = this.getShape(shapeId);
|
|
6709
|
-
if (!shape) return;
|
|
6710
|
-
if (this.isShapeOfType(shape, "group")) {
|
|
6711
|
-
for (const childId of this.getSortedChildIdsForParent(shape.id)) {
|
|
6712
|
-
addShape(childId);
|
|
6713
|
-
}
|
|
6714
|
-
} else {
|
|
6715
|
-
shapesToCheck.push(shape);
|
|
6716
|
-
}
|
|
6717
|
-
};
|
|
6718
|
-
for (const shapeId of this.getSelectedShapeIds()) {
|
|
6719
|
-
addShape(shapeId);
|
|
6720
|
-
}
|
|
6721
6646
|
let opacity = null;
|
|
6722
|
-
for (const shape of
|
|
6647
|
+
for (const shape of this._getStyleableShapes(this.getSelectedShapes())) {
|
|
6723
6648
|
if (opacity === null) {
|
|
6724
6649
|
opacity = shape.opacity;
|
|
6725
6650
|
} else if (opacity !== shape.opacity) {
|
|
@@ -6758,28 +6683,12 @@ class Editor extends EventEmitter {
|
|
|
6758
6683
|
setOpacityForSelectedShapes(opacity) {
|
|
6759
6684
|
const selectedShapes = this.getSelectedShapes();
|
|
6760
6685
|
if (selectedShapes.length > 0) {
|
|
6761
|
-
const shapesToUpdate = [];
|
|
6762
|
-
const addShapeById = (shape) => {
|
|
6763
|
-
if (this.isShapeOfType(shape, "group")) {
|
|
6764
|
-
const childIds = this.getSortedChildIdsForParent(shape);
|
|
6765
|
-
for (const childId of childIds) {
|
|
6766
|
-
addShapeById(this.getShape(childId));
|
|
6767
|
-
}
|
|
6768
|
-
} else {
|
|
6769
|
-
shapesToUpdate.push(shape);
|
|
6770
|
-
}
|
|
6771
|
-
};
|
|
6772
|
-
for (const id of selectedShapes) {
|
|
6773
|
-
addShapeById(id);
|
|
6774
|
-
}
|
|
6775
6686
|
this.updateShapes(
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
};
|
|
6782
|
-
})
|
|
6687
|
+
this._getStyleableShapes(selectedShapes).map((shape) => ({
|
|
6688
|
+
id: shape.id,
|
|
6689
|
+
type: shape.type,
|
|
6690
|
+
opacity
|
|
6691
|
+
}))
|
|
6783
6692
|
);
|
|
6784
6693
|
}
|
|
6785
6694
|
return this;
|
|
@@ -6824,33 +6733,17 @@ class Editor extends EventEmitter {
|
|
|
6824
6733
|
const selectedShapes = this.getSelectedShapes();
|
|
6825
6734
|
if (selectedShapes.length > 0) {
|
|
6826
6735
|
const updates = [];
|
|
6827
|
-
const
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
const stylePropKey = this.styleProps[shape.type].get(style);
|
|
6836
|
-
if (stylePropKey) {
|
|
6837
|
-
const shapePartial = {
|
|
6838
|
-
id: shape.id,
|
|
6839
|
-
type: shape.type,
|
|
6840
|
-
props: { [stylePropKey]: value }
|
|
6841
|
-
};
|
|
6842
|
-
updates.push({
|
|
6843
|
-
util,
|
|
6844
|
-
originalShape: shape,
|
|
6845
|
-
updatePartial: shapePartial
|
|
6846
|
-
});
|
|
6847
|
-
}
|
|
6736
|
+
for (const shape of this._getStyleableShapes(selectedShapes)) {
|
|
6737
|
+
const stylePropKey = this.styleProps[shape.type].get(style);
|
|
6738
|
+
if (stylePropKey) {
|
|
6739
|
+
updates.push({
|
|
6740
|
+
id: shape.id,
|
|
6741
|
+
type: shape.type,
|
|
6742
|
+
props: { [stylePropKey]: value }
|
|
6743
|
+
});
|
|
6848
6744
|
}
|
|
6849
|
-
};
|
|
6850
|
-
for (const shape of selectedShapes) {
|
|
6851
|
-
addShapeById(shape);
|
|
6852
6745
|
}
|
|
6853
|
-
this.updateShapes(updates
|
|
6746
|
+
this.updateShapes(updates);
|
|
6854
6747
|
}
|
|
6855
6748
|
return this;
|
|
6856
6749
|
}
|
|
@@ -7246,7 +7139,6 @@ class Editor extends EventEmitter {
|
|
|
7246
7139
|
if (shapeIdMap.has(newShape.parentId)) {
|
|
7247
7140
|
newShape.parentId = shapeIdMap.get(oldShape.parentId);
|
|
7248
7141
|
} else {
|
|
7249
|
-
rootShapeIds.push(newShape.id);
|
|
7250
7142
|
newShape.index = index;
|
|
7251
7143
|
index = getIndexAbove(index);
|
|
7252
7144
|
}
|
|
@@ -7271,8 +7163,11 @@ class Editor extends EventEmitter {
|
|
|
7271
7163
|
continue;
|
|
7272
7164
|
}
|
|
7273
7165
|
if (asset.type === "image" && asset.props.src?.startsWith("data:image") || asset.type === "video" && asset.props.src?.startsWith("data:video")) {
|
|
7274
|
-
assetsToUpdate.push(
|
|
7275
|
-
|
|
7166
|
+
assetsToUpdate.push(asset);
|
|
7167
|
+
const assetWithoutSrc = structuredClone(asset);
|
|
7168
|
+
assetWithoutSrc.props.src = null;
|
|
7169
|
+
assetsToCreate.push(assetWithoutSrc);
|
|
7170
|
+
continue;
|
|
7276
7171
|
}
|
|
7277
7172
|
assetsToCreate.push(asset);
|
|
7278
7173
|
}
|
|
@@ -8099,7 +7994,7 @@ class Editor extends EventEmitter {
|
|
|
8099
7994
|
if (info.type === "misc") {
|
|
8100
7995
|
if (info.name === "cancel" || info.name === "complete") {
|
|
8101
7996
|
this.inputs.setIsDragging(false);
|
|
8102
|
-
if (this.inputs.getIsPanning()) {
|
|
7997
|
+
if (this.inputs.getIsPanning() && !this.inputs.keys.has("Space")) {
|
|
8103
7998
|
this.inputs.setIsPanning(false);
|
|
8104
7999
|
this.inputs.setIsSpacebarPanning(false);
|
|
8105
8000
|
this.setCursor({ type: this._prevCursor, rotation: 0 });
|
|
@@ -8851,10 +8746,9 @@ function withIsolatedShapes(editor, shapeIds, callback) {
|
|
|
8851
8746
|
}
|
|
8852
8747
|
function getCameraFitXFitY(editor, cameraOptions) {
|
|
8853
8748
|
if (!cameraOptions.constraints) throw Error("Should have constraints here");
|
|
8854
|
-
const {
|
|
8855
|
-
padding: { x: px, y: py }
|
|
8856
|
-
} = cameraOptions.constraints;
|
|
8857
8749
|
const vsb = editor.getViewportScreenBounds();
|
|
8750
|
+
const px = Math.min(cameraOptions.constraints.padding.x, vsb.w / 2);
|
|
8751
|
+
const py = Math.min(cameraOptions.constraints.padding.y, vsb.h / 2);
|
|
8858
8752
|
const bounds = Box.From(cameraOptions.constraints.bounds);
|
|
8859
8753
|
const zx = (vsb.w - px * 2) / bounds.w;
|
|
8860
8754
|
const zy = (vsb.h - py * 2) / bounds.h;
|