@tldraw/editor 5.5.0-next.f9308d324e1c → 5.5.0
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 +49 -23
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +16 -12
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +42 -3
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +5 -1
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +2 -5
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +3 -3
- package/dist-cjs/lib/components/default-components/DefaultSpinner.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +168 -181
- package/dist-cjs/lib/editor/Editor.js.map +3 -3
- package/dist-cjs/lib/editor/derivations/bindingsIndex.js +2 -0
- package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +3 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EditorManager.js +11 -2
- package/dist-cjs/lib/editor/managers/EditorManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js +49 -63
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +1 -1
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +24 -24
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +7 -1
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +4 -3
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +4 -4
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +14 -6
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +3 -3
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/exports/ExportDelay.js +10 -2
- package/dist-cjs/lib/exports/ExportDelay.js.map +2 -2
- package/dist-cjs/lib/exports/FontEmbedder.js +25 -11
- package/dist-cjs/lib/exports/FontEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/StyleEmbedder.js +9 -4
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/fetchCache.js +3 -0
- package/dist-cjs/lib/exports/fetchCache.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgAsImage.js +10 -4
- package/dist-cjs/lib/exports/getSvgAsImage.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgJsx.js +18 -9
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/exports/parseCss.js +1 -1
- package/dist-cjs/lib/exports/parseCss.js.map +1 -1
- package/dist-cjs/lib/hooks/EditorComponentsContext.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +24 -0
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useIdentity.js +6 -2
- package/dist-cjs/lib/hooks/useIdentity.js.map +3 -3
- package/dist-cjs/lib/license/LicenseManager.js +9 -1
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/license/LicenseProvider.js +12 -4
- package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
- package/dist-cjs/lib/utils/debug-flags.js +0 -6
- package/dist-cjs/lib/utils/debug-flags.js.map +2 -2
- package/dist-cjs/lib/utils/deepLinks.js +2 -1
- package/dist-cjs/lib/utils/deepLinks.js.map +2 -2
- package/dist-cjs/lib/utils/sync/LocalIndexedDb.js +32 -25
- package/dist-cjs/lib/utils/sync/LocalIndexedDb.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +81 -40
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.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 +49 -23
- package/dist-esm/index.mjs +4 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +17 -13
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +42 -3
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +5 -1
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +2 -5
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +3 -3
- package/dist-esm/lib/components/default-components/DefaultSpinner.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +168 -181
- package/dist-esm/lib/editor/Editor.mjs.map +3 -3
- package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +2 -0
- package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +3 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EditorManager.mjs +11 -2
- package/dist-esm/lib/editor/managers/EditorManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs +49 -63
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +24 -24
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +7 -1
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +4 -3
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +4 -4
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +14 -6
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +3 -3
- package/dist-esm/lib/exports/ExportDelay.mjs +11 -3
- package/dist-esm/lib/exports/ExportDelay.mjs.map +2 -2
- package/dist-esm/lib/exports/FontEmbedder.mjs +25 -11
- package/dist-esm/lib/exports/FontEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/StyleEmbedder.mjs +9 -4
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/fetchCache.mjs +3 -0
- package/dist-esm/lib/exports/fetchCache.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgAsImage.mjs +10 -4
- package/dist-esm/lib/exports/getSvgAsImage.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +18 -9
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/exports/parseCss.mjs +1 -1
- package/dist-esm/lib/exports/parseCss.mjs.map +1 -1
- package/dist-esm/lib/hooks/EditorComponentsContext.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +24 -0
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useIdentity.mjs +7 -3
- package/dist-esm/lib/hooks/useIdentity.mjs.map +3 -3
- package/dist-esm/lib/license/LicenseManager.mjs +9 -1
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseProvider.mjs +13 -5
- package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
- package/dist-esm/lib/utils/debug-flags.mjs +0 -6
- package/dist-esm/lib/utils/debug-flags.mjs.map +2 -2
- package/dist-esm/lib/utils/deepLinks.mjs +2 -1
- package/dist-esm/lib/utils/deepLinks.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs +32 -25
- package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +81 -40
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +9 -1
- package/package.json +8 -11
- package/src/index.ts +5 -1
- package/src/lib/TldrawEditor.tsx +35 -21
- package/src/lib/components/MenuClickCapture.tsx +55 -4
- package/src/lib/components/default-components/DefaultCanvas.tsx +7 -1
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +13 -5
- package/src/lib/components/default-components/DefaultSpinner.tsx +4 -1
- package/src/lib/editor/Editor.test.ts +65 -0
- package/src/lib/editor/Editor.ts +261 -294
- package/src/lib/editor/derivations/bindingsIndex.ts +3 -0
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +1 -0
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +3 -2
- package/src/lib/editor/managers/EditorManager.test.ts +32 -1
- package/src/lib/editor/managers/EditorManager.ts +15 -3
- package/src/lib/editor/managers/PerformanceManager/PerformanceManager.test.ts +80 -0
- package/src/lib/editor/managers/PerformanceManager/PerformanceManager.ts +54 -81
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +1 -1
- package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +32 -36
- package/src/lib/editor/managers/SnapManager/HandleSnaps.ts +13 -2
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +13 -0
- package/src/lib/editor/managers/SnapManager/SnapManager.ts +6 -4
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +74 -0
- package/src/lib/editor/managers/TextManager/TextManager.ts +6 -5
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +23 -8
- package/src/lib/editor/types/external-content.ts +5 -0
- package/src/lib/exports/ExportDelay.tsx +16 -4
- package/src/lib/exports/FontEmbedder.test.ts +99 -0
- package/src/lib/exports/FontEmbedder.ts +32 -11
- package/src/lib/exports/StyleEmbedder.ts +13 -4
- package/src/lib/exports/fetchCache.test.ts +22 -0
- package/src/lib/exports/fetchCache.ts +4 -0
- package/src/lib/exports/getSvgAsImage.ts +13 -5
- package/src/lib/exports/getSvgJsx.test.ts +43 -1
- package/src/lib/exports/getSvgJsx.tsx +28 -16
- package/src/lib/exports/parseCss.test.ts +4 -0
- package/src/lib/exports/parseCss.ts +2 -2
- package/src/lib/hooks/EditorComponentsContext.tsx +2 -1
- package/src/lib/hooks/useCanvasEvents.ts +42 -0
- package/src/lib/hooks/useIdentity.tsx +12 -1
- package/src/lib/license/LicenseManager.ts +13 -1
- package/src/lib/license/LicenseProvider.test.tsx +76 -0
- package/src/lib/license/LicenseProvider.tsx +19 -5
- package/src/lib/test/preserveFocus.test.tsx +81 -0
- package/src/lib/utils/debug-flags.ts +0 -6
- package/src/lib/utils/deepLinks.test.ts +15 -0
- package/src/lib/utils/deepLinks.ts +8 -3
- package/src/lib/utils/sync/LocalIndexedDb.test.ts +121 -1
- package/src/lib/utils/sync/LocalIndexedDb.ts +41 -28
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +257 -1
- package/src/lib/utils/sync/TLLocalSyncClient.ts +112 -54
- package/src/version.ts +3 -3
- package/dist-cjs/lib/primitives/geometry/geometry.bench.js +0 -133
- package/dist-cjs/lib/primitives/geometry/geometry.bench.js.map +0 -7
- package/dist-esm/lib/primitives/geometry/geometry.bench.mjs +0 -132
- package/dist-esm/lib/primitives/geometry/geometry.bench.mjs.map +0 -7
- package/src/lib/primitives/geometry/geometry.bench.ts +0 -179
|
@@ -136,6 +136,10 @@ import { UserPreferencesManager } from "./managers/UserPreferencesManager/UserPr
|
|
|
136
136
|
import { OverlayManager } from "./overlays/OverlayManager.mjs";
|
|
137
137
|
import { RootState } from "./tools/RootState.mjs";
|
|
138
138
|
const RENDERING_SHAPES_SORT_CACHE_THRESHOLD = 100;
|
|
139
|
+
const AXIS = {
|
|
140
|
+
horizontal: { val: "x", min: "minX", max: "maxX", dim: "width" },
|
|
141
|
+
vertical: { val: "y", min: "minY", max: "maxY", dim: "height" }
|
|
142
|
+
};
|
|
139
143
|
class Editor extends EventEmitter {
|
|
140
144
|
id = uniqueId();
|
|
141
145
|
constructor({
|
|
@@ -462,7 +466,7 @@ class Editor extends EventEmitter {
|
|
|
462
466
|
}
|
|
463
467
|
}
|
|
464
468
|
if (deleteBindingIds.length) {
|
|
465
|
-
this.
|
|
469
|
+
this.store.remove(deleteBindingIds);
|
|
466
470
|
}
|
|
467
471
|
}
|
|
468
472
|
},
|
|
@@ -1422,6 +1426,7 @@ class Editor extends EventEmitter {
|
|
|
1422
1426
|
* @public
|
|
1423
1427
|
**/
|
|
1424
1428
|
updateDocumentSettings(settings) {
|
|
1429
|
+
if (this.getIsReadonly()) return this;
|
|
1425
1430
|
this.run(
|
|
1426
1431
|
() => {
|
|
1427
1432
|
this.store.put([{ ...this.getDocumentSettings(), ...settings }]);
|
|
@@ -1444,7 +1449,7 @@ class Editor extends EventEmitter {
|
|
|
1444
1449
|
updateInstanceState(partial, historyOptions) {
|
|
1445
1450
|
this._updateInstanceState(partial, { history: "ignore", ...historyOptions });
|
|
1446
1451
|
if (partial.isChangingStyle !== void 0) {
|
|
1447
|
-
clearTimeout(this._isChangingStyleTimeout);
|
|
1452
|
+
this.timers.clearTimeout(this._isChangingStyleTimeout);
|
|
1448
1453
|
if (partial.isChangingStyle === true) {
|
|
1449
1454
|
this._isChangingStyleTimeout = this.timers.setTimeout(() => {
|
|
1450
1455
|
this._updateInstanceState({ isChangingStyle: false }, { history: "ignore" });
|
|
@@ -1581,7 +1586,7 @@ class Editor extends EventEmitter {
|
|
|
1581
1586
|
* @public
|
|
1582
1587
|
*/
|
|
1583
1588
|
select(...shapes) {
|
|
1584
|
-
const ids =
|
|
1589
|
+
const ids = toShapeIds(shapes);
|
|
1585
1590
|
this.setSelectedShapes(ids);
|
|
1586
1591
|
return this;
|
|
1587
1592
|
}
|
|
@@ -1596,7 +1601,7 @@ class Editor extends EventEmitter {
|
|
|
1596
1601
|
* @public
|
|
1597
1602
|
*/
|
|
1598
1603
|
deselect(...shapes) {
|
|
1599
|
-
const ids =
|
|
1604
|
+
const ids = toShapeIds(shapes);
|
|
1600
1605
|
const selectedShapeIds = this.getSelectedShapeIds();
|
|
1601
1606
|
if (selectedShapeIds.length > 0 && ids.length > 0) {
|
|
1602
1607
|
this.setSelectedShapes(selectedShapeIds.filter((id) => !ids.includes(id)));
|
|
@@ -1634,7 +1639,7 @@ class Editor extends EventEmitter {
|
|
|
1634
1639
|
}
|
|
1635
1640
|
const ids = this.getSortedChildIdsForParent(parentToSelectWithinId);
|
|
1636
1641
|
if (ids.length <= 0) return this;
|
|
1637
|
-
this.setSelectedShapes(this.
|
|
1642
|
+
this.setSelectedShapes(ids.filter((id) => !this.getShape(id)?.isLocked));
|
|
1638
1643
|
return this;
|
|
1639
1644
|
}
|
|
1640
1645
|
/**
|
|
@@ -1651,12 +1656,15 @@ class Editor extends EventEmitter {
|
|
|
1651
1656
|
const selectedShapeIds = this.getSelectedShapeIds();
|
|
1652
1657
|
const firstParentId = selectedShapeIds[0] ? this.getShape(selectedShapeIds[0])?.parentId : null;
|
|
1653
1658
|
const isSelectedWithinContainer = firstParentId && selectedShapeIds.every((shapeId) => this.getShape(shapeId)?.parentId === firstParentId) && !isPageId(firstParentId);
|
|
1654
|
-
const filteredShapes =
|
|
1655
|
-
|
|
1659
|
+
const filteredShapes = this.getCurrentPageShapes().filter(
|
|
1660
|
+
(shape2) => !this.isShapeOrAncestorLocked(shape2) && (isSelectedWithinContainer ? shape2.parentId === firstParentId : isPageId(shape2.parentId))
|
|
1661
|
+
);
|
|
1662
|
+
const readingOrderShapes = this._getShapesInReadingOrder(filteredShapes);
|
|
1656
1663
|
const currentShapeId = selectedShapeIds.length === 1 ? selectedShapeIds[0] : readingOrderShapes.find((shape2) => selectedShapeIds.includes(shape2.id))?.id;
|
|
1657
1664
|
let adjacentShapeId;
|
|
1658
1665
|
if (direction === "next" || direction === "prev") {
|
|
1659
1666
|
const shapeIds = readingOrderShapes.map((shape2) => shape2.id);
|
|
1667
|
+
if (shapeIds.length === 0) return;
|
|
1660
1668
|
const currentIndex = currentShapeId ? shapeIds.indexOf(currentShapeId) : -1;
|
|
1661
1669
|
const startIndex = currentIndex === -1 && direction === "prev" ? 0 : currentIndex;
|
|
1662
1670
|
const adjacentIndex = (startIndex + (direction === "next" ? 1 : -1) + shapeIds.length) % shapeIds.length;
|
|
@@ -1758,13 +1766,14 @@ class Editor extends EventEmitter {
|
|
|
1758
1766
|
});
|
|
1759
1767
|
if (shapesInDirection.length === 0) return currentShapeId;
|
|
1760
1768
|
const lowestScoringShape = minBy(shapesInDirection, ({ center }) => {
|
|
1761
|
-
const distance = Vec.
|
|
1769
|
+
const distance = Vec.Dist(currentCenter, center);
|
|
1762
1770
|
const dirProp = ["left", "right"].includes(direction) ? "x" : "y";
|
|
1763
1771
|
const directionalDistance = Math.abs(center[dirProp] - currentCenter[dirProp]);
|
|
1764
1772
|
const offProp = ["left", "right"].includes(direction) ? "y" : "x";
|
|
1765
1773
|
const offAxisDeviation = Math.abs(center[offProp] - currentCenter[offProp]);
|
|
1766
|
-
const angle =
|
|
1767
|
-
const
|
|
1774
|
+
const angle = (Vec.Angle(currentCenter, center) * (180 / Math.PI) + 360) % 360;
|
|
1775
|
+
const rawAngleDeviation = Math.abs(angle - directionToAngle[direction]);
|
|
1776
|
+
const angleDeviation = Math.min(rawAngleDeviation, 360 - rawAngleDeviation);
|
|
1768
1777
|
return distance * 1 + // Base distance
|
|
1769
1778
|
offAxisDeviation * 2 + // Heavy penalty for off-axis deviation
|
|
1770
1779
|
(distance - directionalDistance) * 1.5 + // Penalty for diagonal distance
|
|
@@ -2102,7 +2111,7 @@ class Editor extends EventEmitter {
|
|
|
2102
2111
|
* @public
|
|
2103
2112
|
*/
|
|
2104
2113
|
setHintingShapes(shapes) {
|
|
2105
|
-
const ids =
|
|
2114
|
+
const ids = toShapeIds(shapes);
|
|
2106
2115
|
this.run(
|
|
2107
2116
|
() => {
|
|
2108
2117
|
this._updateCurrentPageState({ hintingShapeIds: dedupe(ids) });
|
|
@@ -2132,7 +2141,7 @@ class Editor extends EventEmitter {
|
|
|
2132
2141
|
* @public
|
|
2133
2142
|
*/
|
|
2134
2143
|
setErasingShapes(shapes) {
|
|
2135
|
-
const ids =
|
|
2144
|
+
const ids = toShapeIds(shapes).slice();
|
|
2136
2145
|
ids.sort();
|
|
2137
2146
|
const erasingShapeIds = this.getErasingShapeIds();
|
|
2138
2147
|
this.run(
|
|
@@ -2539,14 +2548,16 @@ class Editor extends EventEmitter {
|
|
|
2539
2548
|
setCamera(point, opts) {
|
|
2540
2549
|
const { isLocked } = this._cameraOptions.__unsafe__getWithoutCapture();
|
|
2541
2550
|
if (isLocked && !opts?.force) return this;
|
|
2551
|
+
const _point = new Vec(point.x, point.y, point.z ?? this.getZoomLevel());
|
|
2552
|
+
if (!Number.isFinite(_point.x) || !Number.isFinite(_point.y) || !Number.isFinite(_point.z)) {
|
|
2553
|
+
throw Error(
|
|
2554
|
+
`Editor.setCamera: expected finite values, got (${_point.x}, ${_point.y}, ${_point.z}).`
|
|
2555
|
+
);
|
|
2556
|
+
}
|
|
2542
2557
|
this.stopCameraAnimation();
|
|
2543
2558
|
if (this.getInstanceState().followingUserId) {
|
|
2544
2559
|
this.stopFollowingUser();
|
|
2545
2560
|
}
|
|
2546
|
-
const _point = Vec.Cast(point);
|
|
2547
|
-
if (!Number.isFinite(_point.x)) _point.x = 0;
|
|
2548
|
-
if (!Number.isFinite(_point.y)) _point.y = 0;
|
|
2549
|
-
if (_point.z === void 0 || !Number.isFinite(_point.z)) point.z = this.getZoomLevel();
|
|
2550
2561
|
const camera = this.getConstrainedCamera(_point, opts);
|
|
2551
2562
|
if (opts?.animation) {
|
|
2552
2563
|
const { width, height } = this.getViewportScreenBounds();
|
|
@@ -2831,11 +2842,14 @@ class Editor extends EventEmitter {
|
|
|
2831
2842
|
_animateViewport(ms) {
|
|
2832
2843
|
if (!this._viewportAnimation) return;
|
|
2833
2844
|
this._viewportAnimation.elapsed += ms;
|
|
2834
|
-
const { elapsed, easing, duration, start, end } = this._viewportAnimation;
|
|
2845
|
+
const { elapsed, easing, duration, start, end, opts } = this._viewportAnimation;
|
|
2835
2846
|
if (elapsed > duration) {
|
|
2836
2847
|
this.off("tick", this._animateViewport);
|
|
2837
2848
|
this._viewportAnimation = null;
|
|
2838
|
-
this._setCamera(
|
|
2849
|
+
this._setCamera(
|
|
2850
|
+
new Vec(-end.x, -end.y, this.getViewportScreenBounds().width / end.width),
|
|
2851
|
+
opts
|
|
2852
|
+
);
|
|
2839
2853
|
return;
|
|
2840
2854
|
}
|
|
2841
2855
|
const remaining = duration - elapsed;
|
|
@@ -2873,7 +2887,8 @@ class Editor extends EventEmitter {
|
|
|
2873
2887
|
duration: duration / animationSpeed,
|
|
2874
2888
|
easing,
|
|
2875
2889
|
start: viewportPageBounds.clone(),
|
|
2876
|
-
end: targetViewportPage.clone()
|
|
2890
|
+
end: targetViewportPage.clone(),
|
|
2891
|
+
opts: rest
|
|
2877
2892
|
};
|
|
2878
2893
|
this.once("stop-camera-animation", () => {
|
|
2879
2894
|
this.off("tick", this._animateViewport);
|
|
@@ -2959,6 +2974,7 @@ class Editor extends EventEmitter {
|
|
|
2959
2974
|
}
|
|
2960
2975
|
const isOnSamePage = presence.currentPageId === this.getCurrentPageId();
|
|
2961
2976
|
if (!isOnSamePage) {
|
|
2977
|
+
this.markHistoryStoppingPoint("change-page");
|
|
2962
2978
|
this.setCurrentPage(presence.currentPageId);
|
|
2963
2979
|
}
|
|
2964
2980
|
if (opts && opts.animation && !isOnSamePage) {
|
|
@@ -3790,7 +3806,9 @@ class Editor extends EventEmitter {
|
|
|
3790
3806
|
if (ids.length <= 0) return this;
|
|
3791
3807
|
this.run(
|
|
3792
3808
|
() => {
|
|
3793
|
-
this.store.props.assets.remove?.(ids)
|
|
3809
|
+
Promise.resolve(this.store.props.assets.remove?.(ids)).catch(
|
|
3810
|
+
(err) => console.error("Error while removing assets from the asset store:", err)
|
|
3811
|
+
);
|
|
3794
3812
|
this.store.remove(ids);
|
|
3795
3813
|
},
|
|
3796
3814
|
{ history: "ignore" }
|
|
@@ -4172,7 +4190,7 @@ class Editor extends EventEmitter {
|
|
|
4172
4190
|
if (shapes.length === 0) {
|
|
4173
4191
|
return;
|
|
4174
4192
|
}
|
|
4175
|
-
const ids =
|
|
4193
|
+
const ids = toShapeIds(shapes);
|
|
4176
4194
|
const freshShapes = compact(ids.map((id) => this.getShape(id)));
|
|
4177
4195
|
if (freshShapes.length === 1) {
|
|
4178
4196
|
const parentId = freshShapes[0].parentId;
|
|
@@ -4269,12 +4287,14 @@ class Editor extends EventEmitter {
|
|
|
4269
4287
|
*/
|
|
4270
4288
|
getSelectedShapeAtPoint(point) {
|
|
4271
4289
|
const selectedShapeIds = this.getSelectedShapeIds();
|
|
4272
|
-
|
|
4290
|
+
if (selectedShapeIds.length === 0) return void 0;
|
|
4291
|
+
const selectedShapeIdSet = new Set(selectedShapeIds);
|
|
4292
|
+
const margin = this.getHitTestMargin();
|
|
4273
4293
|
const sortedShapes = this.getCurrentPageShapesSorted();
|
|
4274
4294
|
for (let i = sortedShapes.length - 1; i >= 0; i--) {
|
|
4275
4295
|
const shape = sortedShapes[i];
|
|
4276
4296
|
if (shape.type === "group") continue;
|
|
4277
|
-
if (!
|
|
4297
|
+
if (!selectedShapeIdSet.has(shape.id)) continue;
|
|
4278
4298
|
if (this.getShapeGeometry(shape).hitTestPoint(
|
|
4279
4299
|
this.getPointInShapeSpace(shape, point),
|
|
4280
4300
|
margin,
|
|
@@ -4372,7 +4392,6 @@ class Editor extends EventEmitter {
|
|
|
4372
4392
|
}
|
|
4373
4393
|
return inMarginClosestToEdgeHit || shape;
|
|
4374
4394
|
} else {
|
|
4375
|
-
if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
|
|
4376
4395
|
if (hitInside ? (
|
|
4377
4396
|
// On hitInside, the distance will be negative for hits inside
|
|
4378
4397
|
// If the distance is positive, check against the outer margin
|
|
@@ -4389,6 +4408,7 @@ class Editor extends EventEmitter {
|
|
|
4389
4408
|
inMarginClosestToEdgeHit = shape;
|
|
4390
4409
|
}
|
|
4391
4410
|
} else if (!inMarginClosestToEdgeHit) {
|
|
4411
|
+
if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
|
|
4392
4412
|
const { area } = geometry;
|
|
4393
4413
|
if (area < inHollowSmallestArea) {
|
|
4394
4414
|
inHollowSmallestArea = area;
|
|
@@ -4399,6 +4419,9 @@ class Editor extends EventEmitter {
|
|
|
4399
4419
|
}
|
|
4400
4420
|
} else {
|
|
4401
4421
|
if (distance < this.getHitTestMargin()) {
|
|
4422
|
+
if (inMarginClosestToEdgeHit && inMarginClosestToEdgeDistance <= distance) {
|
|
4423
|
+
return inMarginClosestToEdgeHit;
|
|
4424
|
+
}
|
|
4402
4425
|
return shape;
|
|
4403
4426
|
}
|
|
4404
4427
|
}
|
|
@@ -4675,7 +4698,7 @@ class Editor extends EventEmitter {
|
|
|
4675
4698
|
* @public
|
|
4676
4699
|
*/
|
|
4677
4700
|
reparentShapes(shapes, parentId, insertIndex) {
|
|
4678
|
-
const ids =
|
|
4701
|
+
const ids = toShapeIds(shapes);
|
|
4679
4702
|
if (ids.length === 0) return this;
|
|
4680
4703
|
const changes = [];
|
|
4681
4704
|
const parentTransform = isPageId(parentId) ? Mat.Identity() : this.getShapePageTransform(parentId);
|
|
@@ -4904,6 +4927,7 @@ class Editor extends EventEmitter {
|
|
|
4904
4927
|
* binding, but the `type`, `toId`, and `fromId` must all be provided.
|
|
4905
4928
|
*/
|
|
4906
4929
|
createBindings(partials) {
|
|
4930
|
+
if (this.getIsReadonly()) return this;
|
|
4907
4931
|
const bindings = [];
|
|
4908
4932
|
for (const partial of partials) {
|
|
4909
4933
|
const fromShape = this.getShape(partial.fromId);
|
|
@@ -4938,6 +4962,7 @@ class Editor extends EventEmitter {
|
|
|
4938
4962
|
* binding is skipped. The changes from the partial are merged into the existing record.
|
|
4939
4963
|
*/
|
|
4940
4964
|
updateBindings(partials) {
|
|
4965
|
+
if (this.getIsReadonly()) return this;
|
|
4941
4966
|
const updated = [];
|
|
4942
4967
|
for (const partial of partials) {
|
|
4943
4968
|
if (!partial) continue;
|
|
@@ -4966,6 +4991,16 @@ class Editor extends EventEmitter {
|
|
|
4966
4991
|
* Delete several bindings by their IDs. If a binding ID doesn't exist, it's ignored.
|
|
4967
4992
|
*/
|
|
4968
4993
|
deleteBindings(bindings, { isolateShapes = false } = {}) {
|
|
4994
|
+
if (this.getIsReadonly()) return this;
|
|
4995
|
+
return this._deleteBindings(bindings, { isolateShapes });
|
|
4996
|
+
}
|
|
4997
|
+
/**
|
|
4998
|
+
* Unguarded so that withIsolatedShapes can transiently isolate shapes for copy and export in
|
|
4999
|
+
* readonly mode; the public deleteBindings is what readonly blocks.
|
|
5000
|
+
*
|
|
5001
|
+
* @internal
|
|
5002
|
+
*/
|
|
5003
|
+
_deleteBindings(bindings, { isolateShapes = false } = {}) {
|
|
4969
5004
|
const ids = bindings.map((binding) => typeof binding === "string" ? binding : binding.id);
|
|
4970
5005
|
if (isolateShapes) {
|
|
4971
5006
|
this.store.atomic(() => {
|
|
@@ -5024,7 +5059,7 @@ class Editor extends EventEmitter {
|
|
|
5024
5059
|
* @param opts - The options for the rotation.
|
|
5025
5060
|
*/
|
|
5026
5061
|
rotateShapesBy(shapes, delta, opts) {
|
|
5027
|
-
const ids =
|
|
5062
|
+
const ids = toShapeIds(shapes);
|
|
5028
5063
|
if (ids.length <= 0) return this;
|
|
5029
5064
|
const snapshot = getRotationSnapshot({ editor: this, ids });
|
|
5030
5065
|
if (!snapshot) return this;
|
|
@@ -5061,6 +5096,14 @@ class Editor extends EventEmitter {
|
|
|
5061
5096
|
}
|
|
5062
5097
|
return workingShape;
|
|
5063
5098
|
}
|
|
5099
|
+
// Counter-rotates the page-space delta into the parent's space; without that a child of a rotated
|
|
5100
|
+
// frame or group would move along its parent's axes instead of the page's.
|
|
5101
|
+
// todo: a shape laid out together with its own parent moves twice, once with the parent and once
|
|
5102
|
+
// on its own; the layout commands should skip shapes whose ancestors are also being laid out
|
|
5103
|
+
getChangesToTranslateShapeByPageDelta(shape, pageDelta) {
|
|
5104
|
+
const localDelta = Vec.From(pageDelta).rot(-this.getShapeParentTransform(shape).rotation());
|
|
5105
|
+
return this.getChangesToTranslateShape(shape, localDelta.add(shape));
|
|
5106
|
+
}
|
|
5064
5107
|
/**
|
|
5065
5108
|
* Move shapes by a delta.
|
|
5066
5109
|
*
|
|
@@ -5073,14 +5116,12 @@ class Editor extends EventEmitter {
|
|
|
5073
5116
|
* @param offset - The offset to apply to the shapes.
|
|
5074
5117
|
*/
|
|
5075
5118
|
nudgeShapes(shapes, offset) {
|
|
5076
|
-
const ids =
|
|
5119
|
+
const ids = toShapeIds(shapes);
|
|
5077
5120
|
if (ids.length <= 0) return this;
|
|
5078
5121
|
const changes = [];
|
|
5079
5122
|
for (const id of ids) {
|
|
5080
5123
|
const shape = this.getShape(id);
|
|
5081
|
-
|
|
5082
|
-
localDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5083
|
-
changes.push(this.getChangesToTranslateShape(shape, localDelta.add(shape)));
|
|
5124
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, offset));
|
|
5084
5125
|
}
|
|
5085
5126
|
this.updateShapes(changes);
|
|
5086
5127
|
return this;
|
|
@@ -5101,7 +5142,7 @@ class Editor extends EventEmitter {
|
|
|
5101
5142
|
*/
|
|
5102
5143
|
duplicateShapes(shapes, offset) {
|
|
5103
5144
|
this.run(() => {
|
|
5104
|
-
const _ids =
|
|
5145
|
+
const _ids = toShapeIds(shapes);
|
|
5105
5146
|
const ids = this._shouldIgnoreShapeLock ? _ids : this._getUnlockedShapeIds(_ids);
|
|
5106
5147
|
if (ids.length <= 0) return this;
|
|
5107
5148
|
const initialIds = new Set(ids);
|
|
@@ -5210,7 +5251,7 @@ class Editor extends EventEmitter {
|
|
|
5210
5251
|
* @public
|
|
5211
5252
|
*/
|
|
5212
5253
|
moveShapesToPage(shapes, pageId) {
|
|
5213
|
-
const ids =
|
|
5254
|
+
const ids = toShapeIds(shapes);
|
|
5214
5255
|
if (ids.length === 0) return this;
|
|
5215
5256
|
if (this.getIsReadonly()) return this;
|
|
5216
5257
|
const currentPageId = this.getCurrentPageId();
|
|
@@ -5246,7 +5287,7 @@ class Editor extends EventEmitter {
|
|
|
5246
5287
|
* @public
|
|
5247
5288
|
*/
|
|
5248
5289
|
toggleLock(shapes) {
|
|
5249
|
-
const ids =
|
|
5290
|
+
const ids = toShapeIds(shapes);
|
|
5250
5291
|
if (this.getIsReadonly() || ids.length === 0) return this;
|
|
5251
5292
|
let allLocked = true;
|
|
5252
5293
|
const shapesToToggle = [];
|
|
@@ -5285,7 +5326,7 @@ class Editor extends EventEmitter {
|
|
|
5285
5326
|
* @public
|
|
5286
5327
|
*/
|
|
5287
5328
|
sendToBack(shapes) {
|
|
5288
|
-
const ids =
|
|
5329
|
+
const ids = toShapeIds(shapes);
|
|
5289
5330
|
const changes = getReorderingShapesChanges(this, "toBack", ids, {
|
|
5290
5331
|
considerAllShapes: true
|
|
5291
5332
|
});
|
|
@@ -5315,7 +5356,7 @@ class Editor extends EventEmitter {
|
|
|
5315
5356
|
* @public
|
|
5316
5357
|
*/
|
|
5317
5358
|
sendBackward(shapes, opts = {}) {
|
|
5318
|
-
const ids =
|
|
5359
|
+
const ids = toShapeIds(shapes);
|
|
5319
5360
|
const changes = getReorderingShapesChanges(this, "backward", ids, opts);
|
|
5320
5361
|
if (changes) this.updateShapes(changes);
|
|
5321
5362
|
return this;
|
|
@@ -5343,7 +5384,7 @@ class Editor extends EventEmitter {
|
|
|
5343
5384
|
* @public
|
|
5344
5385
|
*/
|
|
5345
5386
|
bringForward(shapes, opts = {}) {
|
|
5346
|
-
const ids =
|
|
5387
|
+
const ids = toShapeIds(shapes);
|
|
5347
5388
|
const changes = getReorderingShapesChanges(this, "forward", ids, opts);
|
|
5348
5389
|
if (changes) this.updateShapes(changes);
|
|
5349
5390
|
return this;
|
|
@@ -5362,7 +5403,7 @@ class Editor extends EventEmitter {
|
|
|
5362
5403
|
* @public
|
|
5363
5404
|
*/
|
|
5364
5405
|
bringToFront(shapes) {
|
|
5365
|
-
const ids =
|
|
5406
|
+
const ids = toShapeIds(shapes);
|
|
5366
5407
|
const changes = getReorderingShapesChanges(this, "toFront", ids);
|
|
5367
5408
|
if (changes) this.updateShapes(changes);
|
|
5368
5409
|
return this;
|
|
@@ -5374,7 +5415,7 @@ class Editor extends EventEmitter {
|
|
|
5374
5415
|
* @internal
|
|
5375
5416
|
*/
|
|
5376
5417
|
getShapeClusters(shapes, type, opts) {
|
|
5377
|
-
const ids =
|
|
5418
|
+
const ids = toShapeIds(shapes);
|
|
5378
5419
|
let freshShapes = compact(ids.map((id) => this.getShape(id)));
|
|
5379
5420
|
if (opts?.filterAxisAligned) {
|
|
5380
5421
|
freshShapes = freshShapes.filter((s) => {
|
|
@@ -5399,7 +5440,7 @@ class Editor extends EventEmitter {
|
|
|
5399
5440
|
const shapesMovingTogether = [shape];
|
|
5400
5441
|
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
5401
5442
|
this.collectShapesViaArrowBindings({
|
|
5402
|
-
bindings: this.
|
|
5443
|
+
bindings: this.getBindingsInvolvingShape(shape.id, "arrow"),
|
|
5403
5444
|
initialShapes: freshShapes,
|
|
5404
5445
|
resultShapes: shapesMovingTogether,
|
|
5405
5446
|
resultBounds: boundsOfShapesMovingTogether,
|
|
@@ -5455,7 +5496,7 @@ class Editor extends EventEmitter {
|
|
|
5455
5496
|
*/
|
|
5456
5497
|
flipShapes(shapes, operation) {
|
|
5457
5498
|
if (this.getIsReadonly()) return this;
|
|
5458
|
-
const ids =
|
|
5499
|
+
const ids = toShapeIds(shapes);
|
|
5459
5500
|
const shapesToFlipFirstPass = compact(ids.map((id) => this.getShape(id)));
|
|
5460
5501
|
for (const shape of shapesToFlipFirstPass) {
|
|
5461
5502
|
if (this.isShapeOfType(shape, "group")) {
|
|
@@ -5529,21 +5570,7 @@ class Editor extends EventEmitter {
|
|
|
5529
5570
|
const { clusters: shapeClustersToStack } = this.getShapeClusters(shapes, "stack");
|
|
5530
5571
|
const len = shapeClustersToStack.length;
|
|
5531
5572
|
if (_gap === 0 && len < 3 || len < 2) return this;
|
|
5532
|
-
|
|
5533
|
-
let min;
|
|
5534
|
-
let max;
|
|
5535
|
-
let dim;
|
|
5536
|
-
if (operation === "horizontal") {
|
|
5537
|
-
val = "x";
|
|
5538
|
-
min = "minX";
|
|
5539
|
-
max = "maxX";
|
|
5540
|
-
dim = "width";
|
|
5541
|
-
} else {
|
|
5542
|
-
val = "y";
|
|
5543
|
-
min = "minY";
|
|
5544
|
-
max = "maxY";
|
|
5545
|
-
dim = "height";
|
|
5546
|
-
}
|
|
5573
|
+
const { val, min, max, dim } = AXIS[operation];
|
|
5547
5574
|
let shapeGap = 0;
|
|
5548
5575
|
shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
|
|
5549
5576
|
if (_gap === 0) {
|
|
@@ -5582,13 +5609,7 @@ class Editor extends EventEmitter {
|
|
|
5582
5609
|
const delta = new Vec();
|
|
5583
5610
|
delta[val] = v + shapeGap - pageBounds[val];
|
|
5584
5611
|
for (const shape of shapes2) {
|
|
5585
|
-
|
|
5586
|
-
const parent = this.getShapeParent(shape);
|
|
5587
|
-
if (parent) {
|
|
5588
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5589
|
-
}
|
|
5590
|
-
shapeDelta.add(shape);
|
|
5591
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5612
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5592
5613
|
}
|
|
5593
5614
|
v += pageBounds[dim] + shapeGap;
|
|
5594
5615
|
}
|
|
@@ -5668,13 +5689,7 @@ class Editor extends EventEmitter {
|
|
|
5668
5689
|
for (const { shapes: shapes2, pageBounds, nextPageBounds } of shapeClustersToPack) {
|
|
5669
5690
|
const delta = Vec.Sub(nextPageBounds.point, pageBounds.point).add(centerDelta);
|
|
5670
5691
|
for (const shape of shapes2) {
|
|
5671
|
-
|
|
5672
|
-
const parent = this.getShapeParent(shape);
|
|
5673
|
-
if (parent) {
|
|
5674
|
-
shapeDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5675
|
-
}
|
|
5676
|
-
shapeDelta.add(shape);
|
|
5677
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5692
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5678
5693
|
}
|
|
5679
5694
|
}
|
|
5680
5695
|
if (changes.length) {
|
|
@@ -5734,13 +5749,7 @@ class Editor extends EventEmitter {
|
|
|
5734
5749
|
}
|
|
5735
5750
|
}
|
|
5736
5751
|
for (const shape of shapes2) {
|
|
5737
|
-
|
|
5738
|
-
const parent = this.getShapeParent(shape);
|
|
5739
|
-
if (parent) {
|
|
5740
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5741
|
-
}
|
|
5742
|
-
shapeDelta.add(shape);
|
|
5743
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5752
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5744
5753
|
}
|
|
5745
5754
|
});
|
|
5746
5755
|
this.updateShapes(changes);
|
|
@@ -5764,27 +5773,13 @@ class Editor extends EventEmitter {
|
|
|
5764
5773
|
if (this.getIsReadonly()) return this;
|
|
5765
5774
|
const { clusters: shapeClustersToDistribute } = this.getShapeClusters(shapes, "distribute");
|
|
5766
5775
|
if (shapeClustersToDistribute.length < 3) return this;
|
|
5767
|
-
|
|
5768
|
-
let min;
|
|
5769
|
-
let max;
|
|
5770
|
-
let dim;
|
|
5771
|
-
if (operation === "horizontal") {
|
|
5772
|
-
val = "x";
|
|
5773
|
-
min = "minX";
|
|
5774
|
-
max = "maxX";
|
|
5775
|
-
dim = "width";
|
|
5776
|
-
} else {
|
|
5777
|
-
val = "y";
|
|
5778
|
-
min = "minY";
|
|
5779
|
-
max = "maxY";
|
|
5780
|
-
dim = "height";
|
|
5781
|
-
}
|
|
5776
|
+
const { val, min, max, dim } = AXIS[operation];
|
|
5782
5777
|
const changes = [];
|
|
5783
5778
|
const first = shapeClustersToDistribute.sort((a, b) => a.pageBounds[min] - b.pageBounds[min])[0];
|
|
5784
5779
|
const last2 = shapeClustersToDistribute.sort((a, b) => b.pageBounds[max] - a.pageBounds[max])[0];
|
|
5785
5780
|
if (first === last2) {
|
|
5786
5781
|
const excludedShapeIds = new Set(first.shapes.map((s) => s.id));
|
|
5787
|
-
const ids =
|
|
5782
|
+
const ids = toShapeIds(shapes);
|
|
5788
5783
|
return this.distributeShapes(
|
|
5789
5784
|
ids.filter((id) => !excludedShapeIds.has(id)),
|
|
5790
5785
|
operation
|
|
@@ -5808,13 +5803,7 @@ class Editor extends EventEmitter {
|
|
|
5808
5803
|
delta[val] = last2.pageBounds[max] - pageBounds[max] - 1;
|
|
5809
5804
|
}
|
|
5810
5805
|
for (const shape of shapes2) {
|
|
5811
|
-
|
|
5812
|
-
const parent = this.getShapeParent(shape);
|
|
5813
|
-
if (parent) {
|
|
5814
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5815
|
-
}
|
|
5816
|
-
shapeDelta.add(shape);
|
|
5817
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5806
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5818
5807
|
}
|
|
5819
5808
|
v += pageBounds[dim] + gap;
|
|
5820
5809
|
}
|
|
@@ -5844,32 +5833,17 @@ class Editor extends EventEmitter {
|
|
|
5844
5833
|
);
|
|
5845
5834
|
if (shapeClustersToStretch.length < 2) return this;
|
|
5846
5835
|
const commonBounds = Box.Common(allBounds);
|
|
5847
|
-
|
|
5848
|
-
let min;
|
|
5849
|
-
let dim;
|
|
5850
|
-
if (operation === "horizontal") {
|
|
5851
|
-
val = "x";
|
|
5852
|
-
min = "minX";
|
|
5853
|
-
dim = "width";
|
|
5854
|
-
} else {
|
|
5855
|
-
val = "y";
|
|
5856
|
-
min = "minY";
|
|
5857
|
-
dim = "height";
|
|
5858
|
-
}
|
|
5836
|
+
const { val, min, dim } = AXIS[operation];
|
|
5859
5837
|
this.run(() => {
|
|
5860
5838
|
shapeClustersToStretch.forEach(({ shapes: shapes2, pageBounds }) => {
|
|
5861
|
-
const
|
|
5862
|
-
|
|
5839
|
+
const pageOffset = new Vec();
|
|
5840
|
+
pageOffset[val] = commonBounds[min] - pageBounds[min];
|
|
5863
5841
|
const scaleOrigin = pageBounds.center.clone();
|
|
5864
5842
|
scaleOrigin[val] = commonBounds[min];
|
|
5865
5843
|
const scale = new Vec(1, 1);
|
|
5866
5844
|
scale[val] = commonBounds[dim] / pageBounds[dim];
|
|
5867
5845
|
for (const shape of shapes2) {
|
|
5868
|
-
|
|
5869
|
-
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5870
|
-
shapeLocalOffset.add(shape);
|
|
5871
|
-
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5872
|
-
this.updateShape(changes);
|
|
5846
|
+
this.updateShape(this.getChangesToTranslateShapeByPageDelta(shape, pageOffset));
|
|
5873
5847
|
this.resizeShape(shape.id, scale, {
|
|
5874
5848
|
initialBounds: this.getShapeGeometry(shape).bounds,
|
|
5875
5849
|
scaleOrigin,
|
|
@@ -5912,7 +5886,7 @@ class Editor extends EventEmitter {
|
|
|
5912
5886
|
const scaleY = targetBounds.height / commonBounds.height;
|
|
5913
5887
|
const scale = new Vec(scaleX, scaleY);
|
|
5914
5888
|
shapeClusters.forEach(({ shapes: shapes2, pageBounds }) => {
|
|
5915
|
-
const
|
|
5889
|
+
const pageOffset = new Vec(
|
|
5916
5890
|
targetBounds.minX - commonBounds.minX + (pageBounds.minX - commonBounds.minX) * (scaleX - 1),
|
|
5917
5891
|
targetBounds.minY - commonBounds.minY + (pageBounds.minY - commonBounds.minY) * (scaleY - 1)
|
|
5918
5892
|
);
|
|
@@ -5921,11 +5895,7 @@ class Editor extends EventEmitter {
|
|
|
5921
5895
|
targetBounds.minY + (pageBounds.minY - commonBounds.minY) * scaleY
|
|
5922
5896
|
);
|
|
5923
5897
|
for (const shape of shapes2) {
|
|
5924
|
-
|
|
5925
|
-
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5926
|
-
shapeLocalOffset.add(shape);
|
|
5927
|
-
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5928
|
-
this.updateShape(changes);
|
|
5898
|
+
this.updateShape(this.getChangesToTranslateShapeByPageDelta(shape, pageOffset));
|
|
5929
5899
|
this.resizeShape(shape.id, scale, {
|
|
5930
5900
|
initialBounds: this.getShapeGeometry(shape).bounds,
|
|
5931
5901
|
scaleOrigin,
|
|
@@ -6344,12 +6314,17 @@ class Editor extends EventEmitter {
|
|
|
6344
6314
|
let remaining = duration;
|
|
6345
6315
|
let t;
|
|
6346
6316
|
const animations = [];
|
|
6317
|
+
const ignoreShapeLock = this._shouldIgnoreShapeLock;
|
|
6347
6318
|
let partial, result;
|
|
6348
6319
|
for (let i = 0, n = partials.length; i < n; i++) {
|
|
6349
6320
|
partial = partials[i];
|
|
6350
6321
|
if (!partial) continue;
|
|
6351
6322
|
const shape = this.getShape(partial.id);
|
|
6352
6323
|
if (!shape) continue;
|
|
6324
|
+
const unlocks = shape.isLocked && Object.hasOwn(partial, "isLocked") && !partial.isLocked;
|
|
6325
|
+
if (!ignoreShapeLock && !unlocks && this.isShapeOrAncestorLocked(shape)) {
|
|
6326
|
+
continue;
|
|
6327
|
+
}
|
|
6353
6328
|
result = {
|
|
6354
6329
|
start: structuredClone(shape),
|
|
6355
6330
|
end: applyPartialToRecordWithProps(structuredClone(shape), partial)
|
|
@@ -6365,7 +6340,7 @@ class Editor extends EventEmitter {
|
|
|
6365
6340
|
(p) => p && animatingShapes2.get(p.id) === animationId
|
|
6366
6341
|
);
|
|
6367
6342
|
if (partialsToUpdate.length) {
|
|
6368
|
-
this.updateShapes(partialsToUpdate);
|
|
6343
|
+
this.run(() => this.updateShapes(partialsToUpdate), { ignoreShapeLock });
|
|
6369
6344
|
}
|
|
6370
6345
|
this.off("tick", handleTick);
|
|
6371
6346
|
return;
|
|
@@ -6398,13 +6373,13 @@ class Editor extends EventEmitter {
|
|
|
6398
6373
|
throw Error("Editor.groupShapes: must provide an array of shapes or shape ids");
|
|
6399
6374
|
}
|
|
6400
6375
|
if (this.getIsReadonly()) return this;
|
|
6401
|
-
const ids =
|
|
6402
|
-
if (ids.length <= 1) return this;
|
|
6376
|
+
const ids = toShapeIds(shapes);
|
|
6403
6377
|
const shapesToGroup = compact(
|
|
6404
6378
|
(this._shouldIgnoreShapeLock ? ids : this._getUnlockedShapeIds(ids)).map(
|
|
6405
6379
|
(id) => this.getShape(id)
|
|
6406
6380
|
)
|
|
6407
6381
|
);
|
|
6382
|
+
if (shapesToGroup.length <= 1) return this;
|
|
6408
6383
|
const sortedShapeIds = shapesToGroup.sort(sortByIndex).map((s) => s.id);
|
|
6409
6384
|
const childBounds = compact(shapesToGroup.map((shape) => this.getShapePageBounds(shape)));
|
|
6410
6385
|
const pageBounds = Box.Common(childBounds);
|
|
@@ -6413,8 +6388,11 @@ class Editor extends EventEmitter {
|
|
|
6413
6388
|
}
|
|
6414
6389
|
const { x, y } = pageBounds.point;
|
|
6415
6390
|
const parentId = this.findCommonAncestor(shapesToGroup) ?? this.getCurrentPageId();
|
|
6416
|
-
if (this.
|
|
6417
|
-
|
|
6391
|
+
if (!this.canCreateShapes([groupId])) {
|
|
6392
|
+
alertMaxShapes(this);
|
|
6393
|
+
return this;
|
|
6394
|
+
}
|
|
6395
|
+
if (this.isIn("select") && !this.isIn("select.idle")) {
|
|
6418
6396
|
this.cancel();
|
|
6419
6397
|
}
|
|
6420
6398
|
const shapesWithRootParent = shapesToGroup.filter((shape) => shape.parentId === parentId).sort(sortByIndex);
|
|
@@ -6442,15 +6420,14 @@ class Editor extends EventEmitter {
|
|
|
6442
6420
|
ungroupShapes(shapes, opts = {}) {
|
|
6443
6421
|
if (this.getIsReadonly()) return this;
|
|
6444
6422
|
const { select = true } = opts;
|
|
6445
|
-
const ids =
|
|
6423
|
+
const ids = toShapeIds(shapes);
|
|
6446
6424
|
const shapesToUngroup = compact(
|
|
6447
6425
|
(this._shouldIgnoreShapeLock ? ids : this._getUnlockedShapeIds(ids)).map(
|
|
6448
6426
|
(id) => this.getShape(id)
|
|
6449
6427
|
)
|
|
6450
6428
|
);
|
|
6451
6429
|
if (shapesToUngroup.length === 0) return this;
|
|
6452
|
-
if (this.
|
|
6453
|
-
if (!this.isIn("select.idle")) {
|
|
6430
|
+
if (this.isIn("select") && !this.isIn("select.idle")) {
|
|
6454
6431
|
this.cancel();
|
|
6455
6432
|
}
|
|
6456
6433
|
const idsToSelect = /* @__PURE__ */ new Set();
|
|
@@ -6464,16 +6441,16 @@ class Editor extends EventEmitter {
|
|
|
6464
6441
|
});
|
|
6465
6442
|
if (groups.length === 0) return this;
|
|
6466
6443
|
this.run(() => {
|
|
6467
|
-
let group;
|
|
6468
6444
|
for (let i = 0, n = groups.length; i < n; i++) {
|
|
6469
|
-
group = groups[i];
|
|
6445
|
+
const group = this.getShape(groups[i].id);
|
|
6446
|
+
if (!group) continue;
|
|
6470
6447
|
const childIds = this.getSortedChildIdsForParent(group.id);
|
|
6471
6448
|
for (let j = 0, n2 = childIds.length; j < n2; j++) {
|
|
6472
6449
|
idsToSelect.add(childIds[j]);
|
|
6473
6450
|
}
|
|
6474
6451
|
this.reparentShapes(childIds, group.parentId, group.index);
|
|
6475
6452
|
}
|
|
6476
|
-
this.deleteShapes(groups.map((
|
|
6453
|
+
this.deleteShapes(groups.map((group) => group.id));
|
|
6477
6454
|
if (select) {
|
|
6478
6455
|
this.select(...idsToSelect);
|
|
6479
6456
|
}
|
|
@@ -6554,14 +6531,14 @@ class Editor extends EventEmitter {
|
|
|
6554
6531
|
}
|
|
6555
6532
|
/** @internal */
|
|
6556
6533
|
_getUnlockedShapeIds(ids) {
|
|
6557
|
-
return ids.filter((id) => !this.
|
|
6534
|
+
return ids.filter((id) => !this.isShapeOrAncestorLocked(id));
|
|
6558
6535
|
}
|
|
6559
6536
|
deleteShapes(_ids) {
|
|
6560
6537
|
if (this.getIsReadonly()) return this;
|
|
6561
6538
|
if (!Array.isArray(_ids)) {
|
|
6562
6539
|
throw Error("Editor.deleteShapes: must provide an array of shapes or shapeIds");
|
|
6563
6540
|
}
|
|
6564
|
-
const shapeIds =
|
|
6541
|
+
const shapeIds = toShapeIds(_ids);
|
|
6565
6542
|
const shapeIdsToDelete = this._shouldIgnoreShapeLock ? shapeIds : this._getUnlockedShapeIds(shapeIds);
|
|
6566
6543
|
if (shapeIdsToDelete.length === 0) return this;
|
|
6567
6544
|
const allShapeIdsToDelete = new Set(shapeIdsToDelete);
|
|
@@ -6906,7 +6883,7 @@ class Editor extends EventEmitter {
|
|
|
6906
6883
|
* @public
|
|
6907
6884
|
*/
|
|
6908
6885
|
getContentFromCurrentPage(shapes) {
|
|
6909
|
-
const ids =
|
|
6886
|
+
const ids = toShapeIds(shapes);
|
|
6910
6887
|
if (!ids) return;
|
|
6911
6888
|
if (ids.length === 0) return;
|
|
6912
6889
|
const shapeIds = this.getShapeAndDescendantIds(ids);
|
|
@@ -6974,21 +6951,29 @@ class Editor extends EventEmitter {
|
|
|
6974
6951
|
await Promise.allSettled(
|
|
6975
6952
|
content.assets.map(async (asset) => {
|
|
6976
6953
|
if ((asset.type === "image" || asset.type === "video") && !asset.props.src?.startsWith("data:image") && !asset.props.src?.startsWith("data:video") && !asset.props.src?.startsWith("http")) {
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6954
|
+
try {
|
|
6955
|
+
const objectUrl = await this.store.props.assets.resolve(asset, {
|
|
6956
|
+
screenScale: 1,
|
|
6957
|
+
steppedScreenScale: 1,
|
|
6958
|
+
dpr: 1,
|
|
6959
|
+
networkEffectiveType: null,
|
|
6960
|
+
shouldResolveToOriginal: true
|
|
6961
|
+
});
|
|
6962
|
+
if (objectUrl) {
|
|
6963
|
+
const response = await fetch(objectUrl);
|
|
6964
|
+
if (response.ok) {
|
|
6965
|
+
const assetWithDataUrl = structuredClone(asset);
|
|
6966
|
+
assetWithDataUrl.props.src = await FileHelpers.blobToDataUrl(await response.blob());
|
|
6967
|
+
assets.push(assetWithDataUrl);
|
|
6968
|
+
return;
|
|
6969
|
+
}
|
|
6970
|
+
console.warn(`Could not inline asset ${asset.id}: fetch returned ${response.status}`);
|
|
6971
|
+
}
|
|
6972
|
+
} catch (err) {
|
|
6973
|
+
console.warn(`Could not inline asset ${asset.id}`, err);
|
|
6974
|
+
}
|
|
6991
6975
|
}
|
|
6976
|
+
assets.push(asset);
|
|
6992
6977
|
})
|
|
6993
6978
|
);
|
|
6994
6979
|
content.assets = assets;
|
|
@@ -7282,7 +7267,7 @@ class Editor extends EventEmitter {
|
|
|
7282
7267
|
* @public
|
|
7283
7268
|
*/
|
|
7284
7269
|
async getSvgElement(shapes, opts = {}) {
|
|
7285
|
-
const ids = shapes.length === 0 ? this.getCurrentPageShapeIdsSorted() :
|
|
7270
|
+
const ids = shapes.length === 0 ? this.getCurrentPageShapeIdsSorted() : toShapeIds(shapes);
|
|
7286
7271
|
if (ids.length === 0) return void 0;
|
|
7287
7272
|
await this.fonts.loadRequiredFontsForCurrentPage(this.options.maxFontsToLoadBeforeRender);
|
|
7288
7273
|
return exportToSvg(this, ids, opts);
|
|
@@ -7878,22 +7863,22 @@ class Editor extends EventEmitter {
|
|
|
7878
7863
|
const releaseCtrl = this._ctrlKeyTimeout !== -1;
|
|
7879
7864
|
const releaseMeta = this._metaKeyTimeout !== -1;
|
|
7880
7865
|
if (releaseShift) {
|
|
7881
|
-
clearTimeout(this._shiftKeyTimeout);
|
|
7866
|
+
this.timers.clearTimeout(this._shiftKeyTimeout);
|
|
7882
7867
|
this._shiftKeyTimeout = -1;
|
|
7883
7868
|
this.inputs.setShiftKey(false);
|
|
7884
7869
|
}
|
|
7885
7870
|
if (releaseAlt) {
|
|
7886
|
-
clearTimeout(this._altKeyTimeout);
|
|
7871
|
+
this.timers.clearTimeout(this._altKeyTimeout);
|
|
7887
7872
|
this._altKeyTimeout = -1;
|
|
7888
7873
|
this.inputs.setAltKey(false);
|
|
7889
7874
|
}
|
|
7890
7875
|
if (releaseCtrl) {
|
|
7891
|
-
clearTimeout(this._ctrlKeyTimeout);
|
|
7876
|
+
this.timers.clearTimeout(this._ctrlKeyTimeout);
|
|
7892
7877
|
this._ctrlKeyTimeout = -1;
|
|
7893
7878
|
this.inputs.setCtrlKey(false);
|
|
7894
7879
|
}
|
|
7895
7880
|
if (releaseMeta) {
|
|
7896
|
-
clearTimeout(this._metaKeyTimeout);
|
|
7881
|
+
this.timers.clearTimeout(this._metaKeyTimeout);
|
|
7897
7882
|
this._metaKeyTimeout = -1;
|
|
7898
7883
|
this.inputs.setMetaKey(false);
|
|
7899
7884
|
}
|
|
@@ -8007,28 +7992,28 @@ class Editor extends EventEmitter {
|
|
|
8007
7992
|
return;
|
|
8008
7993
|
}
|
|
8009
7994
|
if (info.shiftKey) {
|
|
8010
|
-
clearTimeout(this._shiftKeyTimeout);
|
|
7995
|
+
this.timers.clearTimeout(this._shiftKeyTimeout);
|
|
8011
7996
|
this._shiftKeyTimeout = -1;
|
|
8012
7997
|
inputs.setShiftKey(true);
|
|
8013
7998
|
} else if (!info.shiftKey && inputs.getShiftKey() && this._shiftKeyTimeout === -1) {
|
|
8014
7999
|
this._shiftKeyTimeout = this.timers.setTimeout(this._releaseShiftKey, 150);
|
|
8015
8000
|
}
|
|
8016
8001
|
if (info.altKey) {
|
|
8017
|
-
clearTimeout(this._altKeyTimeout);
|
|
8002
|
+
this.timers.clearTimeout(this._altKeyTimeout);
|
|
8018
8003
|
this._altKeyTimeout = -1;
|
|
8019
8004
|
inputs.setAltKey(true);
|
|
8020
8005
|
} else if (!info.altKey && inputs.getAltKey() && this._altKeyTimeout === -1) {
|
|
8021
8006
|
this._altKeyTimeout = this.timers.setTimeout(this._releaseAltKey, 150);
|
|
8022
8007
|
}
|
|
8023
8008
|
if (info.ctrlKey) {
|
|
8024
|
-
clearTimeout(this._ctrlKeyTimeout);
|
|
8009
|
+
this.timers.clearTimeout(this._ctrlKeyTimeout);
|
|
8025
8010
|
this._ctrlKeyTimeout = -1;
|
|
8026
8011
|
inputs.setCtrlKey(true);
|
|
8027
8012
|
} else if (!info.ctrlKey && inputs.getCtrlKey() && this._ctrlKeyTimeout === -1) {
|
|
8028
8013
|
this._ctrlKeyTimeout = this.timers.setTimeout(this._releaseCtrlKey, 150);
|
|
8029
8014
|
}
|
|
8030
8015
|
if (info.metaKey && info.name !== "key_up") {
|
|
8031
|
-
clearTimeout(this._metaKeyTimeout);
|
|
8016
|
+
this.timers.clearTimeout(this._metaKeyTimeout);
|
|
8032
8017
|
this._metaKeyTimeout = -1;
|
|
8033
8018
|
inputs.setMetaKey(true);
|
|
8034
8019
|
} else if (!info.metaKey && inputs.getMetaKey() && this._metaKeyTimeout === -1) {
|
|
@@ -8042,8 +8027,7 @@ class Editor extends EventEmitter {
|
|
|
8042
8027
|
const cameraOptions = this._cameraOptions.__unsafe__getWithoutCapture();
|
|
8043
8028
|
switch (type) {
|
|
8044
8029
|
case "pinch": {
|
|
8045
|
-
|
|
8046
|
-
clearTimeout(this._longPressTimeout);
|
|
8030
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8047
8031
|
this.inputs.updateFromEvent(info);
|
|
8048
8032
|
switch (info.name) {
|
|
8049
8033
|
case "pinch_start": {
|
|
@@ -8064,6 +8048,7 @@ class Editor extends EventEmitter {
|
|
|
8064
8048
|
}
|
|
8065
8049
|
case "pinch": {
|
|
8066
8050
|
if (!inputs.getIsPinching()) return;
|
|
8051
|
+
if (cameraOptions.isLocked) return;
|
|
8067
8052
|
const {
|
|
8068
8053
|
point: { z = 1 },
|
|
8069
8054
|
delta: { x: dx, y: dy }
|
|
@@ -8119,7 +8104,7 @@ class Editor extends EventEmitter {
|
|
|
8119
8104
|
const { panSpeed, zoomSpeed } = cameraOptions;
|
|
8120
8105
|
let wheelBehavior = cameraOptions.wheelBehavior;
|
|
8121
8106
|
const inputMode = this.user.getUserPreferences().inputMode;
|
|
8122
|
-
if (inputMode !== null) {
|
|
8107
|
+
if (inputMode !== null && wheelBehavior !== "none") {
|
|
8123
8108
|
wheelBehavior = inputMode === "trackpad" ? "pan" : "zoom";
|
|
8124
8109
|
}
|
|
8125
8110
|
if (wheelBehavior !== "none") {
|
|
@@ -8171,12 +8156,12 @@ class Editor extends EventEmitter {
|
|
|
8171
8156
|
}
|
|
8172
8157
|
case "pointer": {
|
|
8173
8158
|
if (inputs.getIsPinching()) return;
|
|
8174
|
-
this.inputs.updateFromEvent(info);
|
|
8175
8159
|
const { isPen } = info;
|
|
8176
8160
|
const { isPenMode } = instanceState;
|
|
8161
|
+
if (isPenMode && !isPen) return;
|
|
8162
|
+
this.inputs.updateFromEvent(info);
|
|
8177
8163
|
switch (info.name) {
|
|
8178
8164
|
case "pointer_down": {
|
|
8179
|
-
if (isPenMode && !isPen) return;
|
|
8180
8165
|
this._releaseDebouncedModifiers();
|
|
8181
8166
|
if (!this.inputs.getIsPanning()) {
|
|
8182
8167
|
this._longPressTimeout = this.timers.setTimeout(() => {
|
|
@@ -8200,11 +8185,12 @@ class Editor extends EventEmitter {
|
|
|
8200
8185
|
inputs.buttons.add(info.button);
|
|
8201
8186
|
inputs.setIsPointing(true);
|
|
8202
8187
|
inputs.setIsDragging(false);
|
|
8188
|
+
this.stopCameraAnimation();
|
|
8203
8189
|
if (!isPenMode && info.isPenDirect) {
|
|
8204
8190
|
this.updateInstanceState({ isPenMode: true });
|
|
8205
8191
|
this.interrupt();
|
|
8206
8192
|
}
|
|
8207
|
-
if (info.button === STYLUS_ERASER_BUTTON) {
|
|
8193
|
+
if (info.button === STYLUS_ERASER_BUTTON && this.getStateDescendant("eraser")) {
|
|
8208
8194
|
this._restoreToolId = this.getCurrentToolId();
|
|
8209
8195
|
this.complete();
|
|
8210
8196
|
this.setCurrentTool("eraser");
|
|
@@ -8213,10 +8199,10 @@ class Editor extends EventEmitter {
|
|
|
8213
8199
|
this._prevCursor = this.getInstanceState().cursor.type;
|
|
8214
8200
|
}
|
|
8215
8201
|
this.inputs.setIsPanning(true);
|
|
8216
|
-
clearTimeout(this._longPressTimeout);
|
|
8202
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8217
8203
|
} else if (info.button === RIGHT_MOUSE_BUTTON && this.options.rightClickPanning) {
|
|
8218
8204
|
this.inputs.setIsRightPointing(true);
|
|
8219
|
-
clearTimeout(this._longPressTimeout);
|
|
8205
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8220
8206
|
return this;
|
|
8221
8207
|
}
|
|
8222
8208
|
if (this.inputs.getIsPanning()) {
|
|
@@ -8227,7 +8213,6 @@ class Editor extends EventEmitter {
|
|
|
8227
8213
|
break;
|
|
8228
8214
|
}
|
|
8229
8215
|
case "pointer_move": {
|
|
8230
|
-
if (!isPen && isPenMode) return;
|
|
8231
8216
|
const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera());
|
|
8232
8217
|
if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
|
|
8233
8218
|
const currentScreenPoint = this.inputs.getCurrentScreenPoint();
|
|
@@ -8258,16 +8243,15 @@ class Editor extends EventEmitter {
|
|
|
8258
8243
|
}
|
|
8259
8244
|
if (inputs.getIsPointing() && !inputs.getIsDragging() && Vec.Dist2(inputs.getOriginPagePoint(), inputs.getCurrentPagePoint()) * this.getZoomLevel() > (instanceState.isCoarsePointer ? this.options.coarseDragDistanceSquared : this.options.dragDistanceSquared) / cz) {
|
|
8260
8245
|
inputs.setIsDragging(true);
|
|
8261
|
-
clearTimeout(this._longPressTimeout);
|
|
8246
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8262
8247
|
}
|
|
8263
8248
|
break;
|
|
8264
8249
|
}
|
|
8265
8250
|
case "pointer_up": {
|
|
8266
8251
|
inputs.setIsDragging(false);
|
|
8267
8252
|
inputs.setIsPointing(false);
|
|
8268
|
-
clearTimeout(this._longPressTimeout);
|
|
8253
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8269
8254
|
inputs.buttons.delete(info.button);
|
|
8270
|
-
if (instanceState.isPenMode && !isPen) return;
|
|
8271
8255
|
if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
|
|
8272
8256
|
this.inputs.setIsRightPointing(false);
|
|
8273
8257
|
this._selectedShapeIdsAtPointerDown = [];
|
|
@@ -8323,7 +8307,7 @@ class Editor extends EventEmitter {
|
|
|
8323
8307
|
});
|
|
8324
8308
|
}
|
|
8325
8309
|
} else {
|
|
8326
|
-
if (info.button === STYLUS_ERASER_BUTTON) {
|
|
8310
|
+
if (info.button === STYLUS_ERASER_BUTTON && this.getStateDescendant("eraser")) {
|
|
8327
8311
|
this.complete();
|
|
8328
8312
|
this.setCurrentTool(this._restoreToolId);
|
|
8329
8313
|
}
|
|
@@ -8336,8 +8320,8 @@ class Editor extends EventEmitter {
|
|
|
8336
8320
|
break;
|
|
8337
8321
|
}
|
|
8338
8322
|
case "keyboard": {
|
|
8339
|
-
if (info.
|
|
8340
|
-
if (info.
|
|
8323
|
+
if (info.code === "ShiftRight") info.code = "ShiftLeft";
|
|
8324
|
+
if (info.code === "AltRight") info.code = "AltLeft";
|
|
8341
8325
|
if (info.code === "ControlRight") info.code = "ControlLeft";
|
|
8342
8326
|
if (info.code === "MetaRight") info.code = "MetaLeft";
|
|
8343
8327
|
switch (info.name) {
|
|
@@ -8350,7 +8334,7 @@ class Editor extends EventEmitter {
|
|
|
8350
8334
|
}
|
|
8351
8335
|
this.inputs.setIsPanning(true);
|
|
8352
8336
|
this.inputs.setIsSpacebarPanning(true);
|
|
8353
|
-
clearTimeout(this._longPressTimeout);
|
|
8337
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8354
8338
|
this.setCursor({
|
|
8355
8339
|
type: this.inputs.getIsPointing() ? "grabbing" : "grab",
|
|
8356
8340
|
rotation: 0
|
|
@@ -8376,7 +8360,7 @@ class Editor extends EventEmitter {
|
|
|
8376
8360
|
break;
|
|
8377
8361
|
}
|
|
8378
8362
|
}
|
|
8379
|
-
if (offset) {
|
|
8363
|
+
if (offset && !cameraOptions.isLocked) {
|
|
8380
8364
|
const bounds = this.getViewportPageBounds();
|
|
8381
8365
|
const next = bounds.clone().translate(offset.mulV({ x: bounds.w, y: bounds.h }));
|
|
8382
8366
|
this._animateToViewport(next, { animation: { duration: 320 } });
|
|
@@ -8416,7 +8400,7 @@ class Editor extends EventEmitter {
|
|
|
8416
8400
|
this.setCurrentTool("select");
|
|
8417
8401
|
}
|
|
8418
8402
|
const { isPenMode } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID);
|
|
8419
|
-
if (info.isPen
|
|
8403
|
+
if (!isPenMode || info.isPen) {
|
|
8420
8404
|
const clickInfo = this._clickManager.handlePointerEvent(info);
|
|
8421
8405
|
if (info.name !== clickInfo.name) {
|
|
8422
8406
|
this.root.handleEvent(info);
|
|
@@ -8438,7 +8422,7 @@ class Editor extends EventEmitter {
|
|
|
8438
8422
|
maybeTrackPerformance(name) {
|
|
8439
8423
|
if (debugFlags.measurePerformance.get()) {
|
|
8440
8424
|
if (this.performanceTracker.isStarted()) {
|
|
8441
|
-
clearTimeout(this.performanceTrackerTimeout);
|
|
8425
|
+
this.timers.clearTimeout(this.performanceTrackerTimeout);
|
|
8442
8426
|
} else {
|
|
8443
8427
|
this.performanceTracker.start(name);
|
|
8444
8428
|
}
|
|
@@ -8707,6 +8691,9 @@ function pushShapeWithDescendants(editor, id, result) {
|
|
|
8707
8691
|
pushShapeWithDescendants(editor, childIds[i], result);
|
|
8708
8692
|
}
|
|
8709
8693
|
}
|
|
8694
|
+
function toShapeIds(shapes) {
|
|
8695
|
+
return typeof shapes[0] === "string" ? shapes : shapes.map((shape) => shape.id);
|
|
8696
|
+
}
|
|
8710
8697
|
function withIsolatedShapes(editor, shapeIds, callback) {
|
|
8711
8698
|
let result;
|
|
8712
8699
|
editor.run(
|
|
@@ -8729,7 +8716,7 @@ function withIsolatedShapes(editor, shapeIds, callback) {
|
|
|
8729
8716
|
}
|
|
8730
8717
|
}
|
|
8731
8718
|
}
|
|
8732
|
-
editor.
|
|
8719
|
+
editor._deleteBindings([...bindingsToRemove], { isolateShapes: true });
|
|
8733
8720
|
try {
|
|
8734
8721
|
result = Result.ok(callback(bindingsWithBoth));
|
|
8735
8722
|
} catch (error) {
|