@tldraw/editor 5.4.0-canary.042da660fa66 → 5.4.0-canary.059d049864ed
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 +31 -1
- package/dist-cjs/index.js +1 -1
- 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 +139 -268
- package/dist-cjs/lib/editor/Editor.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/SnapManager/BoundsSnaps.js +0 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +1 -0
- 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/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 +9 -7
- 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/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/utils.js +2 -1
- package/dist-cjs/lib/primitives/utils.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/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +31 -1
- package/dist-esm/index.mjs +1 -1
- 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 +147 -269
- package/dist-esm/lib/editor/Editor.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/SnapManager/BoundsSnaps.mjs +0 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +1 -0
- 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/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 +9 -7
- 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/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/utils.mjs +2 -1
- package/dist-esm/lib/primitives/utils.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/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- 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 +196 -341
- 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/SnapManager/BoundsSnaps.ts +0 -2
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -0
- 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/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 +14 -7
- 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/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/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 +31 -0
- package/src/lib/test/usePassThroughWheelEvents.test.tsx +25 -2
- package/src/lib/utils/rotation.ts +4 -12
- package/src/version.ts +3 -3
|
@@ -257,6 +257,10 @@ class Editor extends import_eventemitter3.default {
|
|
|
257
257
|
if (!nextPageState) nextPageState = { ...prevPageState };
|
|
258
258
|
nextPageState.editingShapeId = null;
|
|
259
259
|
}
|
|
260
|
+
if (prevPageState.croppingShapeId && shapesNoLongerInPage.has(prevPageState.croppingShapeId)) {
|
|
261
|
+
if (!nextPageState) nextPageState = { ...prevPageState };
|
|
262
|
+
nextPageState.croppingShapeId = null;
|
|
263
|
+
}
|
|
260
264
|
const hintingShapeIds = prevPageState.hintingShapeIds.filter(
|
|
261
265
|
(id) => !shapesNoLongerInPage.has(id)
|
|
262
266
|
);
|
|
@@ -499,10 +503,11 @@ class Editor extends import_eventemitter3.default {
|
|
|
499
503
|
this.cancelDoubleClick();
|
|
500
504
|
}
|
|
501
505
|
if (prev?.selectedShapeIds !== next?.selectedShapeIds) {
|
|
506
|
+
const selectedShapeIds = new Set(next.selectedShapeIds);
|
|
502
507
|
const filtered = next.selectedShapeIds.filter((id) => {
|
|
503
508
|
let parentId = this.getShape(id)?.parentId;
|
|
504
509
|
while ((0, import_tlschema.isShapeId)(parentId)) {
|
|
505
|
-
if (
|
|
510
|
+
if (selectedShapeIds.has(parentId)) {
|
|
506
511
|
return false;
|
|
507
512
|
}
|
|
508
513
|
parentId = this.getShape(parentId)?.parentId;
|
|
@@ -586,7 +591,10 @@ class Editor extends import_eventemitter3.default {
|
|
|
586
591
|
const mode = this.store.props.collaboration.mode;
|
|
587
592
|
this.disposables.add(
|
|
588
593
|
(0, import_state.react)("update collaboration mode", () => {
|
|
589
|
-
|
|
594
|
+
const isReadonly = mode.get() === "readonly";
|
|
595
|
+
(0, import_state.unsafe__withoutCapture)(
|
|
596
|
+
() => this._updateInstanceState({ isReadonly }, { history: "ignore" })
|
|
597
|
+
);
|
|
590
598
|
})
|
|
591
599
|
);
|
|
592
600
|
}
|
|
@@ -944,7 +952,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
944
952
|
getShapeUtil(arg) {
|
|
945
953
|
const type = typeof arg === "string" ? arg : arg.type;
|
|
946
954
|
const shapeUtil = (0, import_utils.getOwnProperty)(this.shapeUtils, type);
|
|
947
|
-
|
|
955
|
+
if (!shapeUtil) throw new Error(`No shape util found for type "${type}"`);
|
|
948
956
|
return shapeUtil;
|
|
949
957
|
}
|
|
950
958
|
hasShapeUtil(arg) {
|
|
@@ -1733,7 +1741,9 @@ class Editor extends import_eventemitter3.default {
|
|
|
1733
1741
|
const selectedShapes = this.getSelectedShapes();
|
|
1734
1742
|
if (!selectedShapes.length) return;
|
|
1735
1743
|
const selectedShape = selectedShapes[0];
|
|
1736
|
-
const children =
|
|
1744
|
+
const children = (0, import_utils.compact)(
|
|
1745
|
+
this.getSortedChildIdsForParent(selectedShape.id).map((id) => this.getShape(id))
|
|
1746
|
+
);
|
|
1737
1747
|
const sortedChildren = this._getShapesInReadingOrder(children);
|
|
1738
1748
|
if (sortedChildren.length === 0) return;
|
|
1739
1749
|
this._selectShapesAndZoom([sortedChildren[0].id]);
|
|
@@ -1800,18 +1810,13 @@ class Editor extends import_eventemitter3.default {
|
|
|
1800
1810
|
* @internal
|
|
1801
1811
|
*/
|
|
1802
1812
|
getShapesSharedRotation(shapeIds) {
|
|
1803
|
-
let foundFirst = false;
|
|
1804
1813
|
let rotation = 0;
|
|
1805
1814
|
for (let i = 0, n = shapeIds.length; i < n; i++) {
|
|
1806
|
-
const
|
|
1807
|
-
if (
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
}
|
|
1812
|
-
} else {
|
|
1813
|
-
foundFirst = true;
|
|
1814
|
-
rotation = pageTransform.rotation();
|
|
1815
|
+
const pageRotation = this.getShapePageTransform(shapeIds[i]).rotation();
|
|
1816
|
+
if (i === 0) {
|
|
1817
|
+
rotation = pageRotation;
|
|
1818
|
+
} else if (pageRotation !== rotation) {
|
|
1819
|
+
return 0;
|
|
1815
1820
|
}
|
|
1816
1821
|
}
|
|
1817
1822
|
return rotation;
|
|
@@ -1837,11 +1842,9 @@ class Editor extends import_eventemitter3.default {
|
|
|
1837
1842
|
return bounds;
|
|
1838
1843
|
}
|
|
1839
1844
|
const boxFromRotatedVertices = import_Box.Box.FromPoints(
|
|
1840
|
-
shapeIds.flatMap(
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
return pageTransform.applyToPoints(this.getShapeGeometry(id).bounds.corners);
|
|
1844
|
-
}).map((p) => p.rot(-selectionRotation))
|
|
1845
|
+
shapeIds.flatMap(
|
|
1846
|
+
(id) => this.getShapePageTransform(id).applyToPoints(this.getShapeGeometry(id).bounds.corners)
|
|
1847
|
+
).map((p) => p.rot(-selectionRotation))
|
|
1845
1848
|
);
|
|
1846
1849
|
boxFromRotatedVertices.point = boxFromRotatedVertices.point.rot(selectionRotation);
|
|
1847
1850
|
return boxFromRotatedVertices;
|
|
@@ -1852,9 +1855,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
1852
1855
|
getSelectionRotatedScreenBounds() {
|
|
1853
1856
|
const bounds = this.getSelectionRotatedPageBounds();
|
|
1854
1857
|
if (!bounds) return void 0;
|
|
1855
|
-
const
|
|
1856
|
-
const zoom = this.
|
|
1857
|
-
return new import_Box.Box(
|
|
1858
|
+
const screenBounds = this.getViewportScreenBounds();
|
|
1859
|
+
const { x: cx, y: cy, z: zoom } = this.getCamera();
|
|
1860
|
+
return new import_Box.Box(
|
|
1861
|
+
(bounds.x + cx) * zoom + screenBounds.x,
|
|
1862
|
+
(bounds.y + cy) * zoom + screenBounds.y,
|
|
1863
|
+
bounds.width * zoom,
|
|
1864
|
+
bounds.height * zoom
|
|
1865
|
+
);
|
|
1858
1866
|
}
|
|
1859
1867
|
getFocusedGroupId() {
|
|
1860
1868
|
return this.getCurrentPageState().focusedGroupId ?? this.getCurrentPageId();
|
|
@@ -1955,42 +1963,28 @@ class Editor extends import_eventemitter3.default {
|
|
|
1955
1963
|
*/
|
|
1956
1964
|
setEditingShape(shape) {
|
|
1957
1965
|
const id = typeof shape === "string" ? shape : shape?.id ?? null;
|
|
1958
|
-
if (!id)
|
|
1966
|
+
if (id && !this.canEditShape(id)) return this;
|
|
1967
|
+
this.run(() => {
|
|
1968
|
+
const prevEditingShapeId = this.getEditingShapeId();
|
|
1969
|
+
if (prevEditingShapeId) {
|
|
1970
|
+
const prevEditingShape = this.getShape(prevEditingShapeId);
|
|
1971
|
+
if (prevEditingShape) {
|
|
1972
|
+
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1959
1975
|
this.run(
|
|
1960
1976
|
() => {
|
|
1961
|
-
const prevEditingShapeId = this.getEditingShapeId();
|
|
1962
|
-
if (prevEditingShapeId) {
|
|
1963
|
-
const prevEditingShape = this.getShape(prevEditingShapeId);
|
|
1964
|
-
if (prevEditingShape) {
|
|
1965
|
-
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
|
|
1966
|
-
}
|
|
1967
|
-
}
|
|
1968
1977
|
this._updateCurrentPageState({ editingShapeId: null });
|
|
1969
1978
|
this._currentRichTextEditor.set(null);
|
|
1979
|
+
if (!id) return;
|
|
1980
|
+
this.select(id);
|
|
1981
|
+
this._updateCurrentPageState({ editingShapeId: id });
|
|
1982
|
+
const nextEditingShape = this.getShape(id);
|
|
1983
|
+
this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
|
|
1970
1984
|
},
|
|
1971
1985
|
{ history: "ignore" }
|
|
1972
1986
|
);
|
|
1973
|
-
|
|
1974
|
-
}
|
|
1975
|
-
if (!this.canEditShape(id)) return this;
|
|
1976
|
-
this.run(
|
|
1977
|
-
() => {
|
|
1978
|
-
const prevEditingShapeId = this.getEditingShapeId();
|
|
1979
|
-
if (prevEditingShapeId) {
|
|
1980
|
-
const prevEditingShape = this.getShape(prevEditingShapeId);
|
|
1981
|
-
if (prevEditingShape) {
|
|
1982
|
-
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
this._updateCurrentPageState({ editingShapeId: null });
|
|
1986
|
-
this._currentRichTextEditor.set(null);
|
|
1987
|
-
this.select(id);
|
|
1988
|
-
this._updateCurrentPageState({ editingShapeId: id });
|
|
1989
|
-
const nextEditingShape = this.getShape(id);
|
|
1990
|
-
this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
|
|
1991
|
-
},
|
|
1992
|
-
{ history: "ignore" }
|
|
1993
|
-
);
|
|
1987
|
+
});
|
|
1994
1988
|
return this;
|
|
1995
1989
|
}
|
|
1996
1990
|
// Rich text editor
|
|
@@ -2096,19 +2090,12 @@ class Editor extends import_eventemitter3.default {
|
|
|
2096
2090
|
* @public
|
|
2097
2091
|
*/
|
|
2098
2092
|
setErasingShapes(shapes) {
|
|
2099
|
-
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((shape) => shape.id);
|
|
2093
|
+
const ids = typeof shapes[0] === "string" ? shapes.slice() : shapes.map((shape) => shape.id);
|
|
2100
2094
|
ids.sort();
|
|
2101
2095
|
const erasingShapeIds = this.getErasingShapeIds();
|
|
2102
2096
|
this.run(
|
|
2103
2097
|
() => {
|
|
2104
|
-
if (ids
|
|
2105
|
-
for (let i = 0; i < ids.length; i++) {
|
|
2106
|
-
if (ids[i] !== erasingShapeIds[i]) {
|
|
2107
|
-
this._updateCurrentPageState({ erasingShapeIds: ids });
|
|
2108
|
-
break;
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
} else {
|
|
2098
|
+
if (!(0, import_utils.areArraysShallowEqual)(ids, erasingShapeIds)) {
|
|
2112
2099
|
this._updateCurrentPageState({ erasingShapeIds: ids });
|
|
2113
2100
|
}
|
|
2114
2101
|
},
|
|
@@ -2141,6 +2128,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2141
2128
|
if (!_shape) return false;
|
|
2142
2129
|
const util = this.getShapeUtil(_shape);
|
|
2143
2130
|
if (!util.canCrop(_shape)) return false;
|
|
2131
|
+
if (this.getIsReadonly()) return false;
|
|
2144
2132
|
if (this.isShapeOrAncestorLocked(_shape)) return false;
|
|
2145
2133
|
return true;
|
|
2146
2134
|
}
|
|
@@ -2205,11 +2193,11 @@ class Editor extends import_eventemitter3.default {
|
|
|
2205
2193
|
const collaborators = this.getCollaborators();
|
|
2206
2194
|
let leaderPresence = null;
|
|
2207
2195
|
while (targetUserId && !visited.includes(targetUserId)) {
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2196
|
+
const nextPresence = collaborators.find((c) => c.userId === targetUserId);
|
|
2197
|
+
if (!nextPresence) break;
|
|
2198
|
+
leaderPresence = nextPresence;
|
|
2199
|
+
targetUserId = nextPresence.followingUserId ?? null;
|
|
2200
|
+
visited.push(nextPresence.userId);
|
|
2213
2201
|
}
|
|
2214
2202
|
return leaderPresence;
|
|
2215
2203
|
}
|
|
@@ -2272,39 +2260,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2272
2260
|
*
|
|
2273
2261
|
* @public */
|
|
2274
2262
|
getInitialZoom() {
|
|
2275
|
-
|
|
2276
|
-
if (!cameraOptions.constraints) return 1;
|
|
2277
|
-
if (cameraOptions.constraints.initialZoom === "default") return 1;
|
|
2278
|
-
const { zx, zy } = getCameraFitXFitY(this, cameraOptions);
|
|
2279
|
-
switch (cameraOptions.constraints.initialZoom) {
|
|
2280
|
-
case "fit-min": {
|
|
2281
|
-
return Math.max(zx, zy);
|
|
2282
|
-
}
|
|
2283
|
-
case "fit-max": {
|
|
2284
|
-
return Math.min(zx, zy);
|
|
2285
|
-
}
|
|
2286
|
-
case "fit-x": {
|
|
2287
|
-
return zx;
|
|
2288
|
-
}
|
|
2289
|
-
case "fit-y": {
|
|
2290
|
-
return zy;
|
|
2291
|
-
}
|
|
2292
|
-
case "fit-min-100": {
|
|
2293
|
-
return Math.min(1, Math.max(zx, zy));
|
|
2294
|
-
}
|
|
2295
|
-
case "fit-max-100": {
|
|
2296
|
-
return Math.min(1, Math.min(zx, zy));
|
|
2297
|
-
}
|
|
2298
|
-
case "fit-x-100": {
|
|
2299
|
-
return Math.min(1, zx);
|
|
2300
|
-
}
|
|
2301
|
-
case "fit-y-100": {
|
|
2302
|
-
return Math.min(1, zy);
|
|
2303
|
-
}
|
|
2304
|
-
default: {
|
|
2305
|
-
throw (0, import_utils.exhaustiveSwitchError)(cameraOptions.constraints.initialZoom);
|
|
2306
|
-
}
|
|
2307
|
-
}
|
|
2263
|
+
return this._getFitZoom(this.getCameraOptions().constraints?.initialZoom ?? "default");
|
|
2308
2264
|
}
|
|
2309
2265
|
/**
|
|
2310
2266
|
* Get the camera's base level for calculating actual zoom levels based on the zoom steps.
|
|
@@ -2316,11 +2272,13 @@ class Editor extends import_eventemitter3.default {
|
|
|
2316
2272
|
*
|
|
2317
2273
|
* @public */
|
|
2318
2274
|
getBaseZoom() {
|
|
2275
|
+
return this._getFitZoom(this.getCameraOptions().constraints?.baseZoom ?? "default");
|
|
2276
|
+
}
|
|
2277
|
+
_getFitZoom(fit) {
|
|
2319
2278
|
const cameraOptions = this.getCameraOptions();
|
|
2320
|
-
if (!cameraOptions.constraints) return 1;
|
|
2321
|
-
if (cameraOptions.constraints.baseZoom === "default") return 1;
|
|
2279
|
+
if (!cameraOptions.constraints || fit === "default") return 1;
|
|
2322
2280
|
const { zx, zy } = getCameraFitXFitY(this, cameraOptions);
|
|
2323
|
-
switch (
|
|
2281
|
+
switch (fit) {
|
|
2324
2282
|
case "fit-min": {
|
|
2325
2283
|
return Math.max(zx, zy);
|
|
2326
2284
|
}
|
|
@@ -2346,7 +2304,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2346
2304
|
return Math.min(1, zy);
|
|
2347
2305
|
}
|
|
2348
2306
|
default: {
|
|
2349
|
-
throw (0, import_utils.exhaustiveSwitchError)(
|
|
2307
|
+
throw (0, import_utils.exhaustiveSwitchError)(fit);
|
|
2350
2308
|
}
|
|
2351
2309
|
}
|
|
2352
2310
|
}
|
|
@@ -2380,7 +2338,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2380
2338
|
...this._cameraOptions.__unsafe__getWithoutCapture(),
|
|
2381
2339
|
...opts
|
|
2382
2340
|
});
|
|
2383
|
-
if (next.zoomSteps
|
|
2341
|
+
if (!next.zoomSteps || next.zoomSteps.length < 1) next.zoomSteps = [1];
|
|
2384
2342
|
this._cameraOptions.set(next);
|
|
2385
2343
|
this.setCamera(this.getCamera());
|
|
2386
2344
|
return this;
|
|
@@ -2840,9 +2798,9 @@ class Editor extends import_eventemitter3.default {
|
|
|
2840
2798
|
}
|
|
2841
2799
|
const remaining = duration - elapsed;
|
|
2842
2800
|
const t = easing(1 - remaining / duration);
|
|
2843
|
-
const left = start.minX
|
|
2844
|
-
const top = start.minY
|
|
2845
|
-
const right = start.maxX
|
|
2801
|
+
const left = (0, import_utils.lerp)(start.minX, end.minX, t);
|
|
2802
|
+
const top = (0, import_utils.lerp)(start.minY, end.minY, t);
|
|
2803
|
+
const right = (0, import_utils.lerp)(start.maxX, end.maxX, t);
|
|
2846
2804
|
this._setCamera(new import_Vec.Vec(-left, -top, this.getViewportScreenBounds().width / (right - left)), {
|
|
2847
2805
|
force: true
|
|
2848
2806
|
});
|
|
@@ -2920,7 +2878,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2920
2878
|
let newCy = cy + dy;
|
|
2921
2879
|
let newCz = cz;
|
|
2922
2880
|
if (dirZ !== 0) {
|
|
2923
|
-
newCz = cz * (
|
|
2881
|
+
newCz = cz * Math.exp(dirZ * currentSpeed * elapsed);
|
|
2924
2882
|
const center = this.getViewportScreenCenter();
|
|
2925
2883
|
newCx += center.x / newCz - center.x / cz;
|
|
2926
2884
|
newCy += center.y / newCz - center.y / cz;
|
|
@@ -3358,12 +3316,12 @@ class Editor extends import_eventemitter3.default {
|
|
|
3358
3316
|
const renderingShapes = [];
|
|
3359
3317
|
let nextIndex = this.options.maxShapesPerPage * 2;
|
|
3360
3318
|
let nextBackgroundIndex = this.options.maxShapesPerPage;
|
|
3361
|
-
const erasingShapeIds = this.getErasingShapeIds();
|
|
3319
|
+
const erasingShapeIds = new Set(this.getErasingShapeIds());
|
|
3362
3320
|
const addShapeById = (id, opacity, isAncestorErasing) => {
|
|
3363
3321
|
const shape = this.getShape(id);
|
|
3364
3322
|
if (!shape) return;
|
|
3365
3323
|
if (this.isShapeHidden(shape)) {
|
|
3366
|
-
const isErasing = isAncestorErasing || erasingShapeIds.
|
|
3324
|
+
const isErasing = isAncestorErasing || erasingShapeIds.has(id);
|
|
3367
3325
|
for (const childId of this.getSortedChildIdsForParent(id)) {
|
|
3368
3326
|
addShapeById(childId, opacity, isErasing);
|
|
3369
3327
|
}
|
|
@@ -3373,7 +3331,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
3373
3331
|
let isShapeErasing = false;
|
|
3374
3332
|
const util = this.getShapeUtil(shape);
|
|
3375
3333
|
if (useEditorState) {
|
|
3376
|
-
isShapeErasing = !isAncestorErasing && erasingShapeIds.
|
|
3334
|
+
isShapeErasing = !isAncestorErasing && erasingShapeIds.has(id);
|
|
3377
3335
|
if (isShapeErasing) {
|
|
3378
3336
|
opacity *= 0.32;
|
|
3379
3337
|
}
|
|
@@ -3965,10 +3923,8 @@ class Editor extends import_eventemitter3.default {
|
|
|
3965
3923
|
}
|
|
3966
3924
|
_getShapePageBoundsCache() {
|
|
3967
3925
|
return this.store.createComputedCache("pageBoundsCache", (shape) => {
|
|
3968
|
-
const pageTransform = this.getShapePageTransform(shape);
|
|
3969
|
-
if (!pageTransform) return void 0;
|
|
3970
3926
|
return import_Box.Box.FromPoints(
|
|
3971
|
-
|
|
3927
|
+
this.getShapePageTransform(shape).applyToPoints(this.getShapeGeometry(shape).boundsVertices)
|
|
3972
3928
|
);
|
|
3973
3929
|
});
|
|
3974
3930
|
}
|
|
@@ -4517,9 +4473,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4517
4473
|
const freshShape = this.getShape(id);
|
|
4518
4474
|
if (!freshShape) return new import_Vec.Vec(0, 0);
|
|
4519
4475
|
if ((0, import_tlschema.isPageId)(freshShape.parentId)) return import_Vec.Vec.From(point);
|
|
4520
|
-
|
|
4521
|
-
if (!parentTransform) return import_Vec.Vec.From(point);
|
|
4522
|
-
return parentTransform.clone().invert().applyToPoint(point);
|
|
4476
|
+
return this.getShapePageTransform(freshShape.parentId).clone().invert().applyToPoint(point);
|
|
4523
4477
|
}
|
|
4524
4478
|
getCurrentPageShapes() {
|
|
4525
4479
|
return Array.from(this.getCurrentPageShapeIds(), (id) => this.store.get(id));
|
|
@@ -4631,23 +4585,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4631
4585
|
* @public
|
|
4632
4586
|
*/
|
|
4633
4587
|
isShapeInPage(shape, pageId = this.getCurrentPageId()) {
|
|
4634
|
-
|
|
4635
|
-
const shapeToCheck = this.getShape(id);
|
|
4636
|
-
if (!shapeToCheck) return false;
|
|
4637
|
-
let shapeIsInPage = false;
|
|
4638
|
-
if (shapeToCheck.parentId === pageId) {
|
|
4639
|
-
shapeIsInPage = true;
|
|
4640
|
-
} else {
|
|
4641
|
-
let parent = this.getShape(shapeToCheck.parentId);
|
|
4642
|
-
isInPageSearch: while (parent) {
|
|
4643
|
-
if (parent.parentId === pageId) {
|
|
4644
|
-
shapeIsInPage = true;
|
|
4645
|
-
break isInPageSearch;
|
|
4646
|
-
}
|
|
4647
|
-
parent = this.getShape(parent.parentId);
|
|
4648
|
-
}
|
|
4649
|
-
}
|
|
4650
|
-
return shapeIsInPage;
|
|
4588
|
+
return this.getAncestorPageId(shape) === pageId;
|
|
4651
4589
|
}
|
|
4652
4590
|
/**
|
|
4653
4591
|
* Get the id of the containing page for a given shape.
|
|
@@ -4728,10 +4666,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4728
4666
|
for (let i = 0; i < shapesToReparent.length; i++) {
|
|
4729
4667
|
const shape = shapesToReparent[i];
|
|
4730
4668
|
const pageTransform = this.getShapePageTransform(shape);
|
|
4731
|
-
|
|
4732
|
-
const pagePoint = pageTransform.point();
|
|
4733
|
-
if (!pagePoint) continue;
|
|
4734
|
-
const newPoint = invertedParentTransform.applyToPoint(pagePoint);
|
|
4669
|
+
const newPoint = invertedParentTransform.applyToPoint(pageTransform.point());
|
|
4735
4670
|
const newRotation = pageTransform.rotation() - parentPageRotation;
|
|
4736
4671
|
if (shape.id === parentId) {
|
|
4737
4672
|
throw Error("Attempted to reparent a shape to itself!");
|
|
@@ -4820,7 +4755,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4820
4755
|
*/
|
|
4821
4756
|
getShapeAndDescendantIds(ids) {
|
|
4822
4757
|
const shapeIds = /* @__PURE__ */ new Set();
|
|
4823
|
-
for (const shape of ids.map((id) => this.getShape(id)).sort(import_utils.sortByIndex)) {
|
|
4758
|
+
for (const shape of (0, import_utils.compact)(ids.map((id) => this.getShape(id))).sort(import_utils.sortByIndex)) {
|
|
4824
4759
|
shapeIds.add(shape.id);
|
|
4825
4760
|
this.visitDescendants(shape, (descendantId) => {
|
|
4826
4761
|
shapeIds.add(descendantId);
|
|
@@ -4842,11 +4777,12 @@ class Editor extends import_eventemitter3.default {
|
|
|
4842
4777
|
const draggingShapes = (0, import_utils.compact)(droppingShapes.map((s) => this.getShape(s))).filter(
|
|
4843
4778
|
(s) => !s.isLocked && !this.isShapeHidden(s)
|
|
4844
4779
|
);
|
|
4780
|
+
const excludedIds = this.getShapeAndDescendantIds(draggingShapes.map((s) => s.id));
|
|
4845
4781
|
const maybeDraggingOverShapes = this.getShapesAtPoint(point, {
|
|
4846
4782
|
hitInside: true,
|
|
4847
4783
|
margin: 0
|
|
4848
4784
|
}).filter(
|
|
4849
|
-
(s) => !droppingShapes.includes(s) && !s.isLocked && !this.isShapeHidden(s) && !
|
|
4785
|
+
(s) => !droppingShapes.includes(s) && !s.isLocked && !this.isShapeHidden(s) && !excludedIds.has(s.id)
|
|
4850
4786
|
);
|
|
4851
4787
|
for (const maybeDraggingOverShape of maybeDraggingOverShapes) {
|
|
4852
4788
|
const shapeUtil = this.getShapeUtil(maybeDraggingOverShape);
|
|
@@ -5099,8 +5035,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5099
5035
|
for (const id of ids) {
|
|
5100
5036
|
const shape = this.getShape(id);
|
|
5101
5037
|
const localDelta = import_Vec.Vec.From(offset);
|
|
5102
|
-
|
|
5103
|
-
if (parentTransform) localDelta.rot(-parentTransform.rotation());
|
|
5038
|
+
localDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5104
5039
|
changes.push(this.getChangesToTranslateShape(shape, localDelta.add(shape)));
|
|
5105
5040
|
}
|
|
5106
5041
|
this.updateShapes(changes);
|
|
@@ -5155,7 +5090,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5155
5090
|
if (!originalShape) continue;
|
|
5156
5091
|
let ox = 0;
|
|
5157
5092
|
let oy = 0;
|
|
5158
|
-
if (offset && initialIds.has(originalId)) {
|
|
5093
|
+
if (offset && initialIds.has(originalId) && !shapeIdSet.has(originalShape.parentId)) {
|
|
5159
5094
|
const parentTransform = this.getShapeParentTransform(originalShape);
|
|
5160
5095
|
const vec = new import_Vec.Vec(offset.x, offset.y).rot(-parentTransform.rotation());
|
|
5161
5096
|
ox = vec.x;
|
|
@@ -5269,26 +5204,17 @@ class Editor extends import_eventemitter3.default {
|
|
|
5269
5204
|
toggleLock(shapes) {
|
|
5270
5205
|
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
5271
5206
|
if (this.getIsReadonly() || ids.length === 0) return this;
|
|
5272
|
-
let allLocked = true
|
|
5207
|
+
let allLocked = true;
|
|
5273
5208
|
const shapesToToggle = [];
|
|
5274
5209
|
for (const id of ids) {
|
|
5275
5210
|
const shape = this.getShape(id);
|
|
5276
5211
|
if (shape) {
|
|
5277
5212
|
shapesToToggle.push(shape);
|
|
5278
|
-
if (shape.isLocked)
|
|
5279
|
-
allUnlocked = false;
|
|
5280
|
-
} else {
|
|
5281
|
-
allLocked = false;
|
|
5282
|
-
}
|
|
5213
|
+
if (!shape.isLocked) allLocked = false;
|
|
5283
5214
|
}
|
|
5284
5215
|
}
|
|
5285
5216
|
this.run(() => {
|
|
5286
|
-
if (
|
|
5287
|
-
this.updateShapes(
|
|
5288
|
-
shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: true }))
|
|
5289
|
-
);
|
|
5290
|
-
this.setSelectedShapes([]);
|
|
5291
|
-
} else if (allLocked) {
|
|
5217
|
+
if (allLocked) {
|
|
5292
5218
|
this.updateShapes(
|
|
5293
5219
|
shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: false }))
|
|
5294
5220
|
);
|
|
@@ -5296,6 +5222,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5296
5222
|
this.updateShapes(
|
|
5297
5223
|
shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: true }))
|
|
5298
5224
|
);
|
|
5225
|
+
this.setSelectedShapes([]);
|
|
5299
5226
|
}
|
|
5300
5227
|
});
|
|
5301
5228
|
return this;
|
|
@@ -5406,9 +5333,10 @@ class Editor extends import_eventemitter3.default {
|
|
|
5406
5333
|
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
5407
5334
|
let freshShapes = (0, import_utils.compact)(ids.map((id) => this.getShape(id)));
|
|
5408
5335
|
if (opts?.filterAxisAligned) {
|
|
5409
|
-
freshShapes = freshShapes.filter(
|
|
5410
|
-
|
|
5411
|
-
|
|
5336
|
+
freshShapes = freshShapes.filter((s) => {
|
|
5337
|
+
const remainder = Math.abs(this.getShapePageTransform(s).rotation() % import_utils2.HALF_PI);
|
|
5338
|
+
return Math.min(remainder, import_utils2.HALF_PI - remainder) < 1e-9;
|
|
5339
|
+
});
|
|
5412
5340
|
}
|
|
5413
5341
|
const clusters = [];
|
|
5414
5342
|
const allBounds = [];
|
|
@@ -5573,9 +5501,9 @@ class Editor extends import_eventemitter3.default {
|
|
|
5573
5501
|
dim = "height";
|
|
5574
5502
|
}
|
|
5575
5503
|
let shapeGap = 0;
|
|
5504
|
+
shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
|
|
5576
5505
|
if (_gap === 0) {
|
|
5577
5506
|
const gaps = {};
|
|
5578
|
-
shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
|
|
5579
5507
|
for (let i = 0; i < len - 1; i++) {
|
|
5580
5508
|
const currCluster = shapeClustersToStack[i];
|
|
5581
5509
|
const nextCluster = shapeClustersToStack[i + 1];
|
|
@@ -5613,8 +5541,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5613
5541
|
const shapeDelta = delta.clone();
|
|
5614
5542
|
const parent = this.getShapeParent(shape);
|
|
5615
5543
|
if (parent) {
|
|
5616
|
-
|
|
5617
|
-
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5544
|
+
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5618
5545
|
}
|
|
5619
5546
|
shapeDelta.add(shape);
|
|
5620
5547
|
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
@@ -5652,7 +5579,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5652
5579
|
}
|
|
5653
5580
|
const commonBounds = import_Box.Box.Common(allBounds);
|
|
5654
5581
|
const maxWidth = commonBounds.width;
|
|
5655
|
-
shapeClustersToPack.sort((a, b) =>
|
|
5582
|
+
shapeClustersToPack.sort((a, b) => b.pageBounds.width - a.pageBounds.width).sort((a, b) => b.pageBounds.height - a.pageBounds.height);
|
|
5656
5583
|
const startWidth = Math.max(Math.ceil(Math.sqrt(area / 0.95)), maxWidth);
|
|
5657
5584
|
const spaces = [new import_Box.Box(commonBounds.x, commonBounds.y, startWidth, Infinity)];
|
|
5658
5585
|
let width = 0;
|
|
@@ -5700,8 +5627,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5700
5627
|
const shapeDelta = delta.clone();
|
|
5701
5628
|
const parent = this.getShapeParent(shape);
|
|
5702
5629
|
if (parent) {
|
|
5703
|
-
|
|
5704
|
-
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5630
|
+
shapeDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5705
5631
|
}
|
|
5706
5632
|
shapeDelta.add(shape);
|
|
5707
5633
|
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
@@ -5767,8 +5693,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5767
5693
|
const shapeDelta = delta.clone();
|
|
5768
5694
|
const parent = this.getShapeParent(shape);
|
|
5769
5695
|
if (parent) {
|
|
5770
|
-
|
|
5771
|
-
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5696
|
+
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5772
5697
|
}
|
|
5773
5698
|
shapeDelta.add(shape);
|
|
5774
5699
|
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
@@ -5842,8 +5767,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5842
5767
|
const shapeDelta = delta.clone();
|
|
5843
5768
|
const parent = this.getShapeParent(shape);
|
|
5844
5769
|
if (parent) {
|
|
5845
|
-
|
|
5846
|
-
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5770
|
+
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5847
5771
|
}
|
|
5848
5772
|
shapeDelta.add(shape);
|
|
5849
5773
|
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
@@ -5898,8 +5822,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5898
5822
|
scale[val] = commonBounds[dim] / pageBounds[dim];
|
|
5899
5823
|
for (const shape of shapes2) {
|
|
5900
5824
|
const shapeLocalOffset = localOffset.clone();
|
|
5901
|
-
|
|
5902
|
-
if (parentTransform) shapeLocalOffset.rot(-parentTransform.rotation());
|
|
5825
|
+
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5903
5826
|
shapeLocalOffset.add(shape);
|
|
5904
5827
|
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5905
5828
|
this.updateShape(changes);
|
|
@@ -5955,8 +5878,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5955
5878
|
);
|
|
5956
5879
|
for (const shape of shapes2) {
|
|
5957
5880
|
const shapeLocalOffset = localOffset.clone();
|
|
5958
|
-
|
|
5959
|
-
if (parentTransform) shapeLocalOffset.rot(-parentTransform.rotation());
|
|
5881
|
+
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5960
5882
|
shapeLocalOffset.add(shape);
|
|
5961
5883
|
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5962
5884
|
this.updateShape(changes);
|
|
@@ -6005,9 +5927,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
6005
5927
|
const scaleOrigin = opts.scaleOrigin ?? this.getShapePageBounds(id)?.center;
|
|
6006
5928
|
if (!scaleOrigin) return null;
|
|
6007
5929
|
const pageTransform = opts.initialPageTransform ? import_Mat.Mat.Cast(opts.initialPageTransform) : this.getShapePageTransform(id);
|
|
6008
|
-
if (!pageTransform) return null;
|
|
6009
5930
|
const pageRotation = pageTransform.rotation();
|
|
6010
|
-
if (pageRotation == null) return null;
|
|
6011
5931
|
const scaleAxisRotation = opts.scaleAxisRotation ?? pageRotation;
|
|
6012
5932
|
const initialBounds = opts.initialBounds ?? this.getShapeGeometry(id).bounds;
|
|
6013
5933
|
if (!initialBounds) return null;
|
|
@@ -6158,7 +6078,6 @@ class Editor extends import_eventemitter3.default {
|
|
|
6158
6078
|
const currentLocalBounds = this.getShapeGeometry(id).bounds;
|
|
6159
6079
|
const currentPageCenter = import_Mat.Mat.applyToPoint(pageTransform, currentLocalBounds.center);
|
|
6160
6080
|
const shapePageTransformOrigin = pageTransform.point();
|
|
6161
|
-
if (!currentPageCenter || !shapePageTransformOrigin) return this;
|
|
6162
6081
|
const pageDelta = import_Vec.Vec.Sub(postScaleShapePageCenter, currentPageCenter);
|
|
6163
6082
|
const postScaleShapePagePoint = import_Vec.Vec.Add(shapePageTransformOrigin, pageDelta);
|
|
6164
6083
|
const { x, y } = this.getPointInParentSpace(id, postScaleShapePagePoint);
|
|
@@ -6417,10 +6336,10 @@ class Editor extends import_eventemitter3.default {
|
|
|
6417
6336
|
if (animationIdForShape !== animationId) continue;
|
|
6418
6337
|
updates.push({
|
|
6419
6338
|
...end,
|
|
6420
|
-
x: start.x
|
|
6421
|
-
y: start.y
|
|
6422
|
-
opacity: start.opacity
|
|
6423
|
-
rotation: start.rotation
|
|
6339
|
+
x: (0, import_utils.lerp)(start.x, end.x, t),
|
|
6340
|
+
y: (0, import_utils.lerp)(start.y, end.y, t),
|
|
6341
|
+
opacity: (0, import_utils.lerp)(start.opacity, end.opacity, t),
|
|
6342
|
+
rotation: (0, import_utils.lerp)(start.rotation, end.rotation, t),
|
|
6424
6343
|
props: this.getShapeUtil(end).getInterpolatedProps?.(start, end, t) ?? end.props
|
|
6425
6344
|
});
|
|
6426
6345
|
}
|
|
@@ -6546,7 +6465,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
6546
6465
|
* @public
|
|
6547
6466
|
*/
|
|
6548
6467
|
updateShapes(partials) {
|
|
6549
|
-
const compactedPartials =
|
|
6468
|
+
const compactedPartials = [];
|
|
6550
6469
|
for (let i = 0, n = partials.length; i < n; i++) {
|
|
6551
6470
|
const partial = partials[i];
|
|
6552
6471
|
if (!partial) continue;
|
|
@@ -6617,28 +6536,32 @@ class Editor extends import_eventemitter3.default {
|
|
|
6617
6536
|
}
|
|
6618
6537
|
/* --------------------- Styles --------------------- */
|
|
6619
6538
|
/**
|
|
6620
|
-
*
|
|
6539
|
+
* Groups have no styles of their own: a style read or write on a selection applies to the
|
|
6540
|
+
* non-group shapes beneath each group, however deeply nested. Returns those shapes.
|
|
6621
6541
|
*
|
|
6622
6542
|
* @internal
|
|
6623
6543
|
*/
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
if (
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6544
|
+
_getStyleableShapes(shapes) {
|
|
6545
|
+
const result = [];
|
|
6546
|
+
const visit = (shape) => {
|
|
6547
|
+
if (this.isShapeOfType(shape, "group")) {
|
|
6548
|
+
for (const childId of this.getSortedChildIdsForParent(shape.id)) {
|
|
6549
|
+
const child = this.getShape(childId);
|
|
6550
|
+
if (child) visit(child);
|
|
6551
|
+
}
|
|
6552
|
+
} else {
|
|
6553
|
+
result.push(shape);
|
|
6634
6554
|
}
|
|
6635
|
-
}
|
|
6555
|
+
};
|
|
6556
|
+
for (const shape of shapes) visit(shape);
|
|
6557
|
+
return result;
|
|
6636
6558
|
}
|
|
6637
6559
|
_getSelectionSharedStyles() {
|
|
6638
|
-
const selectedShapes = this.getSelectedShapes();
|
|
6639
6560
|
const sharedStyles = new import_SharedStylesMap.SharedStyleMap();
|
|
6640
|
-
for (const
|
|
6641
|
-
|
|
6561
|
+
for (const shape of this._getStyleableShapes(this.getSelectedShapes())) {
|
|
6562
|
+
for (const [style, propKey] of this.styleProps[shape.type]) {
|
|
6563
|
+
sharedStyles.applyValue(style, (0, import_utils.getOwnProperty)(shape.props, propKey));
|
|
6564
|
+
}
|
|
6642
6565
|
}
|
|
6643
6566
|
return sharedStyles;
|
|
6644
6567
|
}
|
|
@@ -6670,38 +6593,16 @@ class Editor extends import_eventemitter3.default {
|
|
|
6670
6593
|
const styles = new import_SharedStylesMap.SharedStyleMap();
|
|
6671
6594
|
if (!currentTool) return styles;
|
|
6672
6595
|
if (currentTool.shapeType) {
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
if (style.id === "tldraw:color") continue;
|
|
6676
|
-
styles.applyValue(style, this.getStyleForNextShape(style));
|
|
6677
|
-
}
|
|
6678
|
-
} else {
|
|
6679
|
-
for (const style of this.styleProps[currentTool.shapeType].keys()) {
|
|
6680
|
-
styles.applyValue(style, this.getStyleForNextShape(style));
|
|
6681
|
-
}
|
|
6596
|
+
for (const style of this.styleProps[currentTool.shapeType].keys()) {
|
|
6597
|
+
styles.applyValue(style, this.getStyleForNextShape(style));
|
|
6682
6598
|
}
|
|
6683
6599
|
}
|
|
6684
6600
|
return styles;
|
|
6685
6601
|
}
|
|
6686
6602
|
getSharedOpacity() {
|
|
6687
6603
|
if (this.isIn("select") && this.getSelectedShapeIds().length > 0) {
|
|
6688
|
-
const shapesToCheck = [];
|
|
6689
|
-
const addShape = (shapeId) => {
|
|
6690
|
-
const shape = this.getShape(shapeId);
|
|
6691
|
-
if (!shape) return;
|
|
6692
|
-
if (this.isShapeOfType(shape, "group")) {
|
|
6693
|
-
for (const childId of this.getSortedChildIdsForParent(shape.id)) {
|
|
6694
|
-
addShape(childId);
|
|
6695
|
-
}
|
|
6696
|
-
} else {
|
|
6697
|
-
shapesToCheck.push(shape);
|
|
6698
|
-
}
|
|
6699
|
-
};
|
|
6700
|
-
for (const shapeId of this.getSelectedShapeIds()) {
|
|
6701
|
-
addShape(shapeId);
|
|
6702
|
-
}
|
|
6703
6604
|
let opacity = null;
|
|
6704
|
-
for (const shape of
|
|
6605
|
+
for (const shape of this._getStyleableShapes(this.getSelectedShapes())) {
|
|
6705
6606
|
if (opacity === null) {
|
|
6706
6607
|
opacity = shape.opacity;
|
|
6707
6608
|
} else if (opacity !== shape.opacity) {
|
|
@@ -6740,28 +6641,12 @@ class Editor extends import_eventemitter3.default {
|
|
|
6740
6641
|
setOpacityForSelectedShapes(opacity) {
|
|
6741
6642
|
const selectedShapes = this.getSelectedShapes();
|
|
6742
6643
|
if (selectedShapes.length > 0) {
|
|
6743
|
-
const shapesToUpdate = [];
|
|
6744
|
-
const addShapeById = (shape) => {
|
|
6745
|
-
if (this.isShapeOfType(shape, "group")) {
|
|
6746
|
-
const childIds = this.getSortedChildIdsForParent(shape);
|
|
6747
|
-
for (const childId of childIds) {
|
|
6748
|
-
addShapeById(this.getShape(childId));
|
|
6749
|
-
}
|
|
6750
|
-
} else {
|
|
6751
|
-
shapesToUpdate.push(shape);
|
|
6752
|
-
}
|
|
6753
|
-
};
|
|
6754
|
-
for (const id of selectedShapes) {
|
|
6755
|
-
addShapeById(id);
|
|
6756
|
-
}
|
|
6757
6644
|
this.updateShapes(
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
};
|
|
6764
|
-
})
|
|
6645
|
+
this._getStyleableShapes(selectedShapes).map((shape) => ({
|
|
6646
|
+
id: shape.id,
|
|
6647
|
+
type: shape.type,
|
|
6648
|
+
opacity
|
|
6649
|
+
}))
|
|
6765
6650
|
);
|
|
6766
6651
|
}
|
|
6767
6652
|
return this;
|
|
@@ -6806,33 +6691,17 @@ class Editor extends import_eventemitter3.default {
|
|
|
6806
6691
|
const selectedShapes = this.getSelectedShapes();
|
|
6807
6692
|
if (selectedShapes.length > 0) {
|
|
6808
6693
|
const updates = [];
|
|
6809
|
-
const
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
const stylePropKey = this.styleProps[shape.type].get(style);
|
|
6818
|
-
if (stylePropKey) {
|
|
6819
|
-
const shapePartial = {
|
|
6820
|
-
id: shape.id,
|
|
6821
|
-
type: shape.type,
|
|
6822
|
-
props: { [stylePropKey]: value }
|
|
6823
|
-
};
|
|
6824
|
-
updates.push({
|
|
6825
|
-
util,
|
|
6826
|
-
originalShape: shape,
|
|
6827
|
-
updatePartial: shapePartial
|
|
6828
|
-
});
|
|
6829
|
-
}
|
|
6694
|
+
for (const shape of this._getStyleableShapes(selectedShapes)) {
|
|
6695
|
+
const stylePropKey = this.styleProps[shape.type].get(style);
|
|
6696
|
+
if (stylePropKey) {
|
|
6697
|
+
updates.push({
|
|
6698
|
+
id: shape.id,
|
|
6699
|
+
type: shape.type,
|
|
6700
|
+
props: { [stylePropKey]: value }
|
|
6701
|
+
});
|
|
6830
6702
|
}
|
|
6831
|
-
};
|
|
6832
|
-
for (const shape of selectedShapes) {
|
|
6833
|
-
addShapeById(shape);
|
|
6834
6703
|
}
|
|
6835
|
-
this.updateShapes(updates
|
|
6704
|
+
this.updateShapes(updates);
|
|
6836
6705
|
}
|
|
6837
6706
|
return this;
|
|
6838
6707
|
}
|
|
@@ -7228,7 +7097,6 @@ class Editor extends import_eventemitter3.default {
|
|
|
7228
7097
|
if (shapeIdMap.has(newShape.parentId)) {
|
|
7229
7098
|
newShape.parentId = shapeIdMap.get(oldShape.parentId);
|
|
7230
7099
|
} else {
|
|
7231
|
-
rootShapeIds.push(newShape.id);
|
|
7232
7100
|
newShape.index = index;
|
|
7233
7101
|
index = (0, import_utils.getIndexAbove)(index);
|
|
7234
7102
|
}
|
|
@@ -7253,8 +7121,11 @@ class Editor extends import_eventemitter3.default {
|
|
|
7253
7121
|
continue;
|
|
7254
7122
|
}
|
|
7255
7123
|
if (asset.type === "image" && asset.props.src?.startsWith("data:image") || asset.type === "video" && asset.props.src?.startsWith("data:video")) {
|
|
7256
|
-
assetsToUpdate.push(
|
|
7257
|
-
|
|
7124
|
+
assetsToUpdate.push(asset);
|
|
7125
|
+
const assetWithoutSrc = (0, import_utils.structuredClone)(asset);
|
|
7126
|
+
assetWithoutSrc.props.src = null;
|
|
7127
|
+
assetsToCreate.push(assetWithoutSrc);
|
|
7128
|
+
continue;
|
|
7258
7129
|
}
|
|
7259
7130
|
assetsToCreate.push(asset);
|
|
7260
7131
|
}
|