@tldraw/editor 5.4.2 → 5.5.0-canary.0241f11f2e99
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 +7 -2
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/constants.js +2 -0
- package/dist-cjs/lib/constants.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +131 -151
- 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/EdgeScrollManager/EdgeScrollManager.js +10 -6
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +7 -3
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.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/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/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/primitives/geometry/Arc2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Edge2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Group2d.js +8 -5
- package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Point2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
- package/dist-cjs/lib/utils/sync/LocalIndexedDb.js +13 -17
- package/dist-cjs/lib/utils/sync/LocalIndexedDb.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +78 -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 +7 -2
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/constants.mjs +2 -0
- package/dist-esm/lib/constants.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +132 -151
- 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/EdgeScrollManager/EdgeScrollManager.mjs +10 -6
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +7 -3
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.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/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/primitives/geometry/Arc2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +12 -6
- package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Point2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs +13 -17
- package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +78 -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/package.json +7 -7
- package/src/lib/constants.ts +8 -0
- package/src/lib/editor/Editor.test.ts +20 -0
- package/src/lib/editor/Editor.ts +202 -255
- package/src/lib/editor/derivations/bindingsIndex.ts +3 -0
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +35 -4
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +13 -7
- package/src/lib/editor/managers/ThemeManager/ThemeManager.test.ts +53 -0
- package/src/lib/editor/managers/ThemeManager/ThemeManager.ts +9 -3
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +23 -8
- 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/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/primitives/geometry/Arc2d.test.ts +9 -0
- package/src/lib/primitives/geometry/Arc2d.ts +1 -1
- package/src/lib/primitives/geometry/CubicBezier2d.test.ts +13 -0
- package/src/lib/primitives/geometry/CubicBezier2d.ts +1 -1
- package/src/lib/primitives/geometry/Edge2d.test.ts +21 -3
- package/src/lib/primitives/geometry/Edge2d.ts +1 -1
- package/src/lib/primitives/geometry/Group2d.test.ts +26 -5
- package/src/lib/primitives/geometry/Group2d.ts +18 -7
- package/src/lib/primitives/geometry/Point2d.test.ts +14 -3
- package/src/lib/primitives/geometry/Point2d.ts +1 -1
- package/src/lib/utils/sync/LocalIndexedDb.test.ts +28 -0
- package/src/lib/utils/sync/LocalIndexedDb.ts +18 -20
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +236 -0
- package/src/lib/utils/sync/TLLocalSyncClient.ts +106 -54
- package/src/version.ts +3 -3
|
@@ -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 }]);
|
|
@@ -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,14 +1615,18 @@ 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
|
-
const
|
|
1628
|
+
const startIndex = currentIndex === -1 && direction === "prev" ? 0 : currentIndex;
|
|
1629
|
+
const adjacentIndex = (startIndex + (direction === "next" ? 1 : -1) + shapeIds.length) % shapeIds.length;
|
|
1621
1630
|
adjacentShapeId = shapeIds[adjacentIndex];
|
|
1622
1631
|
} else {
|
|
1623
1632
|
if (!currentShapeId) return;
|
|
@@ -1716,13 +1725,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
1716
1725
|
});
|
|
1717
1726
|
if (shapesInDirection.length === 0) return currentShapeId;
|
|
1718
1727
|
const lowestScoringShape = (0, import_utils.minBy)(shapesInDirection, ({ center }) => {
|
|
1719
|
-
const distance = import_Vec.Vec.
|
|
1728
|
+
const distance = import_Vec.Vec.Dist(currentCenter, center);
|
|
1720
1729
|
const dirProp = ["left", "right"].includes(direction) ? "x" : "y";
|
|
1721
1730
|
const directionalDistance = Math.abs(center[dirProp] - currentCenter[dirProp]);
|
|
1722
1731
|
const offProp = ["left", "right"].includes(direction) ? "y" : "x";
|
|
1723
1732
|
const offAxisDeviation = Math.abs(center[offProp] - currentCenter[offProp]);
|
|
1724
|
-
const angle =
|
|
1725
|
-
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);
|
|
1726
1736
|
return distance * 1 + // Base distance
|
|
1727
1737
|
offAxisDeviation * 2 + // Heavy penalty for off-axis deviation
|
|
1728
1738
|
(distance - directionalDistance) * 1.5 + // Penalty for diagonal distance
|
|
@@ -2060,7 +2070,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2060
2070
|
* @public
|
|
2061
2071
|
*/
|
|
2062
2072
|
setHintingShapes(shapes) {
|
|
2063
|
-
const ids =
|
|
2073
|
+
const ids = toShapeIds(shapes);
|
|
2064
2074
|
this.run(
|
|
2065
2075
|
() => {
|
|
2066
2076
|
this._updateCurrentPageState({ hintingShapeIds: (0, import_utils.dedupe)(ids) });
|
|
@@ -2090,7 +2100,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2090
2100
|
* @public
|
|
2091
2101
|
*/
|
|
2092
2102
|
setErasingShapes(shapes) {
|
|
2093
|
-
const ids =
|
|
2103
|
+
const ids = toShapeIds(shapes).slice();
|
|
2094
2104
|
ids.sort();
|
|
2095
2105
|
const erasingShapeIds = this.getErasingShapeIds();
|
|
2096
2106
|
this.run(
|
|
@@ -2497,14 +2507,16 @@ class Editor extends import_eventemitter3.default {
|
|
|
2497
2507
|
setCamera(point, opts) {
|
|
2498
2508
|
const { isLocked } = this._cameraOptions.__unsafe__getWithoutCapture();
|
|
2499
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
|
+
}
|
|
2500
2516
|
this.stopCameraAnimation();
|
|
2501
2517
|
if (this.getInstanceState().followingUserId) {
|
|
2502
2518
|
this.stopFollowingUser();
|
|
2503
2519
|
}
|
|
2504
|
-
const _point = import_Vec.Vec.Cast(point);
|
|
2505
|
-
if (!Number.isFinite(_point.x)) _point.x = 0;
|
|
2506
|
-
if (!Number.isFinite(_point.y)) _point.y = 0;
|
|
2507
|
-
if (_point.z === void 0 || !Number.isFinite(_point.z)) point.z = this.getZoomLevel();
|
|
2508
2520
|
const camera = this.getConstrainedCamera(_point, opts);
|
|
2509
2521
|
if (opts?.animation) {
|
|
2510
2522
|
const { width, height } = this.getViewportScreenBounds();
|
|
@@ -2883,7 +2895,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2883
2895
|
newCx += center.x / newCz - center.x / cz;
|
|
2884
2896
|
newCy += center.y / newCz - center.y / cz;
|
|
2885
2897
|
}
|
|
2886
|
-
currentSpeed *= 1 - friction;
|
|
2898
|
+
currentSpeed *= (1 - friction) ** (elapsed / import_constants.FRAME_MS_60HZ);
|
|
2887
2899
|
if (currentSpeed < speedThreshold) {
|
|
2888
2900
|
cancel();
|
|
2889
2901
|
} else {
|
|
@@ -2917,6 +2929,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
2917
2929
|
}
|
|
2918
2930
|
const isOnSamePage = presence.currentPageId === this.getCurrentPageId();
|
|
2919
2931
|
if (!isOnSamePage) {
|
|
2932
|
+
this.markHistoryStoppingPoint("change-page");
|
|
2920
2933
|
this.setCurrentPage(presence.currentPageId);
|
|
2921
2934
|
}
|
|
2922
2935
|
if (opts && opts.animation && !isOnSamePage) {
|
|
@@ -3748,7 +3761,9 @@ class Editor extends import_eventemitter3.default {
|
|
|
3748
3761
|
if (ids.length <= 0) return this;
|
|
3749
3762
|
this.run(
|
|
3750
3763
|
() => {
|
|
3751
|
-
this.store.props.assets.remove?.(ids)
|
|
3764
|
+
Promise.resolve(this.store.props.assets.remove?.(ids)).catch(
|
|
3765
|
+
(err) => console.error("Error while removing assets from the asset store:", err)
|
|
3766
|
+
);
|
|
3752
3767
|
this.store.remove(ids);
|
|
3753
3768
|
},
|
|
3754
3769
|
{ history: "ignore" }
|
|
@@ -4130,7 +4145,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4130
4145
|
if (shapes.length === 0) {
|
|
4131
4146
|
return;
|
|
4132
4147
|
}
|
|
4133
|
-
const ids =
|
|
4148
|
+
const ids = toShapeIds(shapes);
|
|
4134
4149
|
const freshShapes = (0, import_utils.compact)(ids.map((id) => this.getShape(id)));
|
|
4135
4150
|
if (freshShapes.length === 1) {
|
|
4136
4151
|
const parentId = freshShapes[0].parentId;
|
|
@@ -4633,7 +4648,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4633
4648
|
* @public
|
|
4634
4649
|
*/
|
|
4635
4650
|
reparentShapes(shapes, parentId, insertIndex) {
|
|
4636
|
-
const ids =
|
|
4651
|
+
const ids = toShapeIds(shapes);
|
|
4637
4652
|
if (ids.length === 0) return this;
|
|
4638
4653
|
const changes = [];
|
|
4639
4654
|
const parentTransform = (0, import_tlschema.isPageId)(parentId) ? import_Mat.Mat.Identity() : this.getShapePageTransform(parentId);
|
|
@@ -4862,6 +4877,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4862
4877
|
* binding, but the `type`, `toId`, and `fromId` must all be provided.
|
|
4863
4878
|
*/
|
|
4864
4879
|
createBindings(partials) {
|
|
4880
|
+
if (this.getIsReadonly()) return this;
|
|
4865
4881
|
const bindings = [];
|
|
4866
4882
|
for (const partial of partials) {
|
|
4867
4883
|
const fromShape = this.getShape(partial.fromId);
|
|
@@ -4896,6 +4912,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4896
4912
|
* binding is skipped. The changes from the partial are merged into the existing record.
|
|
4897
4913
|
*/
|
|
4898
4914
|
updateBindings(partials) {
|
|
4915
|
+
if (this.getIsReadonly()) return this;
|
|
4899
4916
|
const updated = [];
|
|
4900
4917
|
for (const partial of partials) {
|
|
4901
4918
|
if (!partial) continue;
|
|
@@ -4924,6 +4941,16 @@ class Editor extends import_eventemitter3.default {
|
|
|
4924
4941
|
* Delete several bindings by their IDs. If a binding ID doesn't exist, it's ignored.
|
|
4925
4942
|
*/
|
|
4926
4943
|
deleteBindings(bindings, { isolateShapes = false } = {}) {
|
|
4944
|
+
if (this.getIsReadonly()) return this;
|
|
4945
|
+
return this._deleteBindings(bindings, { isolateShapes });
|
|
4946
|
+
}
|
|
4947
|
+
/**
|
|
4948
|
+
* Unguarded so that withIsolatedShapes can transiently isolate shapes for copy and export in
|
|
4949
|
+
* readonly mode; the public deleteBindings is what readonly blocks.
|
|
4950
|
+
*
|
|
4951
|
+
* @internal
|
|
4952
|
+
*/
|
|
4953
|
+
_deleteBindings(bindings, { isolateShapes = false } = {}) {
|
|
4927
4954
|
const ids = bindings.map((binding) => typeof binding === "string" ? binding : binding.id);
|
|
4928
4955
|
if (isolateShapes) {
|
|
4929
4956
|
this.store.atomic(() => {
|
|
@@ -4982,7 +5009,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
4982
5009
|
* @param opts - The options for the rotation.
|
|
4983
5010
|
*/
|
|
4984
5011
|
rotateShapesBy(shapes, delta, opts) {
|
|
4985
|
-
const ids =
|
|
5012
|
+
const ids = toShapeIds(shapes);
|
|
4986
5013
|
if (ids.length <= 0) return this;
|
|
4987
5014
|
const snapshot = (0, import_rotation.getRotationSnapshot)({ editor: this, ids });
|
|
4988
5015
|
if (!snapshot) return this;
|
|
@@ -5019,6 +5046,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
5019
5046
|
}
|
|
5020
5047
|
return workingShape;
|
|
5021
5048
|
}
|
|
5049
|
+
// Counter-rotates the page-space delta into the parent's space; without that a child of a rotated
|
|
5050
|
+
// frame or group would move along its parent's axes instead of the page's.
|
|
5051
|
+
// todo: a shape laid out together with its own parent moves twice, once with the parent and once
|
|
5052
|
+
// on its own; the layout commands should skip shapes whose ancestors are also being laid out
|
|
5053
|
+
getChangesToTranslateShapeByPageDelta(shape, pageDelta) {
|
|
5054
|
+
const localDelta = import_Vec.Vec.From(pageDelta).rot(-this.getShapeParentTransform(shape).rotation());
|
|
5055
|
+
return this.getChangesToTranslateShape(shape, localDelta.add(shape));
|
|
5056
|
+
}
|
|
5022
5057
|
/**
|
|
5023
5058
|
* Move shapes by a delta.
|
|
5024
5059
|
*
|
|
@@ -5031,14 +5066,12 @@ class Editor extends import_eventemitter3.default {
|
|
|
5031
5066
|
* @param offset - The offset to apply to the shapes.
|
|
5032
5067
|
*/
|
|
5033
5068
|
nudgeShapes(shapes, offset) {
|
|
5034
|
-
const ids =
|
|
5069
|
+
const ids = toShapeIds(shapes);
|
|
5035
5070
|
if (ids.length <= 0) return this;
|
|
5036
5071
|
const changes = [];
|
|
5037
5072
|
for (const id of ids) {
|
|
5038
5073
|
const shape = this.getShape(id);
|
|
5039
|
-
|
|
5040
|
-
localDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5041
|
-
changes.push(this.getChangesToTranslateShape(shape, localDelta.add(shape)));
|
|
5074
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, offset));
|
|
5042
5075
|
}
|
|
5043
5076
|
this.updateShapes(changes);
|
|
5044
5077
|
return this;
|
|
@@ -5059,7 +5092,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5059
5092
|
*/
|
|
5060
5093
|
duplicateShapes(shapes, offset) {
|
|
5061
5094
|
this.run(() => {
|
|
5062
|
-
const _ids =
|
|
5095
|
+
const _ids = toShapeIds(shapes);
|
|
5063
5096
|
const ids = this._shouldIgnoreShapeLock ? _ids : this._getUnlockedShapeIds(_ids);
|
|
5064
5097
|
if (ids.length <= 0) return this;
|
|
5065
5098
|
const initialIds = new Set(ids);
|
|
@@ -5168,7 +5201,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5168
5201
|
* @public
|
|
5169
5202
|
*/
|
|
5170
5203
|
moveShapesToPage(shapes, pageId) {
|
|
5171
|
-
const ids =
|
|
5204
|
+
const ids = toShapeIds(shapes);
|
|
5172
5205
|
if (ids.length === 0) return this;
|
|
5173
5206
|
if (this.getIsReadonly()) return this;
|
|
5174
5207
|
const currentPageId = this.getCurrentPageId();
|
|
@@ -5204,7 +5237,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5204
5237
|
* @public
|
|
5205
5238
|
*/
|
|
5206
5239
|
toggleLock(shapes) {
|
|
5207
|
-
const ids =
|
|
5240
|
+
const ids = toShapeIds(shapes);
|
|
5208
5241
|
if (this.getIsReadonly() || ids.length === 0) return this;
|
|
5209
5242
|
let allLocked = true;
|
|
5210
5243
|
const shapesToToggle = [];
|
|
@@ -5243,7 +5276,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5243
5276
|
* @public
|
|
5244
5277
|
*/
|
|
5245
5278
|
sendToBack(shapes) {
|
|
5246
|
-
const ids =
|
|
5279
|
+
const ids = toShapeIds(shapes);
|
|
5247
5280
|
const changes = (0, import_reorderShapes.getReorderingShapesChanges)(this, "toBack", ids, {
|
|
5248
5281
|
considerAllShapes: true
|
|
5249
5282
|
});
|
|
@@ -5273,7 +5306,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5273
5306
|
* @public
|
|
5274
5307
|
*/
|
|
5275
5308
|
sendBackward(shapes, opts = {}) {
|
|
5276
|
-
const ids =
|
|
5309
|
+
const ids = toShapeIds(shapes);
|
|
5277
5310
|
const changes = (0, import_reorderShapes.getReorderingShapesChanges)(this, "backward", ids, opts);
|
|
5278
5311
|
if (changes) this.updateShapes(changes);
|
|
5279
5312
|
return this;
|
|
@@ -5301,7 +5334,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5301
5334
|
* @public
|
|
5302
5335
|
*/
|
|
5303
5336
|
bringForward(shapes, opts = {}) {
|
|
5304
|
-
const ids =
|
|
5337
|
+
const ids = toShapeIds(shapes);
|
|
5305
5338
|
const changes = (0, import_reorderShapes.getReorderingShapesChanges)(this, "forward", ids, opts);
|
|
5306
5339
|
if (changes) this.updateShapes(changes);
|
|
5307
5340
|
return this;
|
|
@@ -5320,7 +5353,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5320
5353
|
* @public
|
|
5321
5354
|
*/
|
|
5322
5355
|
bringToFront(shapes) {
|
|
5323
|
-
const ids =
|
|
5356
|
+
const ids = toShapeIds(shapes);
|
|
5324
5357
|
const changes = (0, import_reorderShapes.getReorderingShapesChanges)(this, "toFront", ids);
|
|
5325
5358
|
if (changes) this.updateShapes(changes);
|
|
5326
5359
|
return this;
|
|
@@ -5332,7 +5365,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5332
5365
|
* @internal
|
|
5333
5366
|
*/
|
|
5334
5367
|
getShapeClusters(shapes, type, opts) {
|
|
5335
|
-
const ids =
|
|
5368
|
+
const ids = toShapeIds(shapes);
|
|
5336
5369
|
let freshShapes = (0, import_utils.compact)(ids.map((id) => this.getShape(id)));
|
|
5337
5370
|
if (opts?.filterAxisAligned) {
|
|
5338
5371
|
freshShapes = freshShapes.filter((s) => {
|
|
@@ -5357,7 +5390,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5357
5390
|
const shapesMovingTogether = [shape];
|
|
5358
5391
|
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
5359
5392
|
this.collectShapesViaArrowBindings({
|
|
5360
|
-
bindings: this.
|
|
5393
|
+
bindings: this.getBindingsInvolvingShape(shape.id, "arrow"),
|
|
5361
5394
|
initialShapes: freshShapes,
|
|
5362
5395
|
resultShapes: shapesMovingTogether,
|
|
5363
5396
|
resultBounds: boundsOfShapesMovingTogether,
|
|
@@ -5413,7 +5446,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5413
5446
|
*/
|
|
5414
5447
|
flipShapes(shapes, operation) {
|
|
5415
5448
|
if (this.getIsReadonly()) return this;
|
|
5416
|
-
const ids =
|
|
5449
|
+
const ids = toShapeIds(shapes);
|
|
5417
5450
|
const shapesToFlipFirstPass = (0, import_utils.compact)(ids.map((id) => this.getShape(id)));
|
|
5418
5451
|
for (const shape of shapesToFlipFirstPass) {
|
|
5419
5452
|
if (this.isShapeOfType(shape, "group")) {
|
|
@@ -5487,21 +5520,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5487
5520
|
const { clusters: shapeClustersToStack } = this.getShapeClusters(shapes, "stack");
|
|
5488
5521
|
const len = shapeClustersToStack.length;
|
|
5489
5522
|
if (_gap === 0 && len < 3 || len < 2) return this;
|
|
5490
|
-
|
|
5491
|
-
let min;
|
|
5492
|
-
let max;
|
|
5493
|
-
let dim;
|
|
5494
|
-
if (operation === "horizontal") {
|
|
5495
|
-
val = "x";
|
|
5496
|
-
min = "minX";
|
|
5497
|
-
max = "maxX";
|
|
5498
|
-
dim = "width";
|
|
5499
|
-
} else {
|
|
5500
|
-
val = "y";
|
|
5501
|
-
min = "minY";
|
|
5502
|
-
max = "maxY";
|
|
5503
|
-
dim = "height";
|
|
5504
|
-
}
|
|
5523
|
+
const { val, min, max, dim } = AXIS[operation];
|
|
5505
5524
|
let shapeGap = 0;
|
|
5506
5525
|
shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
|
|
5507
5526
|
if (_gap === 0) {
|
|
@@ -5540,13 +5559,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5540
5559
|
const delta = new import_Vec.Vec();
|
|
5541
5560
|
delta[val] = v + shapeGap - pageBounds[val];
|
|
5542
5561
|
for (const shape of shapes2) {
|
|
5543
|
-
|
|
5544
|
-
const parent = this.getShapeParent(shape);
|
|
5545
|
-
if (parent) {
|
|
5546
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5547
|
-
}
|
|
5548
|
-
shapeDelta.add(shape);
|
|
5549
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5562
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5550
5563
|
}
|
|
5551
5564
|
v += pageBounds[dim] + shapeGap;
|
|
5552
5565
|
}
|
|
@@ -5626,13 +5639,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5626
5639
|
for (const { shapes: shapes2, pageBounds, nextPageBounds } of shapeClustersToPack) {
|
|
5627
5640
|
const delta = import_Vec.Vec.Sub(nextPageBounds.point, pageBounds.point).add(centerDelta);
|
|
5628
5641
|
for (const shape of shapes2) {
|
|
5629
|
-
|
|
5630
|
-
const parent = this.getShapeParent(shape);
|
|
5631
|
-
if (parent) {
|
|
5632
|
-
shapeDelta.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5633
|
-
}
|
|
5634
|
-
shapeDelta.add(shape);
|
|
5635
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5642
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5636
5643
|
}
|
|
5637
5644
|
}
|
|
5638
5645
|
if (changes.length) {
|
|
@@ -5692,13 +5699,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5692
5699
|
}
|
|
5693
5700
|
}
|
|
5694
5701
|
for (const shape of shapes2) {
|
|
5695
|
-
|
|
5696
|
-
const parent = this.getShapeParent(shape);
|
|
5697
|
-
if (parent) {
|
|
5698
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5699
|
-
}
|
|
5700
|
-
shapeDelta.add(shape);
|
|
5701
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5702
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5702
5703
|
}
|
|
5703
5704
|
});
|
|
5704
5705
|
this.updateShapes(changes);
|
|
@@ -5722,27 +5723,13 @@ class Editor extends import_eventemitter3.default {
|
|
|
5722
5723
|
if (this.getIsReadonly()) return this;
|
|
5723
5724
|
const { clusters: shapeClustersToDistribute } = this.getShapeClusters(shapes, "distribute");
|
|
5724
5725
|
if (shapeClustersToDistribute.length < 3) return this;
|
|
5725
|
-
|
|
5726
|
-
let min;
|
|
5727
|
-
let max;
|
|
5728
|
-
let dim;
|
|
5729
|
-
if (operation === "horizontal") {
|
|
5730
|
-
val = "x";
|
|
5731
|
-
min = "minX";
|
|
5732
|
-
max = "maxX";
|
|
5733
|
-
dim = "width";
|
|
5734
|
-
} else {
|
|
5735
|
-
val = "y";
|
|
5736
|
-
min = "minY";
|
|
5737
|
-
max = "maxY";
|
|
5738
|
-
dim = "height";
|
|
5739
|
-
}
|
|
5726
|
+
const { val, min, max, dim } = AXIS[operation];
|
|
5740
5727
|
const changes = [];
|
|
5741
5728
|
const first = shapeClustersToDistribute.sort((a, b) => a.pageBounds[min] - b.pageBounds[min])[0];
|
|
5742
5729
|
const last2 = shapeClustersToDistribute.sort((a, b) => b.pageBounds[max] - a.pageBounds[max])[0];
|
|
5743
5730
|
if (first === last2) {
|
|
5744
5731
|
const excludedShapeIds = new Set(first.shapes.map((s) => s.id));
|
|
5745
|
-
const ids =
|
|
5732
|
+
const ids = toShapeIds(shapes);
|
|
5746
5733
|
return this.distributeShapes(
|
|
5747
5734
|
ids.filter((id) => !excludedShapeIds.has(id)),
|
|
5748
5735
|
operation
|
|
@@ -5766,13 +5753,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5766
5753
|
delta[val] = last2.pageBounds[max] - pageBounds[max] - 1;
|
|
5767
5754
|
}
|
|
5768
5755
|
for (const shape of shapes2) {
|
|
5769
|
-
|
|
5770
|
-
const parent = this.getShapeParent(shape);
|
|
5771
|
-
if (parent) {
|
|
5772
|
-
shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
|
|
5773
|
-
}
|
|
5774
|
-
shapeDelta.add(shape);
|
|
5775
|
-
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5756
|
+
changes.push(this.getChangesToTranslateShapeByPageDelta(shape, delta));
|
|
5776
5757
|
}
|
|
5777
5758
|
v += pageBounds[dim] + gap;
|
|
5778
5759
|
}
|
|
@@ -5802,32 +5783,17 @@ class Editor extends import_eventemitter3.default {
|
|
|
5802
5783
|
);
|
|
5803
5784
|
if (shapeClustersToStretch.length < 2) return this;
|
|
5804
5785
|
const commonBounds = import_Box.Box.Common(allBounds);
|
|
5805
|
-
|
|
5806
|
-
let min;
|
|
5807
|
-
let dim;
|
|
5808
|
-
if (operation === "horizontal") {
|
|
5809
|
-
val = "x";
|
|
5810
|
-
min = "minX";
|
|
5811
|
-
dim = "width";
|
|
5812
|
-
} else {
|
|
5813
|
-
val = "y";
|
|
5814
|
-
min = "minY";
|
|
5815
|
-
dim = "height";
|
|
5816
|
-
}
|
|
5786
|
+
const { val, min, dim } = AXIS[operation];
|
|
5817
5787
|
this.run(() => {
|
|
5818
5788
|
shapeClustersToStretch.forEach(({ shapes: shapes2, pageBounds }) => {
|
|
5819
|
-
const
|
|
5820
|
-
|
|
5789
|
+
const pageOffset = new import_Vec.Vec();
|
|
5790
|
+
pageOffset[val] = commonBounds[min] - pageBounds[min];
|
|
5821
5791
|
const scaleOrigin = pageBounds.center.clone();
|
|
5822
5792
|
scaleOrigin[val] = commonBounds[min];
|
|
5823
5793
|
const scale = new import_Vec.Vec(1, 1);
|
|
5824
5794
|
scale[val] = commonBounds[dim] / pageBounds[dim];
|
|
5825
5795
|
for (const shape of shapes2) {
|
|
5826
|
-
|
|
5827
|
-
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5828
|
-
shapeLocalOffset.add(shape);
|
|
5829
|
-
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5830
|
-
this.updateShape(changes);
|
|
5796
|
+
this.updateShape(this.getChangesToTranslateShapeByPageDelta(shape, pageOffset));
|
|
5831
5797
|
this.resizeShape(shape.id, scale, {
|
|
5832
5798
|
initialBounds: this.getShapeGeometry(shape).bounds,
|
|
5833
5799
|
scaleOrigin,
|
|
@@ -5870,7 +5836,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5870
5836
|
const scaleY = targetBounds.height / commonBounds.height;
|
|
5871
5837
|
const scale = new import_Vec.Vec(scaleX, scaleY);
|
|
5872
5838
|
shapeClusters.forEach(({ shapes: shapes2, pageBounds }) => {
|
|
5873
|
-
const
|
|
5839
|
+
const pageOffset = new import_Vec.Vec(
|
|
5874
5840
|
targetBounds.minX - commonBounds.minX + (pageBounds.minX - commonBounds.minX) * (scaleX - 1),
|
|
5875
5841
|
targetBounds.minY - commonBounds.minY + (pageBounds.minY - commonBounds.minY) * (scaleY - 1)
|
|
5876
5842
|
);
|
|
@@ -5879,11 +5845,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
5879
5845
|
targetBounds.minY + (pageBounds.minY - commonBounds.minY) * scaleY
|
|
5880
5846
|
);
|
|
5881
5847
|
for (const shape of shapes2) {
|
|
5882
|
-
|
|
5883
|
-
shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
|
|
5884
|
-
shapeLocalOffset.add(shape);
|
|
5885
|
-
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5886
|
-
this.updateShape(changes);
|
|
5848
|
+
this.updateShape(this.getChangesToTranslateShapeByPageDelta(shape, pageOffset));
|
|
5887
5849
|
this.resizeShape(shape.id, scale, {
|
|
5888
5850
|
initialBounds: this.getShapeGeometry(shape).bounds,
|
|
5889
5851
|
scaleOrigin,
|
|
@@ -6302,12 +6264,17 @@ class Editor extends import_eventemitter3.default {
|
|
|
6302
6264
|
let remaining = duration;
|
|
6303
6265
|
let t;
|
|
6304
6266
|
const animations = [];
|
|
6267
|
+
const ignoreShapeLock = this._shouldIgnoreShapeLock;
|
|
6305
6268
|
let partial, result;
|
|
6306
6269
|
for (let i = 0, n = partials.length; i < n; i++) {
|
|
6307
6270
|
partial = partials[i];
|
|
6308
6271
|
if (!partial) continue;
|
|
6309
6272
|
const shape = this.getShape(partial.id);
|
|
6310
6273
|
if (!shape) continue;
|
|
6274
|
+
const unlocks = shape.isLocked && Object.hasOwn(partial, "isLocked") && !partial.isLocked;
|
|
6275
|
+
if (!ignoreShapeLock && !unlocks && this.isShapeOrAncestorLocked(shape)) {
|
|
6276
|
+
continue;
|
|
6277
|
+
}
|
|
6311
6278
|
result = {
|
|
6312
6279
|
start: (0, import_utils.structuredClone)(shape),
|
|
6313
6280
|
end: applyPartialToRecordWithProps((0, import_utils.structuredClone)(shape), partial)
|
|
@@ -6323,7 +6290,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
6323
6290
|
(p) => p && animatingShapes2.get(p.id) === animationId
|
|
6324
6291
|
);
|
|
6325
6292
|
if (partialsToUpdate.length) {
|
|
6326
|
-
this.updateShapes(partialsToUpdate);
|
|
6293
|
+
this.run(() => this.updateShapes(partialsToUpdate), { ignoreShapeLock });
|
|
6327
6294
|
}
|
|
6328
6295
|
this.off("tick", handleTick);
|
|
6329
6296
|
return;
|
|
@@ -6356,13 +6323,13 @@ class Editor extends import_eventemitter3.default {
|
|
|
6356
6323
|
throw Error("Editor.groupShapes: must provide an array of shapes or shape ids");
|
|
6357
6324
|
}
|
|
6358
6325
|
if (this.getIsReadonly()) return this;
|
|
6359
|
-
const ids =
|
|
6360
|
-
if (ids.length <= 1) return this;
|
|
6326
|
+
const ids = toShapeIds(shapes);
|
|
6361
6327
|
const shapesToGroup = (0, import_utils.compact)(
|
|
6362
6328
|
(this._shouldIgnoreShapeLock ? ids : this._getUnlockedShapeIds(ids)).map(
|
|
6363
6329
|
(id) => this.getShape(id)
|
|
6364
6330
|
)
|
|
6365
6331
|
);
|
|
6332
|
+
if (shapesToGroup.length <= 1) return this;
|
|
6366
6333
|
const sortedShapeIds = shapesToGroup.sort(import_utils.sortByIndex).map((s) => s.id);
|
|
6367
6334
|
const childBounds = (0, import_utils.compact)(shapesToGroup.map((shape) => this.getShapePageBounds(shape)));
|
|
6368
6335
|
const pageBounds = import_Box.Box.Common(childBounds);
|
|
@@ -6371,8 +6338,11 @@ class Editor extends import_eventemitter3.default {
|
|
|
6371
6338
|
}
|
|
6372
6339
|
const { x, y } = pageBounds.point;
|
|
6373
6340
|
const parentId = this.findCommonAncestor(shapesToGroup) ?? this.getCurrentPageId();
|
|
6374
|
-
if (this.
|
|
6375
|
-
|
|
6341
|
+
if (!this.canCreateShapes([groupId])) {
|
|
6342
|
+
alertMaxShapes(this);
|
|
6343
|
+
return this;
|
|
6344
|
+
}
|
|
6345
|
+
if (this.isIn("select") && !this.isIn("select.idle")) {
|
|
6376
6346
|
this.cancel();
|
|
6377
6347
|
}
|
|
6378
6348
|
const shapesWithRootParent = shapesToGroup.filter((shape) => shape.parentId === parentId).sort(import_utils.sortByIndex);
|
|
@@ -6400,15 +6370,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
6400
6370
|
ungroupShapes(shapes, opts = {}) {
|
|
6401
6371
|
if (this.getIsReadonly()) return this;
|
|
6402
6372
|
const { select = true } = opts;
|
|
6403
|
-
const ids =
|
|
6373
|
+
const ids = toShapeIds(shapes);
|
|
6404
6374
|
const shapesToUngroup = (0, import_utils.compact)(
|
|
6405
6375
|
(this._shouldIgnoreShapeLock ? ids : this._getUnlockedShapeIds(ids)).map(
|
|
6406
6376
|
(id) => this.getShape(id)
|
|
6407
6377
|
)
|
|
6408
6378
|
);
|
|
6409
6379
|
if (shapesToUngroup.length === 0) return this;
|
|
6410
|
-
if (this.
|
|
6411
|
-
if (!this.isIn("select.idle")) {
|
|
6380
|
+
if (this.isIn("select") && !this.isIn("select.idle")) {
|
|
6412
6381
|
this.cancel();
|
|
6413
6382
|
}
|
|
6414
6383
|
const idsToSelect = /* @__PURE__ */ new Set();
|
|
@@ -6422,16 +6391,16 @@ class Editor extends import_eventemitter3.default {
|
|
|
6422
6391
|
});
|
|
6423
6392
|
if (groups.length === 0) return this;
|
|
6424
6393
|
this.run(() => {
|
|
6425
|
-
let group;
|
|
6426
6394
|
for (let i = 0, n = groups.length; i < n; i++) {
|
|
6427
|
-
group = groups[i];
|
|
6395
|
+
const group = this.getShape(groups[i].id);
|
|
6396
|
+
if (!group) continue;
|
|
6428
6397
|
const childIds = this.getSortedChildIdsForParent(group.id);
|
|
6429
6398
|
for (let j = 0, n2 = childIds.length; j < n2; j++) {
|
|
6430
6399
|
idsToSelect.add(childIds[j]);
|
|
6431
6400
|
}
|
|
6432
6401
|
this.reparentShapes(childIds, group.parentId, group.index);
|
|
6433
6402
|
}
|
|
6434
|
-
this.deleteShapes(groups.map((
|
|
6403
|
+
this.deleteShapes(groups.map((group) => group.id));
|
|
6435
6404
|
if (select) {
|
|
6436
6405
|
this.select(...idsToSelect);
|
|
6437
6406
|
}
|
|
@@ -6512,14 +6481,14 @@ class Editor extends import_eventemitter3.default {
|
|
|
6512
6481
|
}
|
|
6513
6482
|
/** @internal */
|
|
6514
6483
|
_getUnlockedShapeIds(ids) {
|
|
6515
|
-
return ids.filter((id) => !this.
|
|
6484
|
+
return ids.filter((id) => !this.isShapeOrAncestorLocked(id));
|
|
6516
6485
|
}
|
|
6517
6486
|
deleteShapes(_ids) {
|
|
6518
6487
|
if (this.getIsReadonly()) return this;
|
|
6519
6488
|
if (!Array.isArray(_ids)) {
|
|
6520
6489
|
throw Error("Editor.deleteShapes: must provide an array of shapes or shapeIds");
|
|
6521
6490
|
}
|
|
6522
|
-
const shapeIds =
|
|
6491
|
+
const shapeIds = toShapeIds(_ids);
|
|
6523
6492
|
const shapeIdsToDelete = this._shouldIgnoreShapeLock ? shapeIds : this._getUnlockedShapeIds(shapeIds);
|
|
6524
6493
|
if (shapeIdsToDelete.length === 0) return this;
|
|
6525
6494
|
const allShapeIdsToDelete = new Set(shapeIdsToDelete);
|
|
@@ -6864,7 +6833,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
6864
6833
|
* @public
|
|
6865
6834
|
*/
|
|
6866
6835
|
getContentFromCurrentPage(shapes) {
|
|
6867
|
-
const ids =
|
|
6836
|
+
const ids = toShapeIds(shapes);
|
|
6868
6837
|
if (!ids) return;
|
|
6869
6838
|
if (ids.length === 0) return;
|
|
6870
6839
|
const shapeIds = this.getShapeAndDescendantIds(ids);
|
|
@@ -6932,21 +6901,29 @@ class Editor extends import_eventemitter3.default {
|
|
|
6932
6901
|
await Promise.allSettled(
|
|
6933
6902
|
content.assets.map(async (asset) => {
|
|
6934
6903
|
if ((asset.type === "image" || asset.type === "video") && !asset.props.src?.startsWith("data:image") && !asset.props.src?.startsWith("data:video") && !asset.props.src?.startsWith("http")) {
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6904
|
+
try {
|
|
6905
|
+
const objectUrl = await this.store.props.assets.resolve(asset, {
|
|
6906
|
+
screenScale: 1,
|
|
6907
|
+
steppedScreenScale: 1,
|
|
6908
|
+
dpr: 1,
|
|
6909
|
+
networkEffectiveType: null,
|
|
6910
|
+
shouldResolveToOriginal: true
|
|
6911
|
+
});
|
|
6912
|
+
if (objectUrl) {
|
|
6913
|
+
const response = await (0, import_utils.fetch)(objectUrl);
|
|
6914
|
+
if (response.ok) {
|
|
6915
|
+
const assetWithDataUrl = (0, import_utils.structuredClone)(asset);
|
|
6916
|
+
assetWithDataUrl.props.src = await import_utils.FileHelpers.blobToDataUrl(await response.blob());
|
|
6917
|
+
assets.push(assetWithDataUrl);
|
|
6918
|
+
return;
|
|
6919
|
+
}
|
|
6920
|
+
console.warn(`Could not inline asset ${asset.id}: fetch returned ${response.status}`);
|
|
6921
|
+
}
|
|
6922
|
+
} catch (err) {
|
|
6923
|
+
console.warn(`Could not inline asset ${asset.id}`, err);
|
|
6924
|
+
}
|
|
6949
6925
|
}
|
|
6926
|
+
assets.push(asset);
|
|
6950
6927
|
})
|
|
6951
6928
|
);
|
|
6952
6929
|
content.assets = assets;
|
|
@@ -7240,7 +7217,7 @@ class Editor extends import_eventemitter3.default {
|
|
|
7240
7217
|
* @public
|
|
7241
7218
|
*/
|
|
7242
7219
|
async getSvgElement(shapes, opts = {}) {
|
|
7243
|
-
const ids = shapes.length === 0 ? this.getCurrentPageShapeIdsSorted() :
|
|
7220
|
+
const ids = shapes.length === 0 ? this.getCurrentPageShapeIdsSorted() : toShapeIds(shapes);
|
|
7244
7221
|
if (ids.length === 0) return void 0;
|
|
7245
7222
|
await this.fonts.loadRequiredFontsForCurrentPage(this.options.maxFontsToLoadBeforeRender);
|
|
7246
7223
|
return (0, import_exportToSvg.exportToSvg)(this, ids, opts);
|
|
@@ -8294,8 +8271,8 @@ class Editor extends import_eventemitter3.default {
|
|
|
8294
8271
|
break;
|
|
8295
8272
|
}
|
|
8296
8273
|
case "keyboard": {
|
|
8297
|
-
if (info.
|
|
8298
|
-
if (info.
|
|
8274
|
+
if (info.code === "ShiftRight") info.code = "ShiftLeft";
|
|
8275
|
+
if (info.code === "AltRight") info.code = "AltLeft";
|
|
8299
8276
|
if (info.code === "ControlRight") info.code = "ControlLeft";
|
|
8300
8277
|
if (info.code === "MetaRight") info.code = "MetaLeft";
|
|
8301
8278
|
switch (info.name) {
|
|
@@ -8665,6 +8642,9 @@ function pushShapeWithDescendants(editor, id, result) {
|
|
|
8665
8642
|
pushShapeWithDescendants(editor, childIds[i], result);
|
|
8666
8643
|
}
|
|
8667
8644
|
}
|
|
8645
|
+
function toShapeIds(shapes) {
|
|
8646
|
+
return typeof shapes[0] === "string" ? shapes : shapes.map((shape) => shape.id);
|
|
8647
|
+
}
|
|
8668
8648
|
function withIsolatedShapes(editor, shapeIds, callback) {
|
|
8669
8649
|
let result;
|
|
8670
8650
|
editor.run(
|
|
@@ -8687,7 +8667,7 @@ function withIsolatedShapes(editor, shapeIds, callback) {
|
|
|
8687
8667
|
}
|
|
8688
8668
|
}
|
|
8689
8669
|
}
|
|
8690
|
-
editor.
|
|
8670
|
+
editor._deleteBindings([...bindingsToRemove], { isolateShapes: true });
|
|
8691
8671
|
try {
|
|
8692
8672
|
result = import_utils.Result.ok(callback(bindingsWithBoth));
|
|
8693
8673
|
} catch (error) {
|