@tldraw/editor 5.5.0-next.f9308d324e1c → 5.6.0-canary.5bfc37740468
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 +183 -185
- 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/shapes/shared/resizeBox.js +21 -16
- package/dist-cjs/lib/editor/shapes/shared/resizeBox.js.map +2 -2
- 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/useCursor.js +12 -8
- package/dist-cjs/lib/hooks/useCursor.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 +88 -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 +185 -186
- 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/editor/shapes/shared/resizeBox.mjs +21 -16
- package/dist-esm/lib/editor/shapes/shared/resizeBox.mjs.map +2 -2
- 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/useCursor.mjs +12 -8
- package/dist-esm/lib/hooks/useCursor.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 +89 -41
- 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 +18 -23
- 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 +299 -303
- 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/shapes/shared/resizeBox.ts +21 -16
- 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/useCursor.ts +14 -7
- 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/test/useCursor.test.tsx +36 -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 +330 -1
- package/src/lib/utils/sync/TLLocalSyncClient.ts +129 -55
- 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
|
@@ -95,6 +95,10 @@ var import_UserPreferencesManager = require("./managers/UserPreferencesManager/U
|
|
|
95
95
|
var import_OverlayManager = require("./overlays/OverlayManager");
|
|
96
96
|
var import_RootState = require("./tools/RootState");
|
|
97
97
|
const RENDERING_SHAPES_SORT_CACHE_THRESHOLD = 100;
|
|
98
|
+
const AXIS = {
|
|
99
|
+
horizontal: { val: "x", min: "minX", max: "maxX", dim: "width" },
|
|
100
|
+
vertical: { val: "y", min: "minY", max: "maxY", dim: "height" }
|
|
101
|
+
};
|
|
98
102
|
class Editor extends import_eventemitter3.default {
|
|
99
103
|
id = (0, import_utils.uniqueId)();
|
|
100
104
|
constructor({
|
|
@@ -421,7 +425,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
421
425
|
}
|
|
422
426
|
}
|
|
423
427
|
if (deleteBindingIds.length) {
|
|
424
|
-
this.
|
|
428
|
+
this.store.remove(deleteBindingIds);
|
|
425
429
|
}
|
|
426
430
|
}
|
|
427
431
|
},
|
|
@@ -1381,6 +1385,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
1381
1385
|
* @public
|
|
1382
1386
|
**/
|
|
1383
1387
|
updateDocumentSettings(settings) {
|
|
1388
|
+
if (this.getIsReadonly()) return this;
|
|
1384
1389
|
this.run(
|
|
1385
1390
|
() => {
|
|
1386
1391
|
this.store.put([{ ...this.getDocumentSettings(), ...settings }]);
|
|
@@ -1403,7 +1408,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
1403
1408
|
updateInstanceState(partial, historyOptions) {
|
|
1404
1409
|
this._updateInstanceState(partial, { history: "ignore", ...historyOptions });
|
|
1405
1410
|
if (partial.isChangingStyle !== void 0) {
|
|
1406
|
-
clearTimeout(this._isChangingStyleTimeout);
|
|
1411
|
+
this.timers.clearTimeout(this._isChangingStyleTimeout);
|
|
1407
1412
|
if (partial.isChangingStyle === true) {
|
|
1408
1413
|
this._isChangingStyleTimeout = this.timers.setTimeout(() => {
|
|
1409
1414
|
this._updateInstanceState({ isChangingStyle: false }, { history: "ignore" });
|
|
@@ -1540,7 +1545,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
1540
1545
|
* @public
|
|
1541
1546
|
*/
|
|
1542
1547
|
select(...shapes) {
|
|
1543
|
-
const ids =
|
|
1548
|
+
const ids = toShapeIds(shapes);
|
|
1544
1549
|
this.setSelectedShapes(ids);
|
|
1545
1550
|
return this;
|
|
1546
1551
|
}
|
|
@@ -1555,7 +1560,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
1555
1560
|
* @public
|
|
1556
1561
|
*/
|
|
1557
1562
|
deselect(...shapes) {
|
|
1558
|
-
const ids =
|
|
1563
|
+
const ids = toShapeIds(shapes);
|
|
1559
1564
|
const selectedShapeIds = this.getSelectedShapeIds();
|
|
1560
1565
|
if (selectedShapeIds.length > 0 && ids.length > 0) {
|
|
1561
1566
|
this.setSelectedShapes(selectedShapeIds.filter((id) => !ids.includes(id)));
|
|
@@ -1593,7 +1598,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
1593
1598
|
}
|
|
1594
1599
|
const ids = this.getSortedChildIdsForParent(parentToSelectWithinId);
|
|
1595
1600
|
if (ids.length <= 0) return this;
|
|
1596
|
-
this.setSelectedShapes(this.
|
|
1601
|
+
this.setSelectedShapes(ids.filter((id) => !this.getShape(id)?.isLocked));
|
|
1597
1602
|
return this;
|
|
1598
1603
|
}
|
|
1599
1604
|
/**
|
|
@@ -1610,12 +1615,15 @@ class Editor extends import_eventemitter3.default {
|
|
|
1610
1615
|
const selectedShapeIds = this.getSelectedShapeIds();
|
|
1611
1616
|
const firstParentId = selectedShapeIds[0] ? this.getShape(selectedShapeIds[0])?.parentId : null;
|
|
1612
1617
|
const isSelectedWithinContainer = firstParentId && selectedShapeIds.every((shapeId) => this.getShape(shapeId)?.parentId === firstParentId) && !(0, import_tlschema.isPageId)(firstParentId);
|
|
1613
|
-
const filteredShapes =
|
|
1614
|
-
|
|
1618
|
+
const filteredShapes = this.getCurrentPageShapes().filter(
|
|
1619
|
+
(shape2) => !this.isShapeOrAncestorLocked(shape2) && (isSelectedWithinContainer ? shape2.parentId === firstParentId : (0, import_tlschema.isPageId)(shape2.parentId))
|
|
1620
|
+
);
|
|
1621
|
+
const readingOrderShapes = this._getShapesInReadingOrder(filteredShapes);
|
|
1615
1622
|
const currentShapeId = selectedShapeIds.length === 1 ? selectedShapeIds[0] : readingOrderShapes.find((shape2) => selectedShapeIds.includes(shape2.id))?.id;
|
|
1616
1623
|
let adjacentShapeId;
|
|
1617
1624
|
if (direction === "next" || direction === "prev") {
|
|
1618
1625
|
const shapeIds = readingOrderShapes.map((shape2) => shape2.id);
|
|
1626
|
+
if (shapeIds.length === 0) return;
|
|
1619
1627
|
const currentIndex = currentShapeId ? shapeIds.indexOf(currentShapeId) : -1;
|
|
1620
1628
|
const startIndex = currentIndex === -1 && direction === "prev" ? 0 : currentIndex;
|
|
1621
1629
|
const adjacentIndex = (startIndex + (direction === "next" ? 1 : -1) + shapeIds.length) % shapeIds.length;
|
|
@@ -1717,13 +1725,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
1717
1725
|
});
|
|
1718
1726
|
if (shapesInDirection.length === 0) return currentShapeId;
|
|
1719
1727
|
const lowestScoringShape = (0, import_utils.minBy)(shapesInDirection, ({ center }) => {
|
|
1720
|
-
const distance = import_Vec.Vec.
|
|
1728
|
+
const distance = import_Vec.Vec.Dist(currentCenter, center);
|
|
1721
1729
|
const dirProp = ["left", "right"].includes(direction) ? "x" : "y";
|
|
1722
1730
|
const directionalDistance = Math.abs(center[dirProp] - currentCenter[dirProp]);
|
|
1723
1731
|
const offProp = ["left", "right"].includes(direction) ? "y" : "x";
|
|
1724
1732
|
const offAxisDeviation = Math.abs(center[offProp] - currentCenter[offProp]);
|
|
1725
|
-
const angle =
|
|
1726
|
-
const
|
|
1733
|
+
const angle = (import_Vec.Vec.Angle(currentCenter, center) * (180 / Math.PI) + 360) % 360;
|
|
1734
|
+
const rawAngleDeviation = Math.abs(angle - directionToAngle[direction]);
|
|
1735
|
+
const angleDeviation = Math.min(rawAngleDeviation, 360 - rawAngleDeviation);
|
|
1727
1736
|
return distance * 1 + // Base distance
|
|
1728
1737
|
offAxisDeviation * 2 + // Heavy penalty for off-axis deviation
|
|
1729
1738
|
(distance - directionalDistance) * 1.5 + // Penalty for diagonal distance
|
|
@@ -2061,7 +2070,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2061
2070
|
* @public
|
|
2062
2071
|
*/
|
|
2063
2072
|
setHintingShapes(shapes) {
|
|
2064
|
-
const ids =
|
|
2073
|
+
const ids = toShapeIds(shapes);
|
|
2065
2074
|
this.run(
|
|
2066
2075
|
() => {
|
|
2067
2076
|
this._updateCurrentPageState({ hintingShapeIds: (0, import_utils.dedupe)(ids) });
|
|
@@ -2091,7 +2100,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2091
2100
|
* @public
|
|
2092
2101
|
*/
|
|
2093
2102
|
setErasingShapes(shapes) {
|
|
2094
|
-
const ids =
|
|
2103
|
+
const ids = toShapeIds(shapes).slice();
|
|
2095
2104
|
ids.sort();
|
|
2096
2105
|
const erasingShapeIds = this.getErasingShapeIds();
|
|
2097
2106
|
this.run(
|
|
@@ -2498,14 +2507,16 @@ class Editor extends import_eventemitter3.default {
|
|
|
2498
2507
|
setCamera(point, opts) {
|
|
2499
2508
|
const { isLocked } = this._cameraOptions.__unsafe__getWithoutCapture();
|
|
2500
2509
|
if (isLocked && !opts?.force) return this;
|
|
2510
|
+
const _point = new import_Vec.Vec(point.x, point.y, point.z ?? this.getZoomLevel());
|
|
2511
|
+
if (!Number.isFinite(_point.x) || !Number.isFinite(_point.y) || !Number.isFinite(_point.z)) {
|
|
2512
|
+
throw Error(
|
|
2513
|
+
`Editor.setCamera: expected finite values, got (${_point.x}, ${_point.y}, ${_point.z}).`
|
|
2514
|
+
);
|
|
2515
|
+
}
|
|
2501
2516
|
this.stopCameraAnimation();
|
|
2502
2517
|
if (this.getInstanceState().followingUserId) {
|
|
2503
2518
|
this.stopFollowingUser();
|
|
2504
2519
|
}
|
|
2505
|
-
const _point = import_Vec.Vec.Cast(point);
|
|
2506
|
-
if (!Number.isFinite(_point.x)) _point.x = 0;
|
|
2507
|
-
if (!Number.isFinite(_point.y)) _point.y = 0;
|
|
2508
|
-
if (_point.z === void 0 || !Number.isFinite(_point.z)) point.z = this.getZoomLevel();
|
|
2509
2520
|
const camera = this.getConstrainedCamera(_point, opts);
|
|
2510
2521
|
if (opts?.animation) {
|
|
2511
2522
|
const { width, height } = this.getViewportScreenBounds();
|
|
@@ -2790,11 +2801,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
2790
2801
|
_animateViewport(ms) {
|
|
2791
2802
|
if (!this._viewportAnimation) return;
|
|
2792
2803
|
this._viewportAnimation.elapsed += ms;
|
|
2793
|
-
const { elapsed, easing, duration, start, end } = this._viewportAnimation;
|
|
2804
|
+
const { elapsed, easing, duration, start, end, opts } = this._viewportAnimation;
|
|
2794
2805
|
if (elapsed > duration) {
|
|
2795
2806
|
this.off("tick", this._animateViewport);
|
|
2796
2807
|
this._viewportAnimation = null;
|
|
2797
|
-
this._setCamera(
|
|
2808
|
+
this._setCamera(
|
|
2809
|
+
new import_Vec.Vec(-end.x, -end.y, this.getViewportScreenBounds().width / end.width),
|
|
2810
|
+
opts
|
|
2811
|
+
);
|
|
2798
2812
|
return;
|
|
2799
2813
|
}
|
|
2800
2814
|
const remaining = duration - elapsed;
|
|
@@ -2832,7 +2846,8 @@ class Editor extends import_eventemitter3.default {
|
|
|
2832
2846
|
duration: duration / animationSpeed,
|
|
2833
2847
|
easing,
|
|
2834
2848
|
start: viewportPageBounds.clone(),
|
|
2835
|
-
end: targetViewportPage.clone()
|
|
2849
|
+
end: targetViewportPage.clone(),
|
|
2850
|
+
opts: rest
|
|
2836
2851
|
};
|
|
2837
2852
|
this.once("stop-camera-animation", () => {
|
|
2838
2853
|
this.off("tick", this._animateViewport);
|
|
@@ -2918,6 +2933,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2918
2933
|
}
|
|
2919
2934
|
const isOnSamePage = presence.currentPageId === this.getCurrentPageId();
|
|
2920
2935
|
if (!isOnSamePage) {
|
|
2936
|
+
this.markHistoryStoppingPoint("change-page");
|
|
2921
2937
|
this.setCurrentPage(presence.currentPageId);
|
|
2922
2938
|
}
|
|
2923
2939
|
if (opts && opts.animation && !isOnSamePage) {
|
|
@@ -3641,7 +3657,9 @@ class Editor extends import_eventemitter3.default {
|
|
|
3641
3657
|
const id = typeof page === "string" ? page : page.id;
|
|
3642
3658
|
const freshPage = this.getPage(id);
|
|
3643
3659
|
if (!freshPage) return this;
|
|
3644
|
-
const prevCamera = {
|
|
3660
|
+
const prevCamera = {
|
|
3661
|
+
...this.store.get(import_tlschema.CameraRecordType.createId(freshPage.id)) ?? this.getCamera()
|
|
3662
|
+
};
|
|
3645
3663
|
const content = this.getContentFromCurrentPage(this.getSortedChildIdsForParent(freshPage.id));
|
|
3646
3664
|
this.run(() => {
|
|
3647
3665
|
const pages = this.getPages();
|
|
@@ -3650,7 +3668,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
3650
3668
|
this.setCurrentPage(createId);
|
|
3651
3669
|
this.setCamera(prevCamera);
|
|
3652
3670
|
if (content) {
|
|
3653
|
-
return this.putContentOntoCurrentPage(content);
|
|
3671
|
+
return this.putContentOntoCurrentPage(content, { preservePosition: true });
|
|
3654
3672
|
}
|
|
3655
3673
|
});
|
|
3656
3674
|
return this;
|
|
@@ -3749,7 +3767,9 @@ class Editor extends import_eventemitter3.default {
|
|
|
3749
3767
|
if (ids.length <= 0) return this;
|
|
3750
3768
|
this.run(
|
|
3751
3769
|
() => {
|
|
3752
|
-
this.store.props.assets.remove?.(ids)
|
|
3770
|
+
Promise.resolve(this.store.props.assets.remove?.(ids)).catch(
|
|
3771
|
+
(err) => console.error("Error while removing assets from the asset store:", err)
|
|
3772
|
+
);
|
|
3753
3773
|
this.store.remove(ids);
|
|
3754
3774
|
},
|
|
3755
3775
|
{ history: "ignore" }
|
|
@@ -4131,7 +4151,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4131
4151
|
if (shapes.length === 0) {
|
|
4132
4152
|
return;
|
|
4133
4153
|
}
|
|
4134
|
-
const ids =
|
|
4154
|
+
const ids = toShapeIds(shapes);
|
|
4135
4155
|
const freshShapes = (0, import_utils.compact)(ids.map((id) => this.getShape(id)));
|
|
4136
4156
|
if (freshShapes.length === 1) {
|
|
4137
4157
|
const parentId = freshShapes[0].parentId;
|
|
@@ -4228,12 +4248,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
4228
4248
|
*/
|
|
4229
4249
|
getSelectedShapeAtPoint(point) {
|
|
4230
4250
|
const selectedShapeIds = this.getSelectedShapeIds();
|
|
4231
|
-
|
|
4251
|
+
if (selectedShapeIds.length === 0) return void 0;
|
|
4252
|
+
const selectedShapeIdSet = new Set(selectedShapeIds);
|
|
4253
|
+
const margin = this.getHitTestMargin();
|
|
4232
4254
|
const sortedShapes = this.getCurrentPageShapesSorted();
|
|
4233
4255
|
for (let i = sortedShapes.length - 1; i >= 0; i--) {
|
|
4234
4256
|
const shape = sortedShapes[i];
|
|
4235
4257
|
if (shape.type === "group") continue;
|
|
4236
|
-
if (!
|
|
4258
|
+
if (!selectedShapeIdSet.has(shape.id)) continue;
|
|
4237
4259
|
if (this.getShapeGeometry(shape).hitTestPoint(
|
|
4238
4260
|
this.getPointInShapeSpace(shape, point),
|
|
4239
4261
|
margin,
|
|
@@ -4331,7 +4353,6 @@ class Editor extends import_eventemitter3.default {
|
|
|
4331
4353
|
}
|
|
4332
4354
|
return inMarginClosestToEdgeHit || shape;
|
|
4333
4355
|
} else {
|
|
4334
|
-
if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
|
|
4335
4356
|
if (hitInside ? (
|
|
4336
4357
|
// On hitInside, the distance will be negative for hits inside
|
|
4337
4358
|
// If the distance is positive, check against the outer margin
|
|
@@ -4348,6 +4369,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4348
4369
|
inMarginClosestToEdgeHit = shape;
|
|
4349
4370
|
}
|
|
4350
4371
|
} else if (!inMarginClosestToEdgeHit) {
|
|
4372
|
+
if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
|
|
4351
4373
|
const { area } = geometry;
|
|
4352
4374
|
if (area < inHollowSmallestArea) {
|
|
4353
4375
|
inHollowSmallestArea = area;
|
|
@@ -4358,6 +4380,9 @@ class Editor extends import_eventemitter3.default {
|
|
|
4358
4380
|
}
|
|
4359
4381
|
} else {
|
|
4360
4382
|
if (distance < this.getHitTestMargin()) {
|
|
4383
|
+
if (inMarginClosestToEdgeHit && inMarginClosestToEdgeDistance <= distance) {
|
|
4384
|
+
return inMarginClosestToEdgeHit;
|
|
4385
|
+
}
|
|
4361
4386
|
return shape;
|
|
4362
4387
|
}
|
|
4363
4388
|
}
|
|
@@ -4634,7 +4659,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4634
4659
|
* @public
|
|
4635
4660
|
*/
|
|
4636
4661
|
reparentShapes(shapes, parentId, insertIndex) {
|
|
4637
|
-
const ids =
|
|
4662
|
+
const ids = toShapeIds(shapes);
|
|
4638
4663
|
if (ids.length === 0) return this;
|
|
4639
4664
|
const changes = [];
|
|
4640
4665
|
const parentTransform = (0, import_tlschema.isPageId)(parentId) ? import_Mat.Mat.Identity() : this.getShapePageTransform(parentId);
|
|
@@ -4863,6 +4888,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4863
4888
|
* binding, but the `type`, `toId`, and `fromId` must all be provided.
|
|
4864
4889
|
*/
|
|
4865
4890
|
createBindings(partials) {
|
|
4891
|
+
if (this.getIsReadonly()) return this;
|
|
4866
4892
|
const bindings = [];
|
|
4867
4893
|
for (const partial of partials) {
|
|
4868
4894
|
const fromShape = this.getShape(partial.fromId);
|
|
@@ -4897,6 +4923,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4897
4923
|
* binding is skipped. The changes from the partial are merged into the existing record.
|
|
4898
4924
|
*/
|
|
4899
4925
|
updateBindings(partials) {
|
|
4926
|
+
if (this.getIsReadonly()) return this;
|
|
4900
4927
|
const updated = [];
|
|
4901
4928
|
for (const partial of partials) {
|
|
4902
4929
|
if (!partial) continue;
|
|
@@ -4925,6 +4952,16 @@ class Editor extends import_eventemitter3.default {
|
|
|
4925
4952
|
* Delete several bindings by their IDs. If a binding ID doesn't exist, it's ignored.
|
|
4926
4953
|
*/
|
|
4927
4954
|
deleteBindings(bindings, { isolateShapes = false } = {}) {
|
|
4955
|
+
if (this.getIsReadonly()) return this;
|
|
4956
|
+
return this._deleteBindings(bindings, { isolateShapes });
|
|
4957
|
+
}
|
|
4958
|
+
/**
|
|
4959
|
+
* Unguarded so that withIsolatedShapes can transiently isolate shapes for copy and export in
|
|
4960
|
+
* readonly mode; the public deleteBindings is what readonly blocks.
|
|
4961
|
+
*
|
|
4962
|
+
* @internal
|
|
4963
|
+
*/
|
|
4964
|
+
_deleteBindings(bindings, { isolateShapes = false } = {}) {
|
|
4928
4965
|
const ids = bindings.map((binding) => typeof binding === "string" ? binding : binding.id);
|
|
4929
4966
|
if (isolateShapes) {
|
|
4930
4967
|
this.store.atomic(() => {
|
|
@@ -4983,7 +5020,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4983
5020
|
* @param opts - The options for the rotation.
|
|
4984
5021
|
*/
|
|
4985
5022
|
rotateShapesBy(shapes, delta, opts) {
|
|
4986
|
-
const ids =
|
|
5023
|
+
const ids = toShapeIds(shapes);
|
|
4987
5024
|
if (ids.length <= 0) return this;
|
|
4988
5025
|
const snapshot = (0, import_rotation.getRotationSnapshot)({ editor: this, ids });
|
|
4989
5026
|
if (!snapshot) return this;
|
|
@@ -5020,6 +5057,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
5020
5057
|
}
|
|
5021
5058
|
return workingShape;
|
|
5022
5059
|
}
|
|
5060
|
+
// Counter-rotates the page-space delta into the parent's space; without that a child of a rotated
|
|
5061
|
+
// frame or group would move along its parent's axes instead of the page's.
|
|
5062
|
+
// todo: a shape laid out together with its own parent moves twice, once with the parent and once
|
|
5063
|
+
// on its own; the layout commands should skip shapes whose ancestors are also being laid out
|
|
5064
|
+
getChangesToTranslateShapeByPageDelta(shape, pageDelta) {
|
|
5065
|
+
const localDelta = import_Vec.Vec.From(pageDelta).rot(-this.getShapeParentTransform(shape).rotation());
|
|
5066
|
+
return this.getChangesToTranslateShape(shape, localDelta.add(shape));
|
|
5067
|
+
}
|
|
5023
5068
|
/**
|
|
5024
5069
|
* Move shapes by a delta.
|
|
5025
5070
|
*
|
|
@@ -5032,14 +5077,12 @@ class Editor extends import_eventemitter3.default {
|
|
|
5032
5077
|
* @param offset - The offset to apply to the shapes.
|
|
5033
5078
|
*/
|
|
5034
5079
|
nudgeShapes(shapes, offset) {
|
|
5035
|
-
const ids =
|
|
5080
|
+
const ids = toShapeIds(shapes);
|
|
5036
5081
|
if (ids.length <= 0) return this;
|
|
5037
5082
|
const changes = [];
|
|
5038
5083
|
for (const id of ids) {
|
|
5039
5084
|
const shape = this.getShape(id);
|
|
5040
|
-
|
|
5041
|
-
localDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5042
|
-
changes.push(this.getChangesToTranslateShape(shape, localDelta.add(shape)));
|
|
5085
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, offset));
|
|
5043
5086
|
}
|
|
5044
5087
|
this.updateShapes(changes);
|
|
5045
5088
|
return this;
|
|
@@ -5060,7 +5103,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5060
5103
|
*/
|
|
5061
5104
|
duplicateShapes(shapes, offset) {
|
|
5062
5105
|
this.run(() => {
|
|
5063
|
-
const _ids =
|
|
5106
|
+
const _ids = toShapeIds(shapes);
|
|
5064
5107
|
const ids = this._shouldIgnoreShapeLock ? _ids : this._getUnlockedShapeIds(_ids);
|
|
5065
5108
|
if (ids.length <= 0) return this;
|
|
5066
5109
|
const initialIds = new Set(ids);
|
|
@@ -5169,7 +5212,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5169
5212
|
* @public
|
|
5170
5213
|
*/
|
|
5171
5214
|
moveShapesToPage(shapes, pageId) {
|
|
5172
|
-
const ids =
|
|
5215
|
+
const ids = toShapeIds(shapes);
|
|
5173
5216
|
if (ids.length === 0) return this;
|
|
5174
5217
|
if (this.getIsReadonly()) return this;
|
|
5175
5218
|
const currentPageId = this.getCurrentPageId();
|
|
@@ -5205,7 +5248,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5205
5248
|
* @public
|
|
5206
5249
|
*/
|
|
5207
5250
|
toggleLock(shapes) {
|
|
5208
|
-
const ids =
|
|
5251
|
+
const ids = toShapeIds(shapes);
|
|
5209
5252
|
if (this.getIsReadonly() || ids.length === 0) return this;
|
|
5210
5253
|
let allLocked = true;
|
|
5211
5254
|
const shapesToToggle = [];
|
|
@@ -5244,7 +5287,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5244
5287
|
* @public
|
|
5245
5288
|
*/
|
|
5246
5289
|
sendToBack(shapes) {
|
|
5247
|
-
const ids =
|
|
5290
|
+
const ids = toShapeIds(shapes);
|
|
5248
5291
|
const changes = (0, import_reorderShapes.getReorderingShapesChanges)(this, "toBack", ids, {
|
|
5249
5292
|
considerAllShapes: true
|
|
5250
5293
|
});
|
|
@@ -5274,7 +5317,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5274
5317
|
* @public
|
|
5275
5318
|
*/
|
|
5276
5319
|
sendBackward(shapes, opts = {}) {
|
|
5277
|
-
const ids =
|
|
5320
|
+
const ids = toShapeIds(shapes);
|
|
5278
5321
|
const changes = (0, import_reorderShapes.getReorderingShapesChanges)(this, "backward", ids, opts);
|
|
5279
5322
|
if (changes) this.updateShapes(changes);
|
|
5280
5323
|
return this;
|
|
@@ -5302,7 +5345,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5302
5345
|
* @public
|
|
5303
5346
|
*/
|
|
5304
5347
|
bringForward(shapes, opts = {}) {
|
|
5305
|
-
const ids =
|
|
5348
|
+
const ids = toShapeIds(shapes);
|
|
5306
5349
|
const changes = (0, import_reorderShapes.getReorderingShapesChanges)(this, "forward", ids, opts);
|
|
5307
5350
|
if (changes) this.updateShapes(changes);
|
|
5308
5351
|
return this;
|
|
@@ -5321,7 +5364,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5321
5364
|
* @public
|
|
5322
5365
|
*/
|
|
5323
5366
|
bringToFront(shapes) {
|
|
5324
|
-
const ids =
|
|
5367
|
+
const ids = toShapeIds(shapes);
|
|
5325
5368
|
const changes = (0, import_reorderShapes.getReorderingShapesChanges)(this, "toFront", ids);
|
|
5326
5369
|
if (changes) this.updateShapes(changes);
|
|
5327
5370
|
return this;
|
|
@@ -5333,7 +5376,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5333
5376
|
* @internal
|
|
5334
5377
|
*/
|
|
5335
5378
|
getShapeClusters(shapes, type, opts) {
|
|
5336
|
-
const ids =
|
|
5379
|
+
const ids = toShapeIds(shapes);
|
|
5337
5380
|
let freshShapes = (0, import_utils.compact)(ids.map((id) => this.getShape(id)));
|
|
5338
5381
|
if (opts?.filterAxisAligned) {
|
|
5339
5382
|
freshShapes = freshShapes.filter((s) => {
|
|
@@ -5358,7 +5401,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5358
5401
|
const shapesMovingTogether = [shape];
|
|
5359
5402
|
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
5360
5403
|
this.collectShapesViaArrowBindings({
|
|
5361
|
-
bindings: this.
|
|
5404
|
+
bindings: this.getBindingsInvolvingShape(shape.id, "arrow"),
|
|
5362
5405
|
initialShapes: freshShapes,
|
|
5363
5406
|
resultShapes: shapesMovingTogether,
|
|
5364
5407
|
resultBounds: boundsOfShapesMovingTogether,
|
|
@@ -5414,7 +5457,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5414
5457
|
*/
|
|
5415
5458
|
flipShapes(shapes, operation) {
|
|
5416
5459
|
if (this.getIsReadonly()) return this;
|
|
5417
|
-
const ids =
|
|
5460
|
+
const ids = toShapeIds(shapes);
|
|
5418
5461
|
const shapesToFlipFirstPass = (0, import_utils.compact)(ids.map((id) => this.getShape(id)));
|
|
5419
5462
|
for (const shape of shapesToFlipFirstPass) {
|
|
5420
5463
|
if (this.isShapeOfType(shape, "group")) {
|
|
@@ -5488,21 +5531,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5488
5531
|
const { clusters: shapeClustersToStack } = this.getShapeClusters(shapes, "stack");
|
|
5489
5532
|
const len = shapeClustersToStack.length;
|
|
5490
5533
|
if (_gap === 0 && len < 3 || len < 2) return this;
|
|
5491
|
-
|
|
5492
|
-
let min;
|
|
5493
|
-
let max;
|
|
5494
|
-
let dim;
|
|
5495
|
-
if (operation === "horizontal") {
|
|
5496
|
-
val = "x";
|
|
5497
|
-
min = "minX";
|
|
5498
|
-
max = "maxX";
|
|
5499
|
-
dim = "width";
|
|
5500
|
-
} else {
|
|
5501
|
-
val = "y";
|
|
5502
|
-
min = "minY";
|
|
5503
|
-
max = "maxY";
|
|
5504
|
-
dim = "height";
|
|
5505
|
-
}
|
|
5534
|
+
const { val, min, max, dim } = AXIS[operation];
|
|
5506
5535
|
let shapeGap = 0;
|
|
5507
5536
|
shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
|
|
5508
5537
|
if (_gap === 0) {
|
|
@@ -5541,13 +5570,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5541
5570
|
const delta = new import_Vec.Vec();
|
|
5542
5571
|
delta[val] = v + shapeGap - pageBounds[val];
|
|
5543
5572
|
for (const shape of shapes2) {
|
|
5544
|
-
|
|
5545
|
-
const parent = this.getShapeParent(shape);
|
|
5546
|
-
if (parent) {
|
|
5547
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5548
|
-
}
|
|
5549
|
-
shapeDelta.add(shape);
|
|
5550
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5573
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5551
5574
|
}
|
|
5552
5575
|
v += pageBounds[dim] + shapeGap;
|
|
5553
5576
|
}
|
|
@@ -5627,13 +5650,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5627
5650
|
for (const { shapes: shapes2, pageBounds, nextPageBounds } of shapeClustersToPack) {
|
|
5628
5651
|
const delta = import_Vec.Vec.Sub(nextPageBounds.point, pageBounds.point).add(centerDelta);
|
|
5629
5652
|
for (const shape of shapes2) {
|
|
5630
|
-
|
|
5631
|
-
const parent = this.getShapeParent(shape);
|
|
5632
|
-
if (parent) {
|
|
5633
|
-
shapeDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5634
|
-
}
|
|
5635
|
-
shapeDelta.add(shape);
|
|
5636
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5653
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5637
5654
|
}
|
|
5638
5655
|
}
|
|
5639
5656
|
if (changes.length) {
|
|
@@ -5693,13 +5710,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5693
5710
|
}
|
|
5694
5711
|
}
|
|
5695
5712
|
for (const shape of shapes2) {
|
|
5696
|
-
|
|
5697
|
-
const parent = this.getShapeParent(shape);
|
|
5698
|
-
if (parent) {
|
|
5699
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5700
|
-
}
|
|
5701
|
-
shapeDelta.add(shape);
|
|
5702
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5713
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5703
5714
|
}
|
|
5704
5715
|
});
|
|
5705
5716
|
this.updateShapes(changes);
|
|
@@ -5723,27 +5734,13 @@ class Editor extends import_eventemitter3.default {
|
|
|
5723
5734
|
if (this.getIsReadonly()) return this;
|
|
5724
5735
|
const { clusters: shapeClustersToDistribute } = this.getShapeClusters(shapes, "distribute");
|
|
5725
5736
|
if (shapeClustersToDistribute.length < 3) return this;
|
|
5726
|
-
|
|
5727
|
-
let min;
|
|
5728
|
-
let max;
|
|
5729
|
-
let dim;
|
|
5730
|
-
if (operation === "horizontal") {
|
|
5731
|
-
val = "x";
|
|
5732
|
-
min = "minX";
|
|
5733
|
-
max = "maxX";
|
|
5734
|
-
dim = "width";
|
|
5735
|
-
} else {
|
|
5736
|
-
val = "y";
|
|
5737
|
-
min = "minY";
|
|
5738
|
-
max = "maxY";
|
|
5739
|
-
dim = "height";
|
|
5740
|
-
}
|
|
5737
|
+
const { val, min, max, dim } = AXIS[operation];
|
|
5741
5738
|
const changes = [];
|
|
5742
5739
|
const first = shapeClustersToDistribute.sort((a, b) => a.pageBounds[min] - b.pageBounds[min])[0];
|
|
5743
5740
|
const last2 = shapeClustersToDistribute.sort((a, b) => b.pageBounds[max] - a.pageBounds[max])[0];
|
|
5744
5741
|
if (first === last2) {
|
|
5745
5742
|
const excludedShapeIds = new Set(first.shapes.map((s) => s.id));
|
|
5746
|
-
const ids =
|
|
5743
|
+
const ids = toShapeIds(shapes);
|
|
5747
5744
|
return this.distributeShapes(
|
|
5748
5745
|
ids.filter((id) => !excludedShapeIds.has(id)),
|
|
5749
5746
|
operation
|
|
@@ -5767,13 +5764,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5767
5764
|
delta[val] = last2.pageBounds[max] - pageBounds[max] - 1;
|
|
5768
5765
|
}
|
|
5769
5766
|
for (const shape of shapes2) {
|
|
5770
|
-
|
|
5771
|
-
const parent = this.getShapeParent(shape);
|
|
5772
|
-
if (parent) {
|
|
5773
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5774
|
-
}
|
|
5775
|
-
shapeDelta.add(shape);
|
|
5776
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5767
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5777
5768
|
}
|
|
5778
5769
|
v += pageBounds[dim] + gap;
|
|
5779
5770
|
}
|
|
@@ -5803,32 +5794,17 @@ class Editor extends import_eventemitter3.default {
|
|
|
5803
5794
|
);
|
|
5804
5795
|
if (shapeClustersToStretch.length < 2) return this;
|
|
5805
5796
|
const commonBounds = import_Box.Box.Common(allBounds);
|
|
5806
|
-
|
|
5807
|
-
let min;
|
|
5808
|
-
let dim;
|
|
5809
|
-
if (operation === "horizontal") {
|
|
5810
|
-
val = "x";
|
|
5811
|
-
min = "minX";
|
|
5812
|
-
dim = "width";
|
|
5813
|
-
} else {
|
|
5814
|
-
val = "y";
|
|
5815
|
-
min = "minY";
|
|
5816
|
-
dim = "height";
|
|
5817
|
-
}
|
|
5797
|
+
const { val, min, dim } = AXIS[operation];
|
|
5818
5798
|
this.run(() => {
|
|
5819
5799
|
shapeClustersToStretch.forEach(({ shapes: shapes2, pageBounds }) => {
|
|
5820
|
-
const
|
|
5821
|
-
|
|
5800
|
+
const pageOffset = new import_Vec.Vec();
|
|
5801
|
+
pageOffset[val] = commonBounds[min] - pageBounds[min];
|
|
5822
5802
|
const scaleOrigin = pageBounds.center.clone();
|
|
5823
5803
|
scaleOrigin[val] = commonBounds[min];
|
|
5824
5804
|
const scale = new import_Vec.Vec(1, 1);
|
|
5825
5805
|
scale[val] = commonBounds[dim] / pageBounds[dim];
|
|
5826
5806
|
for (const shape of shapes2) {
|
|
5827
|
-
|
|
5828
|
-
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5829
|
-
shapeLocalOffset.add(shape);
|
|
5830
|
-
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5831
|
-
this.updateShape(changes);
|
|
5807
|
+
this.updateShape(this.getChangesToTranslateShapeByPageDelta(shape, pageOffset));
|
|
5832
5808
|
this.resizeShape(shape.id, scale, {
|
|
5833
5809
|
initialBounds: this.getShapeGeometry(shape).bounds,
|
|
5834
5810
|
scaleOrigin,
|
|
@@ -5871,7 +5847,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5871
5847
|
const scaleY = targetBounds.height / commonBounds.height;
|
|
5872
5848
|
const scale = new import_Vec.Vec(scaleX, scaleY);
|
|
5873
5849
|
shapeClusters.forEach(({ shapes: shapes2, pageBounds }) => {
|
|
5874
|
-
const
|
|
5850
|
+
const pageOffset = new import_Vec.Vec(
|
|
5875
5851
|
targetBounds.minX - commonBounds.minX + (pageBounds.minX - commonBounds.minX) * (scaleX - 1),
|
|
5876
5852
|
targetBounds.minY - commonBounds.minY + (pageBounds.minY - commonBounds.minY) * (scaleY - 1)
|
|
5877
5853
|
);
|
|
@@ -5880,11 +5856,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5880
5856
|
targetBounds.minY + (pageBounds.minY - commonBounds.minY) * scaleY
|
|
5881
5857
|
);
|
|
5882
5858
|
for (const shape of shapes2) {
|
|
5883
|
-
|
|
5884
|
-
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5885
|
-
shapeLocalOffset.add(shape);
|
|
5886
|
-
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5887
|
-
this.updateShape(changes);
|
|
5859
|
+
this.updateShape(this.getChangesToTranslateShapeByPageDelta(shape, pageOffset));
|
|
5888
5860
|
this.resizeShape(shape.id, scale, {
|
|
5889
5861
|
initialBounds: this.getShapeGeometry(shape).bounds,
|
|
5890
5862
|
scaleOrigin,
|
|
@@ -6060,11 +6032,20 @@ class Editor extends import_eventemitter3.default {
|
|
|
6060
6032
|
initialShape: options.initialShape,
|
|
6061
6033
|
initialBounds: options.initialBounds,
|
|
6062
6034
|
isAspectRatioLocked: options.isAspectRatioLocked,
|
|
6063
|
-
initialPageTransform: options.initialPageTransform
|
|
6035
|
+
initialPageTransform: options.initialPageTransform,
|
|
6036
|
+
dragHandle: options.dragHandle,
|
|
6037
|
+
mode: options.mode,
|
|
6038
|
+
// this is one frame of the same resize, not a new one, so don't fire start/end again
|
|
6039
|
+
skipStartAndEndCallbacks: options.skipStartAndEndCallbacks
|
|
6064
6040
|
});
|
|
6065
6041
|
if (Math.sign(scale.x) * Math.sign(scale.y) < 0) {
|
|
6066
6042
|
const parentRotation = this.getShapeParentTransform(id).rotation();
|
|
6067
|
-
const
|
|
6043
|
+
const parentDelta = (0, import_utils2.shortAngleDist)(
|
|
6044
|
+
import_Mat.Mat.Cast(options.initialPageTransform).rotation() - options.initialShape.rotation,
|
|
6045
|
+
parentRotation
|
|
6046
|
+
);
|
|
6047
|
+
const initialParentRotation = parentRotation - parentDelta;
|
|
6048
|
+
const rotation = 2 * options.scaleAxisRotation - options.initialShape.rotation - 2 * initialParentRotation - parentDelta;
|
|
6068
6049
|
this.updateShapes([{ id, type, rotation }]);
|
|
6069
6050
|
}
|
|
6070
6051
|
const preScaleShapePageCenter = import_Mat.Mat.applyToPoint(
|
|
@@ -6303,12 +6284,17 @@ class Editor extends import_eventemitter3.default {
|
|
|
6303
6284
|
let remaining = duration;
|
|
6304
6285
|
let t;
|
|
6305
6286
|
const animations = [];
|
|
6287
|
+
const ignoreShapeLock = this._shouldIgnoreShapeLock;
|
|
6306
6288
|
let partial, result;
|
|
6307
6289
|
for (let i = 0, n = partials.length; i < n; i++) {
|
|
6308
6290
|
partial = partials[i];
|
|
6309
6291
|
if (!partial) continue;
|
|
6310
6292
|
const shape = this.getShape(partial.id);
|
|
6311
6293
|
if (!shape) continue;
|
|
6294
|
+
const unlocks = shape.isLocked && Object.hasOwn(partial, "isLocked") && !partial.isLocked;
|
|
6295
|
+
if (!ignoreShapeLock && !unlocks && this.isShapeOrAncestorLocked(shape)) {
|
|
6296
|
+
continue;
|
|
6297
|
+
}
|
|
6312
6298
|
result = {
|
|
6313
6299
|
start: (0, import_utils.structuredClone)(shape),
|
|
6314
6300
|
end: applyPartialToRecordWithProps((0, import_utils.structuredClone)(shape), partial)
|
|
@@ -6324,7 +6310,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
6324
6310
|
(p) => p && animatingShapes2.get(p.id) === animationId
|
|
6325
6311
|
);
|
|
6326
6312
|
if (partialsToUpdate.length) {
|
|
6327
|
-
this.updateShapes(partialsToUpdate);
|
|
6313
|
+
this.run(() => this.updateShapes(partialsToUpdate), { ignoreShapeLock });
|
|
6328
6314
|
}
|
|
6329
6315
|
this.off("tick", handleTick);
|
|
6330
6316
|
return;
|
|
@@ -6357,13 +6343,13 @@ class Editor extends import_eventemitter3.default {
|
|
|
6357
6343
|
throw Error("Editor.groupShapes: must provide an array of shapes or shape ids");
|
|
6358
6344
|
}
|
|
6359
6345
|
if (this.getIsReadonly()) return this;
|
|
6360
|
-
const ids =
|
|
6361
|
-
if (ids.length <= 1) return this;
|
|
6346
|
+
const ids = toShapeIds(shapes);
|
|
6362
6347
|
const shapesToGroup = (0, import_utils.compact)(
|
|
6363
6348
|
(this._shouldIgnoreShapeLock ? ids : this._getUnlockedShapeIds(ids)).map(
|
|
6364
6349
|
(id) => this.getShape(id)
|
|
6365
6350
|
)
|
|
6366
6351
|
);
|
|
6352
|
+
if (shapesToGroup.length <= 1) return this;
|
|
6367
6353
|
const sortedShapeIds = shapesToGroup.sort(import_utils.sortByIndex).map((s) => s.id);
|
|
6368
6354
|
const childBounds = (0, import_utils.compact)(shapesToGroup.map((shape) => this.getShapePageBounds(shape)));
|
|
6369
6355
|
const pageBounds = import_Box.Box.Common(childBounds);
|
|
@@ -6372,8 +6358,11 @@ class Editor extends import_eventemitter3.default {
|
|
|
6372
6358
|
}
|
|
6373
6359
|
const { x, y } = pageBounds.point;
|
|
6374
6360
|
const parentId = this.findCommonAncestor(shapesToGroup) ?? this.getCurrentPageId();
|
|
6375
|
-
if (this.
|
|
6376
|
-
|
|
6361
|
+
if (!this.canCreateShapes([groupId])) {
|
|
6362
|
+
alertMaxShapes(this);
|
|
6363
|
+
return this;
|
|
6364
|
+
}
|
|
6365
|
+
if (this.isIn("select") && !this.isIn("select.idle")) {
|
|
6377
6366
|
this.cancel();
|
|
6378
6367
|
}
|
|
6379
6368
|
const shapesWithRootParent = shapesToGroup.filter((shape) => shape.parentId === parentId).sort(import_utils.sortByIndex);
|
|
@@ -6401,15 +6390,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
6401
6390
|
ungroupShapes(shapes, opts = {}) {
|
|
6402
6391
|
if (this.getIsReadonly()) return this;
|
|
6403
6392
|
const { select = true } = opts;
|
|
6404
|
-
const ids =
|
|
6393
|
+
const ids = toShapeIds(shapes);
|
|
6405
6394
|
const shapesToUngroup = (0, import_utils.compact)(
|
|
6406
6395
|
(this._shouldIgnoreShapeLock ? ids : this._getUnlockedShapeIds(ids)).map(
|
|
6407
6396
|
(id) => this.getShape(id)
|
|
6408
6397
|
)
|
|
6409
6398
|
);
|
|
6410
6399
|
if (shapesToUngroup.length === 0) return this;
|
|
6411
|
-
if (this.
|
|
6412
|
-
if (!this.isIn("select.idle")) {
|
|
6400
|
+
if (this.isIn("select") && !this.isIn("select.idle")) {
|
|
6413
6401
|
this.cancel();
|
|
6414
6402
|
}
|
|
6415
6403
|
const idsToSelect = /* @__PURE__ */ new Set();
|
|
@@ -6423,16 +6411,16 @@ class Editor extends import_eventemitter3.default {
|
|
|
6423
6411
|
});
|
|
6424
6412
|
if (groups.length === 0) return this;
|
|
6425
6413
|
this.run(() => {
|
|
6426
|
-
let group;
|
|
6427
6414
|
for (let i = 0, n = groups.length; i < n; i++) {
|
|
6428
|
-
group = groups[i];
|
|
6415
|
+
const group = this.getShape(groups[i].id);
|
|
6416
|
+
if (!group) continue;
|
|
6429
6417
|
const childIds = this.getSortedChildIdsForParent(group.id);
|
|
6430
6418
|
for (let j = 0, n2 = childIds.length; j < n2; j++) {
|
|
6431
6419
|
idsToSelect.add(childIds[j]);
|
|
6432
6420
|
}
|
|
6433
6421
|
this.reparentShapes(childIds, group.parentId, group.index);
|
|
6434
6422
|
}
|
|
6435
|
-
this.deleteShapes(groups.map((
|
|
6423
|
+
this.deleteShapes(groups.map((group) => group.id));
|
|
6436
6424
|
if (select) {
|
|
6437
6425
|
this.select(...idsToSelect);
|
|
6438
6426
|
}
|
|
@@ -6513,14 +6501,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
6513
6501
|
}
|
|
6514
6502
|
/** @internal */
|
|
6515
6503
|
_getUnlockedShapeIds(ids) {
|
|
6516
|
-
return ids.filter((id) => !this.
|
|
6504
|
+
return ids.filter((id) => !this.isShapeOrAncestorLocked(id));
|
|
6517
6505
|
}
|
|
6518
6506
|
deleteShapes(_ids) {
|
|
6519
6507
|
if (this.getIsReadonly()) return this;
|
|
6520
6508
|
if (!Array.isArray(_ids)) {
|
|
6521
6509
|
throw Error("Editor.deleteShapes: must provide an array of shapes or shapeIds");
|
|
6522
6510
|
}
|
|
6523
|
-
const shapeIds =
|
|
6511
|
+
const shapeIds = toShapeIds(_ids);
|
|
6524
6512
|
const shapeIdsToDelete = this._shouldIgnoreShapeLock ? shapeIds : this._getUnlockedShapeIds(shapeIds);
|
|
6525
6513
|
if (shapeIdsToDelete.length === 0) return this;
|
|
6526
6514
|
const allShapeIdsToDelete = new Set(shapeIdsToDelete);
|
|
@@ -6865,7 +6853,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
6865
6853
|
* @public
|
|
6866
6854
|
*/
|
|
6867
6855
|
getContentFromCurrentPage(shapes) {
|
|
6868
|
-
const ids =
|
|
6856
|
+
const ids = toShapeIds(shapes);
|
|
6869
6857
|
if (!ids) return;
|
|
6870
6858
|
if (ids.length === 0) return;
|
|
6871
6859
|
const shapeIds = this.getShapeAndDescendantIds(ids);
|
|
@@ -6933,21 +6921,29 @@ class Editor extends import_eventemitter3.default {
|
|
|
6933
6921
|
await Promise.allSettled(
|
|
6934
6922
|
content.assets.map(async (asset) => {
|
|
6935
6923
|
if ((asset.type === "image" || asset.type === "video") && !asset.props.src?.startsWith("data:image") && !asset.props.src?.startsWith("data:video") && !asset.props.src?.startsWith("http")) {
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6924
|
+
try {
|
|
6925
|
+
const objectUrl = await this.store.props.assets.resolve(asset, {
|
|
6926
|
+
screenScale: 1,
|
|
6927
|
+
steppedScreenScale: 1,
|
|
6928
|
+
dpr: 1,
|
|
6929
|
+
networkEffectiveType: null,
|
|
6930
|
+
shouldResolveToOriginal: true
|
|
6931
|
+
});
|
|
6932
|
+
if (objectUrl) {
|
|
6933
|
+
const response = await (0, import_utils.fetch)(objectUrl);
|
|
6934
|
+
if (response.ok) {
|
|
6935
|
+
const assetWithDataUrl = (0, import_utils.structuredClone)(asset);
|
|
6936
|
+
assetWithDataUrl.props.src = await import_utils.FileHelpers.blobToDataUrl(await response.blob());
|
|
6937
|
+
assets.push(assetWithDataUrl);
|
|
6938
|
+
return;
|
|
6939
|
+
}
|
|
6940
|
+
console.warn(`Could not inline asset ${asset.id}: fetch returned ${response.status}`);
|
|
6941
|
+
}
|
|
6942
|
+
} catch (err) {
|
|
6943
|
+
console.warn(`Could not inline asset ${asset.id}`, err);
|
|
6944
|
+
}
|
|
6950
6945
|
}
|
|
6946
|
+
assets.push(asset);
|
|
6951
6947
|
})
|
|
6952
6948
|
);
|
|
6953
6949
|
content.assets = assets;
|
|
@@ -7241,7 +7237,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
7241
7237
|
* @public
|
|
7242
7238
|
*/
|
|
7243
7239
|
async getSvgElement(shapes, opts = {}) {
|
|
7244
|
-
const ids = shapes.length === 0 ? this.getCurrentPageShapeIdsSorted() :
|
|
7240
|
+
const ids = shapes.length === 0 ? this.getCurrentPageShapeIdsSorted() : toShapeIds(shapes);
|
|
7245
7241
|
if (ids.length === 0) return void 0;
|
|
7246
7242
|
await this.fonts.loadRequiredFontsForCurrentPage(this.options.maxFontsToLoadBeforeRender);
|
|
7247
7243
|
return (0, import_exportToSvg.exportToSvg)(this, ids, opts);
|
|
@@ -7837,22 +7833,22 @@ class Editor extends import_eventemitter3.default {
|
|
|
7837
7833
|
const releaseCtrl = this._ctrlKeyTimeout !== -1;
|
|
7838
7834
|
const releaseMeta = this._metaKeyTimeout !== -1;
|
|
7839
7835
|
if (releaseShift) {
|
|
7840
|
-
clearTimeout(this._shiftKeyTimeout);
|
|
7836
|
+
this.timers.clearTimeout(this._shiftKeyTimeout);
|
|
7841
7837
|
this._shiftKeyTimeout = -1;
|
|
7842
7838
|
this.inputs.setShiftKey(false);
|
|
7843
7839
|
}
|
|
7844
7840
|
if (releaseAlt) {
|
|
7845
|
-
clearTimeout(this._altKeyTimeout);
|
|
7841
|
+
this.timers.clearTimeout(this._altKeyTimeout);
|
|
7846
7842
|
this._altKeyTimeout = -1;
|
|
7847
7843
|
this.inputs.setAltKey(false);
|
|
7848
7844
|
}
|
|
7849
7845
|
if (releaseCtrl) {
|
|
7850
|
-
clearTimeout(this._ctrlKeyTimeout);
|
|
7846
|
+
this.timers.clearTimeout(this._ctrlKeyTimeout);
|
|
7851
7847
|
this._ctrlKeyTimeout = -1;
|
|
7852
7848
|
this.inputs.setCtrlKey(false);
|
|
7853
7849
|
}
|
|
7854
7850
|
if (releaseMeta) {
|
|
7855
|
-
clearTimeout(this._metaKeyTimeout);
|
|
7851
|
+
this.timers.clearTimeout(this._metaKeyTimeout);
|
|
7856
7852
|
this._metaKeyTimeout = -1;
|
|
7857
7853
|
this.inputs.setMetaKey(false);
|
|
7858
7854
|
}
|
|
@@ -7966,28 +7962,28 @@ class Editor extends import_eventemitter3.default {
|
|
|
7966
7962
|
return;
|
|
7967
7963
|
}
|
|
7968
7964
|
if (info.shiftKey) {
|
|
7969
|
-
clearTimeout(this._shiftKeyTimeout);
|
|
7965
|
+
this.timers.clearTimeout(this._shiftKeyTimeout);
|
|
7970
7966
|
this._shiftKeyTimeout = -1;
|
|
7971
7967
|
inputs.setShiftKey(true);
|
|
7972
7968
|
} else if (!info.shiftKey && inputs.getShiftKey() && this._shiftKeyTimeout === -1) {
|
|
7973
7969
|
this._shiftKeyTimeout = this.timers.setTimeout(this._releaseShiftKey, 150);
|
|
7974
7970
|
}
|
|
7975
7971
|
if (info.altKey) {
|
|
7976
|
-
clearTimeout(this._altKeyTimeout);
|
|
7972
|
+
this.timers.clearTimeout(this._altKeyTimeout);
|
|
7977
7973
|
this._altKeyTimeout = -1;
|
|
7978
7974
|
inputs.setAltKey(true);
|
|
7979
7975
|
} else if (!info.altKey && inputs.getAltKey() && this._altKeyTimeout === -1) {
|
|
7980
7976
|
this._altKeyTimeout = this.timers.setTimeout(this._releaseAltKey, 150);
|
|
7981
7977
|
}
|
|
7982
7978
|
if (info.ctrlKey) {
|
|
7983
|
-
clearTimeout(this._ctrlKeyTimeout);
|
|
7979
|
+
this.timers.clearTimeout(this._ctrlKeyTimeout);
|
|
7984
7980
|
this._ctrlKeyTimeout = -1;
|
|
7985
7981
|
inputs.setCtrlKey(true);
|
|
7986
7982
|
} else if (!info.ctrlKey && inputs.getCtrlKey() && this._ctrlKeyTimeout === -1) {
|
|
7987
7983
|
this._ctrlKeyTimeout = this.timers.setTimeout(this._releaseCtrlKey, 150);
|
|
7988
7984
|
}
|
|
7989
7985
|
if (info.metaKey && info.name !== "key_up") {
|
|
7990
|
-
clearTimeout(this._metaKeyTimeout);
|
|
7986
|
+
this.timers.clearTimeout(this._metaKeyTimeout);
|
|
7991
7987
|
this._metaKeyTimeout = -1;
|
|
7992
7988
|
inputs.setMetaKey(true);
|
|
7993
7989
|
} else if (!info.metaKey && inputs.getMetaKey() && this._metaKeyTimeout === -1) {
|
|
@@ -8001,8 +7997,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
8001
7997
|
const cameraOptions = this._cameraOptions.__unsafe__getWithoutCapture();
|
|
8002
7998
|
switch (type) {
|
|
8003
7999
|
case "pinch": {
|
|
8004
|
-
|
|
8005
|
-
clearTimeout(this._longPressTimeout);
|
|
8000
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8006
8001
|
this.inputs.updateFromEvent(info);
|
|
8007
8002
|
switch (info.name) {
|
|
8008
8003
|
case "pinch_start": {
|
|
@@ -8023,6 +8018,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
8023
8018
|
}
|
|
8024
8019
|
case "pinch": {
|
|
8025
8020
|
if (!inputs.getIsPinching()) return;
|
|
8021
|
+
if (cameraOptions.isLocked) return;
|
|
8026
8022
|
const {
|
|
8027
8023
|
point: { z = 1 },
|
|
8028
8024
|
delta: { x: dx, y: dy }
|
|
@@ -8078,7 +8074,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
8078
8074
|
const { panSpeed, zoomSpeed } = cameraOptions;
|
|
8079
8075
|
let wheelBehavior = cameraOptions.wheelBehavior;
|
|
8080
8076
|
const inputMode = this.user.getUserPreferences().inputMode;
|
|
8081
|
-
if (inputMode !== null) {
|
|
8077
|
+
if (inputMode !== null && wheelBehavior !== "none") {
|
|
8082
8078
|
wheelBehavior = inputMode === "trackpad" ? "pan" : "zoom";
|
|
8083
8079
|
}
|
|
8084
8080
|
if (wheelBehavior !== "none") {
|
|
@@ -8130,12 +8126,12 @@ class Editor extends import_eventemitter3.default {
|
|
|
8130
8126
|
}
|
|
8131
8127
|
case "pointer": {
|
|
8132
8128
|
if (inputs.getIsPinching()) return;
|
|
8133
|
-
this.inputs.updateFromEvent(info);
|
|
8134
8129
|
const { isPen } = info;
|
|
8135
8130
|
const { isPenMode } = instanceState;
|
|
8131
|
+
if (isPenMode && !isPen) return;
|
|
8132
|
+
this.inputs.updateFromEvent(info);
|
|
8136
8133
|
switch (info.name) {
|
|
8137
8134
|
case "pointer_down": {
|
|
8138
|
-
if (isPenMode && !isPen) return;
|
|
8139
8135
|
this._releaseDebouncedModifiers();
|
|
8140
8136
|
if (!this.inputs.getIsPanning()) {
|
|
8141
8137
|
this._longPressTimeout = this.timers.setTimeout(() => {
|
|
@@ -8159,11 +8155,12 @@ class Editor extends import_eventemitter3.default {
|
|
|
8159
8155
|
inputs.buttons.add(info.button);
|
|
8160
8156
|
inputs.setIsPointing(true);
|
|
8161
8157
|
inputs.setIsDragging(false);
|
|
8158
|
+
this.stopCameraAnimation();
|
|
8162
8159
|
if (!isPenMode && info.isPenDirect) {
|
|
8163
8160
|
this.updateInstanceState({ isPenMode: true });
|
|
8164
8161
|
this.interrupt();
|
|
8165
8162
|
}
|
|
8166
|
-
if (info.button === import_constants.STYLUS_ERASER_BUTTON) {
|
|
8163
|
+
if (info.button === import_constants.STYLUS_ERASER_BUTTON && this.getStateDescendant("eraser")) {
|
|
8167
8164
|
this._restoreToolId = this.getCurrentToolId();
|
|
8168
8165
|
this.complete();
|
|
8169
8166
|
this.setCurrentTool("eraser");
|
|
@@ -8172,10 +8169,10 @@ class Editor extends import_eventemitter3.default {
|
|
|
8172
8169
|
this._prevCursor = this.getInstanceState().cursor.type;
|
|
8173
8170
|
}
|
|
8174
8171
|
this.inputs.setIsPanning(true);
|
|
8175
|
-
clearTimeout(this._longPressTimeout);
|
|
8172
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8176
8173
|
} else if (info.button === import_constants.RIGHT_MOUSE_BUTTON && this.options.rightClickPanning) {
|
|
8177
8174
|
this.inputs.setIsRightPointing(true);
|
|
8178
|
-
clearTimeout(this._longPressTimeout);
|
|
8175
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8179
8176
|
return this;
|
|
8180
8177
|
}
|
|
8181
8178
|
if (this.inputs.getIsPanning()) {
|
|
@@ -8186,7 +8183,6 @@ class Editor extends import_eventemitter3.default {
|
|
|
8186
8183
|
break;
|
|
8187
8184
|
}
|
|
8188
8185
|
case "pointer_move": {
|
|
8189
|
-
if (!isPen && isPenMode) return;
|
|
8190
8186
|
const { x: cx, y: cy, z: cz } = (0, import_state.unsafe__withoutCapture)(() => this.getCamera());
|
|
8191
8187
|
if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
|
|
8192
8188
|
const currentScreenPoint = this.inputs.getCurrentScreenPoint();
|
|
@@ -8217,16 +8213,15 @@ class Editor extends import_eventemitter3.default {
|
|
|
8217
8213
|
}
|
|
8218
8214
|
if (inputs.getIsPointing() && !inputs.getIsDragging() && import_Vec.Vec.Dist2(inputs.getOriginPagePoint(), inputs.getCurrentPagePoint()) * this.getZoomLevel() > (instanceState.isCoarsePointer ? this.options.coarseDragDistanceSquared : this.options.dragDistanceSquared) / cz) {
|
|
8219
8215
|
inputs.setIsDragging(true);
|
|
8220
|
-
clearTimeout(this._longPressTimeout);
|
|
8216
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8221
8217
|
}
|
|
8222
8218
|
break;
|
|
8223
8219
|
}
|
|
8224
8220
|
case "pointer_up": {
|
|
8225
8221
|
inputs.setIsDragging(false);
|
|
8226
8222
|
inputs.setIsPointing(false);
|
|
8227
|
-
clearTimeout(this._longPressTimeout);
|
|
8223
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8228
8224
|
inputs.buttons.delete(info.button);
|
|
8229
|
-
if (instanceState.isPenMode && !isPen) return;
|
|
8230
8225
|
if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
|
|
8231
8226
|
this.inputs.setIsRightPointing(false);
|
|
8232
8227
|
this._selectedShapeIdsAtPointerDown = [];
|
|
@@ -8282,7 +8277,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
8282
8277
|
});
|
|
8283
8278
|
}
|
|
8284
8279
|
} else {
|
|
8285
|
-
if (info.button === import_constants.STYLUS_ERASER_BUTTON) {
|
|
8280
|
+
if (info.button === import_constants.STYLUS_ERASER_BUTTON && this.getStateDescendant("eraser")) {
|
|
8286
8281
|
this.complete();
|
|
8287
8282
|
this.setCurrentTool(this._restoreToolId);
|
|
8288
8283
|
}
|
|
@@ -8295,8 +8290,8 @@ class Editor extends import_eventemitter3.default {
|
|
|
8295
8290
|
break;
|
|
8296
8291
|
}
|
|
8297
8292
|
case "keyboard": {
|
|
8298
|
-
if (info.
|
|
8299
|
-
if (info.
|
|
8293
|
+
if (info.code === "ShiftRight") info.code = "ShiftLeft";
|
|
8294
|
+
if (info.code === "AltRight") info.code = "AltLeft";
|
|
8300
8295
|
if (info.code === "ControlRight") info.code = "ControlLeft";
|
|
8301
8296
|
if (info.code === "MetaRight") info.code = "MetaLeft";
|
|
8302
8297
|
switch (info.name) {
|
|
@@ -8309,7 +8304,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
8309
8304
|
}
|
|
8310
8305
|
this.inputs.setIsPanning(true);
|
|
8311
8306
|
this.inputs.setIsSpacebarPanning(true);
|
|
8312
|
-
clearTimeout(this._longPressTimeout);
|
|
8307
|
+
this.timers.clearTimeout(this._longPressTimeout);
|
|
8313
8308
|
this.setCursor({
|
|
8314
8309
|
type: this.inputs.getIsPointing() ? "grabbing" : "grab",
|
|
8315
8310
|
rotation: 0
|
|
@@ -8335,7 +8330,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
8335
8330
|
break;
|
|
8336
8331
|
}
|
|
8337
8332
|
}
|
|
8338
|
-
if (offset) {
|
|
8333
|
+
if (offset && !cameraOptions.isLocked) {
|
|
8339
8334
|
const bounds = this.getViewportPageBounds();
|
|
8340
8335
|
const next = bounds.clone().translate(offset.mulV({ x: bounds.w, y: bounds.h }));
|
|
8341
8336
|
this._animateToViewport(next, { animation: { duration: 320 } });
|
|
@@ -8375,7 +8370,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
8375
8370
|
this.setCurrentTool("select");
|
|
8376
8371
|
}
|
|
8377
8372
|
const { isPenMode } = this.store.unsafeGetWithoutCapture(import_tlschema.TLINSTANCE_ID);
|
|
8378
|
-
if (info.isPen
|
|
8373
|
+
if (!isPenMode || info.isPen) {
|
|
8379
8374
|
const clickInfo = this._clickManager.handlePointerEvent(info);
|
|
8380
8375
|
if (info.name !== clickInfo.name) {
|
|
8381
8376
|
this.root.handleEvent(info);
|
|
@@ -8397,7 +8392,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
8397
8392
|
maybeTrackPerformance(name) {
|
|
8398
8393
|
if (import_debug_flags.debugFlags.measurePerformance.get()) {
|
|
8399
8394
|
if (this.performanceTracker.isStarted()) {
|
|
8400
|
-
clearTimeout(this.performanceTrackerTimeout);
|
|
8395
|
+
this.timers.clearTimeout(this.performanceTrackerTimeout);
|
|
8401
8396
|
} else {
|
|
8402
8397
|
this.performanceTracker.start(name);
|
|
8403
8398
|
}
|
|
@@ -8666,6 +8661,9 @@ function pushShapeWithDescendants(editor, id, result) {
|
|
|
8666
8661
|
pushShapeWithDescendants(editor, childIds[i], result);
|
|
8667
8662
|
}
|
|
8668
8663
|
}
|
|
8664
|
+
function toShapeIds(shapes) {
|
|
8665
|
+
return typeof shapes[0] === "string" ? shapes : shapes.map((shape) => shape.id);
|
|
8666
|
+
}
|
|
8669
8667
|
function withIsolatedShapes(editor, shapeIds, callback) {
|
|
8670
8668
|
let result;
|
|
8671
8669
|
editor.run(
|
|
@@ -8688,7 +8686,7 @@ function withIsolatedShapes(editor, shapeIds, callback) {
|
|
|
8688
8686
|
}
|
|
8689
8687
|
}
|
|
8690
8688
|
}
|
|
8691
|
-
editor.
|
|
8689
|
+
editor._deleteBindings([...bindingsToRemove], { isolateShapes: true });
|
|
8692
8690
|
try {
|
|
8693
8691
|
result = import_utils.Result.ok(callback(bindingsWithBoth));
|
|
8694
8692
|
} catch (error) {
|