@tldraw/editor 3.9.0-internal.7f0e15f4f7d9 → 3.10.0-canary.075415a2bbc8
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/CHANGELOG.md +90 -0
- package/README.md +2 -2
- package/dist-cjs/index.d.ts +54 -9
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +2 -3
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/LiveCollaborators.js +5 -0
- package/dist-cjs/lib/components/LiveCollaborators.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +430 -248
- package/dist-cjs/lib/editor/Editor.js.map +3 -3
- package/dist-cjs/lib/editor/managers/FontManager.js +25 -26
- package/dist-cjs/lib/editor/managers/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +7 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/exports/StyleEmbedder.js +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js.map +1 -1
- package/dist-cjs/lib/hooks/usePresence.js.map +1 -1
- package/dist-cjs/lib/license/Watermark.js +1 -1
- package/dist-cjs/lib/license/Watermark.js.map +1 -1
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js +5 -0
- package/dist-cjs/lib/utils/browserCanvasMaxSize.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 +54 -9
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +2 -3
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/LiveCollaborators.mjs +5 -0
- package/dist-esm/lib/components/LiveCollaborators.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +431 -249
- package/dist-esm/lib/editor/Editor.mjs.map +3 -3
- package/dist-esm/lib/editor/managers/FontManager.mjs +26 -27
- package/dist-esm/lib/editor/managers/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +7 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -1
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +1 -1
- package/dist-esm/lib/hooks/usePresence.mjs.map +1 -1
- package/dist-esm/lib/license/Watermark.mjs +1 -1
- package/dist-esm/lib/license/Watermark.mjs.map +1 -1
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs +5 -0
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +4 -0
- package/package.json +7 -7
- package/src/index.ts +2 -0
- package/src/lib/TldrawEditor.tsx +3 -3
- package/src/lib/components/LiveCollaborators.tsx +5 -0
- package/src/lib/components/default-components/DefaultBrush.tsx +1 -0
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -0
- package/src/lib/components/default-components/DefaultCursor.tsx +1 -0
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +5 -3
- package/src/lib/components/default-components/DefaultScribble.tsx +1 -0
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +1 -0
- package/src/lib/editor/Editor.ts +560 -277
- package/src/lib/editor/managers/FontManager.ts +26 -27
- package/src/lib/editor/shapes/ShapeUtil.ts +32 -5
- package/src/lib/exports/StyleEmbedder.ts +1 -1
- package/src/lib/exports/getSvgJsx.tsx +1 -0
- package/src/lib/hooks/usePeerIds.ts +1 -1
- package/src/lib/hooks/usePresence.ts +2 -2
- package/src/lib/license/Watermark.tsx +1 -1
- package/src/lib/utils/browserCanvasMaxSize.ts +5 -3
- package/src/version.ts +3 -3
|
@@ -46,7 +46,7 @@ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use
|
|
|
46
46
|
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
47
47
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
48
48
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
49
|
-
var __setMetaKeyTimeout_dec, __setCtrlKeyTimeout_dec, __setAltKeyTimeout_dec, __setShiftKeyTimeout_dec, _getIsReadonly_dec, _getIsFocused_dec, _getSharedOpacity_dec, _getSharedStyles_dec, __getSelectionSharedStyles_dec, __getBindingsIndexCache_dec, _getCurrentPageRenderingShapesSorted_dec, _getCurrentPageShapesSorted_dec, _getCurrentPageShapes_dec, _getCurrentPageBounds_dec, _getCulledShapes_dec, __notVisibleShapes_dec, __getShapeMaskedPageBoundsCache_dec, __getShapeMaskCache_dec, __getShapeClipPathCache_dec, __getShapePageBoundsCache_dec, __getShapePageTransformCache_dec, __getShapeHandlesCache_dec,
|
|
49
|
+
var __setMetaKeyTimeout_dec, __setCtrlKeyTimeout_dec, __setAltKeyTimeout_dec, __setShiftKeyTimeout_dec, _getIsReadonly_dec, _getIsFocused_dec, _getSharedOpacity_dec, _getSharedStyles_dec, __getSelectionSharedStyles_dec, __getBindingsIndexCache_dec, _getCurrentPageRenderingShapesSorted_dec, _getCurrentPageShapesSorted_dec, _getCurrentPageShapes_dec, _getCurrentPageBounds_dec, _getCulledShapes_dec, __notVisibleShapes_dec, __getShapeMaskedPageBoundsCache_dec, __getShapeMaskCache_dec, __getShapeClipPathCache_dec, __getShapePageBoundsCache_dec, __getShapePageTransformCache_dec, __getShapeHandlesCache_dec, __getAllAssetsQuery_dec, _getCurrentPageShapeIdsSorted_dec, _getCurrentPageId_dec, _getPages_dec, __getAllPagesQuery_dec, _getRenderingShapes_dec, _getCollaboratorsOnCurrentPage_dec, _getCollaborators_dec, __getCollaboratorsQuery_dec, _getViewportPageBounds_dec, _getViewportScreenCenter_dec, _getViewportScreenBounds_dec, _getZoomLevel_dec, _getCameraForFollowing_dec, _getViewportPageBoundsForFollowing_dec, _getCamera_dec, __unsafe_getCameraId_dec, _getErasingShapes_dec, _getErasingShapeIds_dec, _getHintingShape_dec, _getHintingShapeIds_dec, _getHoveredShape_dec, _getHoveredShapeId_dec, _getRichTextEditor_dec, _getEditingShape_dec, _getEditingShapeId_dec, _getFocusedGroup_dec, _getFocusedGroupId_dec, _getSelectionRotatedScreenBounds_dec, _getSelectionRotatedPageBounds_dec, _getSelectionRotation_dec, _getSelectionPageBounds_dec, _getOnlySelectedShape_dec, _getOnlySelectedShapeId_dec, _getSelectedShapes_dec, _getSelectedShapeIds_dec, __getCurrentPageStateId_dec, _getCurrentPageState_dec, __getPageStatesQuery_dec, _getPageStates_dec, _getIsMenuOpen_dec, _getOpenMenus_dec, _getInstanceState_dec, _getDocumentSettings_dec, _getCurrentToolId_dec, _getCurrentTool_dec, _getPath_dec, _getCanRedo_dec, _getCanUndo_dec, _getIsShapeHiddenCache_dec, _a, _init;
|
|
50
50
|
import {
|
|
51
51
|
EMPTY_ARRAY,
|
|
52
52
|
atom,
|
|
@@ -129,7 +129,7 @@ import { Vec } from "../primitives/Vec.mjs";
|
|
|
129
129
|
import { EASINGS } from "../primitives/easings.mjs";
|
|
130
130
|
import { Group2d } from "../primitives/geometry/Group2d.mjs";
|
|
131
131
|
import { intersectPolygonPolygon } from "../primitives/intersect.mjs";
|
|
132
|
-
import {
|
|
132
|
+
import { PI, approximately, areAnglesCompatible, clamp, pointInPolygon } from "../primitives/utils.mjs";
|
|
133
133
|
import { SharedStyleMap } from "../utils/SharedStylesMap.mjs";
|
|
134
134
|
import { dataUrlToFile } from "../utils/assets.mjs";
|
|
135
135
|
import { debugFlags } from "../utils/debug-flags.mjs";
|
|
@@ -156,7 +156,7 @@ import { TextManager } from "./managers/TextManager.mjs";
|
|
|
156
156
|
import { TickManager } from "./managers/TickManager.mjs";
|
|
157
157
|
import { UserPreferencesManager } from "./managers/UserPreferencesManager.mjs";
|
|
158
158
|
import { RootState } from "./tools/RootState.mjs";
|
|
159
|
-
class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed], _getCanUndo_dec = [computed], _getCanRedo_dec = [computed], _getPath_dec = [computed], _getCurrentTool_dec = [computed], _getCurrentToolId_dec = [computed], _getDocumentSettings_dec = [computed], _getInstanceState_dec = [computed], _getOpenMenus_dec = [computed], _getIsMenuOpen_dec = [computed], _getPageStates_dec = [computed], __getPageStatesQuery_dec = [computed], _getCurrentPageState_dec = [computed], __getCurrentPageStateId_dec = [computed], _getSelectedShapeIds_dec = [computed], _getSelectedShapes_dec = [computed], _getOnlySelectedShapeId_dec = [computed], _getOnlySelectedShape_dec = [computed], _getSelectionPageBounds_dec = [computed], _getSelectionRotation_dec = [computed], _getSelectionRotatedPageBounds_dec = [computed], _getSelectionRotatedScreenBounds_dec = [computed], _getFocusedGroupId_dec = [computed], _getFocusedGroup_dec = [computed], _getEditingShapeId_dec = [computed], _getEditingShape_dec = [computed], _getRichTextEditor_dec = [computed], _getHoveredShapeId_dec = [computed], _getHoveredShape_dec = [computed], _getHintingShapeIds_dec = [computed], _getHintingShape_dec = [computed], _getErasingShapeIds_dec = [computed], _getErasingShapes_dec = [computed], __unsafe_getCameraId_dec = [computed], _getCamera_dec = [computed], _getViewportPageBoundsForFollowing_dec = [computed], _getCameraForFollowing_dec = [computed], _getZoomLevel_dec = [computed], _getViewportScreenBounds_dec = [computed], _getViewportScreenCenter_dec = [computed], _getViewportPageBounds_dec = [computed], __getCollaboratorsQuery_dec = [computed], _getCollaborators_dec = [computed], _getCollaboratorsOnCurrentPage_dec = [computed], _getRenderingShapes_dec = [computed], __getAllPagesQuery_dec = [computed], _getPages_dec = [computed], _getCurrentPageId_dec = [computed], _getCurrentPageShapeIdsSorted_dec = [computed], __getAllAssetsQuery_dec = [computed],
|
|
159
|
+
class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed], _getCanUndo_dec = [computed], _getCanRedo_dec = [computed], _getPath_dec = [computed], _getCurrentTool_dec = [computed], _getCurrentToolId_dec = [computed], _getDocumentSettings_dec = [computed], _getInstanceState_dec = [computed], _getOpenMenus_dec = [computed], _getIsMenuOpen_dec = [computed], _getPageStates_dec = [computed], __getPageStatesQuery_dec = [computed], _getCurrentPageState_dec = [computed], __getCurrentPageStateId_dec = [computed], _getSelectedShapeIds_dec = [computed], _getSelectedShapes_dec = [computed], _getOnlySelectedShapeId_dec = [computed], _getOnlySelectedShape_dec = [computed], _getSelectionPageBounds_dec = [computed], _getSelectionRotation_dec = [computed], _getSelectionRotatedPageBounds_dec = [computed], _getSelectionRotatedScreenBounds_dec = [computed], _getFocusedGroupId_dec = [computed], _getFocusedGroup_dec = [computed], _getEditingShapeId_dec = [computed], _getEditingShape_dec = [computed], _getRichTextEditor_dec = [computed], _getHoveredShapeId_dec = [computed], _getHoveredShape_dec = [computed], _getHintingShapeIds_dec = [computed], _getHintingShape_dec = [computed], _getErasingShapeIds_dec = [computed], _getErasingShapes_dec = [computed], __unsafe_getCameraId_dec = [computed], _getCamera_dec = [computed], _getViewportPageBoundsForFollowing_dec = [computed], _getCameraForFollowing_dec = [computed], _getZoomLevel_dec = [computed], _getViewportScreenBounds_dec = [computed], _getViewportScreenCenter_dec = [computed], _getViewportPageBounds_dec = [computed], __getCollaboratorsQuery_dec = [computed], _getCollaborators_dec = [computed], _getCollaboratorsOnCurrentPage_dec = [computed], _getRenderingShapes_dec = [computed], __getAllPagesQuery_dec = [computed], _getPages_dec = [computed], _getCurrentPageId_dec = [computed], _getCurrentPageShapeIdsSorted_dec = [computed], __getAllAssetsQuery_dec = [computed], __getShapeHandlesCache_dec = [computed], __getShapePageTransformCache_dec = [computed], __getShapePageBoundsCache_dec = [computed], __getShapeClipPathCache_dec = [computed], __getShapeMaskCache_dec = [computed], __getShapeMaskedPageBoundsCache_dec = [computed], __notVisibleShapes_dec = [computed], _getCulledShapes_dec = [computed], _getCurrentPageBounds_dec = [computed], _getCurrentPageShapes_dec = [computed], _getCurrentPageShapesSorted_dec = [computed], _getCurrentPageRenderingShapesSorted_dec = [computed], __getBindingsIndexCache_dec = [computed], __getSelectionSharedStyles_dec = [computed], _getSharedStyles_dec = [computed({ isEqual: (a, b) => a.equals(b) })], _getSharedOpacity_dec = [computed], _getIsFocused_dec = [computed], _getIsReadonly_dec = [computed], __setShiftKeyTimeout_dec = [bind], __setAltKeyTimeout_dec = [bind], __setCtrlKeyTimeout_dec = [bind], __setMetaKeyTimeout_dec = [bind], _a) {
|
|
160
160
|
constructor({
|
|
161
161
|
store,
|
|
162
162
|
user,
|
|
@@ -175,6 +175,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
175
175
|
}) {
|
|
176
176
|
super();
|
|
177
177
|
__runInitializers(_init, 5, this);
|
|
178
|
+
__publicField(this, "id", uniqueId());
|
|
178
179
|
__publicField(this, "_isShapeHiddenPredicate");
|
|
179
180
|
__publicField(this, "options");
|
|
180
181
|
__publicField(this, "contextId", uniqueId());
|
|
@@ -329,6 +330,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
329
330
|
__publicField(this, "_cameraStateTimeoutRemaining", 0);
|
|
330
331
|
/* @internal */
|
|
331
332
|
__publicField(this, "_currentPageShapeIds");
|
|
333
|
+
/* --------------------- Shapes --------------------- */
|
|
334
|
+
__publicField(this, "_shapeGeometryCaches", {});
|
|
332
335
|
// Parents and children
|
|
333
336
|
/**
|
|
334
337
|
* A cache of parents to children.
|
|
@@ -3279,16 +3282,6 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
3279
3282
|
async uploadAsset(asset, file, abortSignal) {
|
|
3280
3283
|
return await this.store.props.assets.upload(asset, file, abortSignal);
|
|
3281
3284
|
}
|
|
3282
|
-
_getShapeGeometryCache() {
|
|
3283
|
-
return this.store.createComputedCache(
|
|
3284
|
-
"bounds",
|
|
3285
|
-
(shape) => {
|
|
3286
|
-
this.fonts.trackFontsForShape(shape);
|
|
3287
|
-
return this.getShapeUtil(shape).getGeometry(shape);
|
|
3288
|
-
},
|
|
3289
|
-
{ areRecordsEqual: (a, b) => a.props === b.props }
|
|
3290
|
-
);
|
|
3291
|
-
}
|
|
3292
3285
|
/**
|
|
3293
3286
|
* Get the geometry of a shape.
|
|
3294
3287
|
*
|
|
@@ -3296,14 +3289,29 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
3296
3289
|
* ```ts
|
|
3297
3290
|
* editor.getShapeGeometry(myShape)
|
|
3298
3291
|
* editor.getShapeGeometry(myShapeId)
|
|
3292
|
+
* editor.getShapeGeometry(myShapeId, { context: "arrow" })
|
|
3299
3293
|
* ```
|
|
3300
3294
|
*
|
|
3301
3295
|
* @param shape - The shape (or shape id) to get the geometry for.
|
|
3296
|
+
* @param opts - Additional options about the request for geometry. Passed to {@link ShapeUtil.getGeometry}.
|
|
3302
3297
|
*
|
|
3303
3298
|
* @public
|
|
3304
3299
|
*/
|
|
3305
|
-
getShapeGeometry(shape) {
|
|
3306
|
-
|
|
3300
|
+
getShapeGeometry(shape, opts) {
|
|
3301
|
+
const context = opts?.context ?? "none";
|
|
3302
|
+
if (!this._shapeGeometryCaches[context]) {
|
|
3303
|
+
this._shapeGeometryCaches[context] = this.store.createComputedCache(
|
|
3304
|
+
"bounds",
|
|
3305
|
+
(shape2) => {
|
|
3306
|
+
this.fonts.trackFontsForShape(shape2);
|
|
3307
|
+
return this.getShapeUtil(shape2).getGeometry(shape2, opts);
|
|
3308
|
+
},
|
|
3309
|
+
{ areRecordsEqual: (a, b) => a.props === b.props }
|
|
3310
|
+
);
|
|
3311
|
+
}
|
|
3312
|
+
return this._shapeGeometryCaches[context].get(
|
|
3313
|
+
typeof shape === "string" ? shape : shape.id
|
|
3314
|
+
);
|
|
3307
3315
|
}
|
|
3308
3316
|
_getShapeHandlesCache() {
|
|
3309
3317
|
return this.store.createComputedCache("handles", (shape) => {
|
|
@@ -4034,7 +4042,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4034
4042
|
indices = sib ? getIndicesAbove(sib.index, ids.length) : getIndices(ids.length);
|
|
4035
4043
|
}
|
|
4036
4044
|
const invertedParentTransform = parentTransform.clone().invert();
|
|
4037
|
-
const shapesToReparent = compact(ids.map((id) => this.getShape(id)));
|
|
4045
|
+
const shapesToReparent = compact(ids.map((id) => this.getShape(id))).sort(sortByIndex);
|
|
4038
4046
|
this.run(
|
|
4039
4047
|
() => {
|
|
4040
4048
|
for (let i = 0; i < shapesToReparent.length; i++) {
|
|
@@ -4369,27 +4377,28 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4369
4377
|
});
|
|
4370
4378
|
return this;
|
|
4371
4379
|
}
|
|
4380
|
+
// Gets a shape partial that includes life cycle changes: on translate start, on translate, on translate end
|
|
4372
4381
|
getChangesToTranslateShape(initialShape, newShapeCoords) {
|
|
4373
4382
|
let workingShape = initialShape;
|
|
4374
4383
|
const util = this.getShapeUtil(initialShape);
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4384
|
+
const afterTranslateStart = util.onTranslateStart?.(workingShape);
|
|
4385
|
+
if (afterTranslateStart) {
|
|
4386
|
+
workingShape = applyPartialToRecordWithProps(workingShape, afterTranslateStart);
|
|
4387
|
+
}
|
|
4379
4388
|
workingShape = applyPartialToRecordWithProps(workingShape, {
|
|
4380
4389
|
id: initialShape.id,
|
|
4381
4390
|
type: initialShape.type,
|
|
4382
4391
|
x: newShapeCoords.x,
|
|
4383
4392
|
y: newShapeCoords.y
|
|
4384
4393
|
});
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4394
|
+
const afterTranslate = util.onTranslate?.(initialShape, workingShape);
|
|
4395
|
+
if (afterTranslate) {
|
|
4396
|
+
workingShape = applyPartialToRecordWithProps(workingShape, afterTranslate);
|
|
4397
|
+
}
|
|
4398
|
+
const afterTranslateEnd = util.onTranslateEnd?.(initialShape, workingShape);
|
|
4399
|
+
if (afterTranslateEnd) {
|
|
4400
|
+
workingShape = applyPartialToRecordWithProps(workingShape, afterTranslateEnd);
|
|
4401
|
+
}
|
|
4393
4402
|
return workingShape;
|
|
4394
4403
|
}
|
|
4395
4404
|
/**
|
|
@@ -4696,6 +4705,30 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4696
4705
|
if (changes) this.updateShapes(changes);
|
|
4697
4706
|
return this;
|
|
4698
4707
|
}
|
|
4708
|
+
/**
|
|
4709
|
+
* @internal
|
|
4710
|
+
*/
|
|
4711
|
+
collectShapesViaArrowBindings(info) {
|
|
4712
|
+
const { initialShapes, resultShapes, resultBounds, bindings, visited } = info;
|
|
4713
|
+
for (const binding of bindings) {
|
|
4714
|
+
for (const id of [binding.fromId, binding.toId]) {
|
|
4715
|
+
if (!visited.has(id)) {
|
|
4716
|
+
const aligningShape = initialShapes.find((s) => s.id === id);
|
|
4717
|
+
if (aligningShape && !visited.has(aligningShape.id)) {
|
|
4718
|
+
visited.add(aligningShape.id);
|
|
4719
|
+
const shapePageBounds = this.getShapePageBounds(aligningShape);
|
|
4720
|
+
if (!shapePageBounds) continue;
|
|
4721
|
+
resultShapes.push(aligningShape);
|
|
4722
|
+
resultBounds.push(shapePageBounds);
|
|
4723
|
+
this.collectShapesViaArrowBindings({
|
|
4724
|
+
...info,
|
|
4725
|
+
bindings: this.getBindingsInvolvingShape(aligningShape, "arrow")
|
|
4726
|
+
});
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4699
4732
|
/**
|
|
4700
4733
|
* Flip shape positions.
|
|
4701
4734
|
*
|
|
@@ -4711,35 +4744,52 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4711
4744
|
* @public
|
|
4712
4745
|
*/
|
|
4713
4746
|
flipShapes(shapes, operation) {
|
|
4714
|
-
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
4715
4747
|
if (this.getIsReadonly()) return this;
|
|
4716
|
-
|
|
4748
|
+
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
4749
|
+
const shapesToFlipFirstPass = compact(ids.map((id) => this.getShape(id)));
|
|
4750
|
+
for (const shape of shapesToFlipFirstPass) {
|
|
4751
|
+
if (this.isShapeOfType(shape, "group")) {
|
|
4752
|
+
const childrenOfGroups = compact(
|
|
4753
|
+
this.getSortedChildIdsForParent(shape.id).map((id) => this.getShape(id))
|
|
4754
|
+
);
|
|
4755
|
+
shapesToFlipFirstPass.push(...childrenOfGroups);
|
|
4756
|
+
}
|
|
4757
|
+
}
|
|
4758
|
+
const shapesToFlip = [];
|
|
4759
|
+
const allBounds = [];
|
|
4760
|
+
for (const shape of shapesToFlipFirstPass) {
|
|
4761
|
+
const util = this.getShapeUtil(shape);
|
|
4762
|
+
if (!util.canBeLaidOut(shape, {
|
|
4763
|
+
type: "flip",
|
|
4764
|
+
shapes: shapesToFlipFirstPass
|
|
4765
|
+
})) {
|
|
4766
|
+
continue;
|
|
4767
|
+
}
|
|
4768
|
+
const pageBounds = this.getShapePageBounds(shape);
|
|
4769
|
+
const localBounds = this.getShapeGeometry(shape).bounds;
|
|
4770
|
+
const pageTransform = this.getShapePageTransform(shape.id);
|
|
4771
|
+
if (!(pageBounds && localBounds && pageTransform)) continue;
|
|
4772
|
+
shapesToFlip.push({
|
|
4773
|
+
shape,
|
|
4774
|
+
localBounds,
|
|
4775
|
+
pageTransform,
|
|
4776
|
+
isAspectRatioLocked: util.isAspectRatioLocked(shape)
|
|
4777
|
+
});
|
|
4778
|
+
allBounds.push(pageBounds);
|
|
4779
|
+
}
|
|
4717
4780
|
if (!shapesToFlip.length) return this;
|
|
4718
|
-
|
|
4719
|
-
shapesToFlip.map((shape) => {
|
|
4720
|
-
if (this.isShapeOfType(shape, "group")) {
|
|
4721
|
-
return this.getSortedChildIdsForParent(shape.id).map((id) => this.getShape(id));
|
|
4722
|
-
}
|
|
4723
|
-
return shape;
|
|
4724
|
-
}).flat()
|
|
4725
|
-
);
|
|
4726
|
-
const scaleOriginPage = Box.Common(
|
|
4727
|
-
compact(shapesToFlip.map((id) => this.getShapePageBounds(id)))
|
|
4728
|
-
).center;
|
|
4781
|
+
const scaleOriginPage = Box.Common(allBounds).center;
|
|
4729
4782
|
this.run(() => {
|
|
4730
|
-
for (const shape of shapesToFlip) {
|
|
4731
|
-
const bounds = this.getShapeGeometry(shape).bounds;
|
|
4732
|
-
const initialPageTransform = this.getShapePageTransform(shape.id);
|
|
4733
|
-
if (!initialPageTransform) continue;
|
|
4783
|
+
for (const { shape, localBounds, pageTransform, isAspectRatioLocked } of shapesToFlip) {
|
|
4734
4784
|
this.resizeShape(
|
|
4735
4785
|
shape.id,
|
|
4736
4786
|
{ x: operation === "horizontal" ? -1 : 1, y: operation === "vertical" ? -1 : 1 },
|
|
4737
4787
|
{
|
|
4738
|
-
initialBounds:
|
|
4739
|
-
initialPageTransform,
|
|
4788
|
+
initialBounds: localBounds,
|
|
4789
|
+
initialPageTransform: pageTransform,
|
|
4740
4790
|
initialShape: shape,
|
|
4791
|
+
isAspectRatioLocked,
|
|
4741
4792
|
mode: "scale_shape",
|
|
4742
|
-
isAspectRatioLocked: this.getShapeUtil(shape).isAspectRatioLocked(shape),
|
|
4743
4793
|
scaleOrigin: scaleOriginPage,
|
|
4744
4794
|
scaleAxisRotation: 0
|
|
4745
4795
|
}
|
|
@@ -4766,15 +4816,40 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4766
4816
|
stackShapes(shapes, operation, gap) {
|
|
4767
4817
|
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
4768
4818
|
if (this.getIsReadonly()) return this;
|
|
4769
|
-
const
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
const
|
|
4819
|
+
const shapesToStackFirstPass = compact(ids.map((id) => this.getShape(id)));
|
|
4820
|
+
const shapeClustersToStack = [];
|
|
4821
|
+
const allBounds = [];
|
|
4822
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4823
|
+
for (const shape of shapesToStackFirstPass) {
|
|
4824
|
+
if (visited.has(shape.id)) continue;
|
|
4825
|
+
visited.add(shape.id);
|
|
4826
|
+
const shapePageBounds = this.getShapePageBounds(shape);
|
|
4827
|
+
if (!shapePageBounds) continue;
|
|
4828
|
+
if (!this.getShapeUtil(shape).canBeLaidOut?.(shape, {
|
|
4829
|
+
type: "stack",
|
|
4830
|
+
shapes: shapesToStackFirstPass
|
|
4831
|
+
})) {
|
|
4832
|
+
continue;
|
|
4833
|
+
}
|
|
4834
|
+
const shapesMovingTogether = [shape];
|
|
4835
|
+
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
4836
|
+
this.collectShapesViaArrowBindings({
|
|
4837
|
+
bindings: this.getBindingsToShape(shape.id, "arrow"),
|
|
4838
|
+
initialShapes: shapesToStackFirstPass,
|
|
4839
|
+
resultShapes: shapesMovingTogether,
|
|
4840
|
+
resultBounds: boundsOfShapesMovingTogether,
|
|
4841
|
+
visited
|
|
4842
|
+
});
|
|
4843
|
+
const commonPageBounds = Box.Common(boundsOfShapesMovingTogether);
|
|
4844
|
+
if (!commonPageBounds) continue;
|
|
4845
|
+
shapeClustersToStack.push({
|
|
4846
|
+
shapes: shapesMovingTogether,
|
|
4847
|
+
pageBounds: commonPageBounds
|
|
4848
|
+
});
|
|
4849
|
+
allBounds.push(commonPageBounds);
|
|
4850
|
+
}
|
|
4851
|
+
const len = shapeClustersToStack.length;
|
|
4774
4852
|
if (gap === 0 && len < 3 || len < 2) return this;
|
|
4775
|
-
const pageBounds = Object.fromEntries(
|
|
4776
|
-
shapesToStack.map((shape) => [shape.id, this.getShapePageBounds(shape)])
|
|
4777
|
-
);
|
|
4778
4853
|
let val;
|
|
4779
4854
|
let min;
|
|
4780
4855
|
let max;
|
|
@@ -4790,57 +4865,55 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4790
4865
|
max = "maxY";
|
|
4791
4866
|
dim = "height";
|
|
4792
4867
|
}
|
|
4793
|
-
let shapeGap;
|
|
4868
|
+
let shapeGap = 0;
|
|
4794
4869
|
if (gap === 0) {
|
|
4795
|
-
const gaps =
|
|
4796
|
-
|
|
4870
|
+
const gaps = {};
|
|
4871
|
+
shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
|
|
4797
4872
|
for (let i = 0; i < len - 1; i++) {
|
|
4798
|
-
const
|
|
4799
|
-
const
|
|
4800
|
-
const
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
const current = gaps.find((g) => g.gap === gap2);
|
|
4804
|
-
if (current) {
|
|
4805
|
-
current.count++;
|
|
4806
|
-
} else {
|
|
4807
|
-
gaps.push({ gap: gap2, count: 1 });
|
|
4873
|
+
const currCluster = shapeClustersToStack[i];
|
|
4874
|
+
const nextCluster = shapeClustersToStack[i + 1];
|
|
4875
|
+
const gap2 = nextCluster.pageBounds[min] - currCluster.pageBounds[max];
|
|
4876
|
+
if (!gaps[gap2]) {
|
|
4877
|
+
gaps[gap2] = 0;
|
|
4808
4878
|
}
|
|
4879
|
+
gaps[gap2]++;
|
|
4809
4880
|
}
|
|
4810
|
-
let maxCount =
|
|
4811
|
-
|
|
4812
|
-
if (
|
|
4813
|
-
maxCount =
|
|
4814
|
-
shapeGap =
|
|
4881
|
+
let maxCount = 1;
|
|
4882
|
+
for (const [gap2, count] of Object.entries(gaps)) {
|
|
4883
|
+
if (count > maxCount) {
|
|
4884
|
+
maxCount = count;
|
|
4885
|
+
shapeGap = parseFloat(gap2);
|
|
4815
4886
|
}
|
|
4816
|
-
}
|
|
4887
|
+
}
|
|
4817
4888
|
if (maxCount === 1) {
|
|
4818
|
-
|
|
4889
|
+
let totalCount = 0;
|
|
4890
|
+
for (const [gap2, count] of Object.entries(gaps)) {
|
|
4891
|
+
shapeGap += parseFloat(gap2) * count;
|
|
4892
|
+
totalCount += count;
|
|
4893
|
+
}
|
|
4894
|
+
shapeGap /= totalCount;
|
|
4819
4895
|
}
|
|
4820
4896
|
} else {
|
|
4821
4897
|
shapeGap = gap;
|
|
4822
4898
|
}
|
|
4823
4899
|
const changes = [];
|
|
4824
|
-
let v =
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
const delta =
|
|
4828
|
-
delta[val] = v + shapeGap - pageBounds[
|
|
4829
|
-
const
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
[val]: shape[val] + localDelta[val]
|
|
4836
|
-
} : {
|
|
4837
|
-
id: shape.id,
|
|
4838
|
-
type: shape.type,
|
|
4839
|
-
[val]: shape[val] + localDelta[val]
|
|
4900
|
+
let v = shapeClustersToStack[0].pageBounds[max];
|
|
4901
|
+
for (let i = 1; i < shapeClustersToStack.length; i++) {
|
|
4902
|
+
const { shapes: shapes2, pageBounds } = shapeClustersToStack[i];
|
|
4903
|
+
const delta = new Vec();
|
|
4904
|
+
delta[val] = v + shapeGap - pageBounds[val];
|
|
4905
|
+
for (const shape of shapes2) {
|
|
4906
|
+
const shapeDelta = delta.clone();
|
|
4907
|
+
const parent = this.getShapeParent(shape);
|
|
4908
|
+
if (parent) {
|
|
4909
|
+
const parentTransform = this.getShapePageTransform(parent);
|
|
4910
|
+
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
4840
4911
|
}
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4912
|
+
shapeDelta.add(shape);
|
|
4913
|
+
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
4914
|
+
}
|
|
4915
|
+
v += pageBounds[dim] + shapeGap;
|
|
4916
|
+
}
|
|
4844
4917
|
this.updateShapes(changes);
|
|
4845
4918
|
return this;
|
|
4846
4919
|
}
|
|
@@ -4858,91 +4931,101 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4858
4931
|
* @param gap - The padding to apply to the packed shapes. Defaults to 16.
|
|
4859
4932
|
*/
|
|
4860
4933
|
packShapes(shapes, gap) {
|
|
4861
|
-
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
4862
4934
|
if (this.getIsReadonly()) return this;
|
|
4863
|
-
|
|
4864
|
-
const
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
const
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4935
|
+
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
4936
|
+
const shapesToPackFirstPass = compact(ids.map((id) => this.getShape(id)));
|
|
4937
|
+
const shapeClustersToPack = [];
|
|
4938
|
+
const allBounds = [];
|
|
4939
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4940
|
+
for (const shape of shapesToPackFirstPass) {
|
|
4941
|
+
if (visited.has(shape.id)) continue;
|
|
4942
|
+
visited.add(shape.id);
|
|
4943
|
+
const shapePageBounds = this.getShapePageBounds(shape);
|
|
4944
|
+
if (!shapePageBounds) continue;
|
|
4945
|
+
if (!this.getShapeUtil(shape).canBeLaidOut?.(shape, {
|
|
4946
|
+
type: "pack",
|
|
4947
|
+
shapes: shapesToPackFirstPass
|
|
4948
|
+
})) {
|
|
4949
|
+
continue;
|
|
4950
|
+
}
|
|
4951
|
+
const shapesMovingTogether = [shape];
|
|
4952
|
+
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
4953
|
+
this.collectShapesViaArrowBindings({
|
|
4954
|
+
bindings: this.getBindingsToShape(shape.id, "arrow"),
|
|
4955
|
+
initialShapes: shapesToPackFirstPass,
|
|
4956
|
+
resultShapes: shapesMovingTogether,
|
|
4957
|
+
resultBounds: boundsOfShapesMovingTogether,
|
|
4958
|
+
visited
|
|
4959
|
+
});
|
|
4960
|
+
const commonPageBounds = Box.Common(boundsOfShapesMovingTogether);
|
|
4961
|
+
if (!commonPageBounds) continue;
|
|
4962
|
+
shapeClustersToPack.push({
|
|
4963
|
+
shapes: shapesMovingTogether,
|
|
4964
|
+
pageBounds: commonPageBounds,
|
|
4965
|
+
nextPageBounds: commonPageBounds.clone()
|
|
4966
|
+
});
|
|
4967
|
+
allBounds.push(commonPageBounds);
|
|
4968
|
+
}
|
|
4969
|
+
if (shapeClustersToPack.length < 2) return this;
|
|
4970
|
+
let area = 0;
|
|
4971
|
+
for (const { pageBounds } of shapeClustersToPack) {
|
|
4972
|
+
area += pageBounds.width * pageBounds.height;
|
|
4973
|
+
}
|
|
4974
|
+
const commonBounds = Box.Common(allBounds);
|
|
4879
4975
|
const maxWidth = commonBounds.width;
|
|
4880
|
-
|
|
4976
|
+
shapeClustersToPack.sort((a, b) => a.pageBounds.width - b.pageBounds.width).sort((a, b) => a.pageBounds.height - b.pageBounds.height);
|
|
4881
4977
|
const startWidth = Math.max(Math.ceil(Math.sqrt(area / 0.95)), maxWidth);
|
|
4882
4978
|
const spaces = [new Box(commonBounds.x, commonBounds.y, startWidth, Infinity)];
|
|
4883
4979
|
let width = 0;
|
|
4884
4980
|
let height = 0;
|
|
4885
4981
|
let space;
|
|
4886
4982
|
let last2;
|
|
4887
|
-
for (
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
width = Math.max(width, bounds.maxX);
|
|
4897
|
-
if (bounds.width === space.width && bounds.height === space.height) {
|
|
4983
|
+
for (const { nextPageBounds } of shapeClustersToPack) {
|
|
4984
|
+
for (let i = spaces.length - 1; i >= 0; i--) {
|
|
4985
|
+
space = spaces[i];
|
|
4986
|
+
if (nextPageBounds.width > space.width || nextPageBounds.height > space.height) continue;
|
|
4987
|
+
nextPageBounds.x = space.x;
|
|
4988
|
+
nextPageBounds.y = space.y;
|
|
4989
|
+
height = Math.max(height, nextPageBounds.maxY);
|
|
4990
|
+
width = Math.max(width, nextPageBounds.maxX);
|
|
4991
|
+
if (nextPageBounds.width === space.width && nextPageBounds.height === space.height) {
|
|
4898
4992
|
last2 = spaces.pop();
|
|
4899
|
-
if (
|
|
4900
|
-
} else if (
|
|
4901
|
-
space.x +=
|
|
4902
|
-
space.width -=
|
|
4903
|
-
} else if (
|
|
4904
|
-
space.y +=
|
|
4905
|
-
space.height -=
|
|
4993
|
+
if (i < spaces.length) spaces[i] = last2;
|
|
4994
|
+
} else if (nextPageBounds.height === space.height) {
|
|
4995
|
+
space.x += nextPageBounds.width + gap;
|
|
4996
|
+
space.width -= nextPageBounds.width + gap;
|
|
4997
|
+
} else if (nextPageBounds.width === space.width) {
|
|
4998
|
+
space.y += nextPageBounds.height + gap;
|
|
4999
|
+
space.height -= nextPageBounds.height + gap;
|
|
4906
5000
|
} else {
|
|
4907
5001
|
spaces.push(
|
|
4908
5002
|
new Box(
|
|
4909
|
-
space.x + (
|
|
5003
|
+
space.x + (nextPageBounds.width + gap),
|
|
4910
5004
|
space.y,
|
|
4911
|
-
space.width - (
|
|
4912
|
-
|
|
5005
|
+
space.width - (nextPageBounds.width + gap),
|
|
5006
|
+
nextPageBounds.height
|
|
4913
5007
|
)
|
|
4914
5008
|
);
|
|
4915
|
-
space.y +=
|
|
4916
|
-
space.height -=
|
|
5009
|
+
space.y += nextPageBounds.height + gap;
|
|
5010
|
+
space.height -= nextPageBounds.height + gap;
|
|
4917
5011
|
}
|
|
4918
5012
|
break;
|
|
4919
5013
|
}
|
|
4920
5014
|
}
|
|
4921
|
-
const commonAfter = Box.Common(
|
|
5015
|
+
const commonAfter = Box.Common(shapeClustersToPack.map((s) => s.nextPageBounds));
|
|
4922
5016
|
const centerDelta = Vec.Sub(commonBounds.center, commonAfter.center);
|
|
4923
|
-
let nextBounds;
|
|
4924
5017
|
const changes = [];
|
|
4925
|
-
for (
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
y: shape.y + delta.y
|
|
4937
|
-
};
|
|
4938
|
-
const translateStartChange = this.getShapeUtil(shape).onTranslateStart?.({
|
|
4939
|
-
...shape,
|
|
4940
|
-
...change
|
|
4941
|
-
});
|
|
4942
|
-
if (translateStartChange) {
|
|
4943
|
-
changes.push({ ...change, ...translateStartChange });
|
|
4944
|
-
} else {
|
|
4945
|
-
changes.push(change);
|
|
5018
|
+
for (const { shapes: shapes2, pageBounds, nextPageBounds } of shapeClustersToPack) {
|
|
5019
|
+
const delta = Vec.Sub(nextPageBounds.point, pageBounds.point).add(centerDelta);
|
|
5020
|
+
for (const shape of shapes2) {
|
|
5021
|
+
const shapeDelta = delta.clone();
|
|
5022
|
+
const parent = this.getShapeParent(shape);
|
|
5023
|
+
if (parent) {
|
|
5024
|
+
const parentTransform = this.getShapeParentTransform(shape);
|
|
5025
|
+
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5026
|
+
}
|
|
5027
|
+
shapeDelta.add(shape);
|
|
5028
|
+
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
4946
5029
|
}
|
|
4947
5030
|
}
|
|
4948
5031
|
if (changes.length) {
|
|
@@ -4965,19 +5048,45 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4965
5048
|
* @public
|
|
4966
5049
|
*/
|
|
4967
5050
|
alignShapes(shapes, operation) {
|
|
4968
|
-
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
4969
5051
|
if (this.getIsReadonly()) return this;
|
|
4970
|
-
|
|
4971
|
-
const
|
|
4972
|
-
const
|
|
4973
|
-
|
|
4974
|
-
);
|
|
4975
|
-
const
|
|
5052
|
+
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
5053
|
+
const shapesToAlignFirstPass = compact(ids.map((id) => this.getShape(id)));
|
|
5054
|
+
const shapeClustersToAlign = [];
|
|
5055
|
+
const allBounds = [];
|
|
5056
|
+
const visited = /* @__PURE__ */ new Set();
|
|
5057
|
+
for (const shape of shapesToAlignFirstPass) {
|
|
5058
|
+
if (visited.has(shape.id)) continue;
|
|
5059
|
+
visited.add(shape.id);
|
|
5060
|
+
const shapePageBounds = this.getShapePageBounds(shape);
|
|
5061
|
+
if (!shapePageBounds) continue;
|
|
5062
|
+
if (!this.getShapeUtil(shape).canBeLaidOut?.(shape, {
|
|
5063
|
+
type: "align",
|
|
5064
|
+
shapes: shapesToAlignFirstPass
|
|
5065
|
+
})) {
|
|
5066
|
+
continue;
|
|
5067
|
+
}
|
|
5068
|
+
const shapesMovingTogether = [shape];
|
|
5069
|
+
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
5070
|
+
this.collectShapesViaArrowBindings({
|
|
5071
|
+
bindings: this.getBindingsToShape(shape.id, "arrow"),
|
|
5072
|
+
initialShapes: shapesToAlignFirstPass,
|
|
5073
|
+
resultShapes: shapesMovingTogether,
|
|
5074
|
+
resultBounds: boundsOfShapesMovingTogether,
|
|
5075
|
+
visited
|
|
5076
|
+
});
|
|
5077
|
+
const commonPageBounds = Box.Common(boundsOfShapesMovingTogether);
|
|
5078
|
+
if (!commonPageBounds) continue;
|
|
5079
|
+
shapeClustersToAlign.push({
|
|
5080
|
+
shapes: shapesMovingTogether,
|
|
5081
|
+
pageBounds: commonPageBounds
|
|
5082
|
+
});
|
|
5083
|
+
allBounds.push(commonPageBounds);
|
|
5084
|
+
}
|
|
5085
|
+
if (shapeClustersToAlign.length < 2) return this;
|
|
5086
|
+
const commonBounds = Box.Common(allBounds);
|
|
4976
5087
|
const changes = [];
|
|
4977
|
-
|
|
4978
|
-
const
|
|
4979
|
-
if (!pageBounds) return;
|
|
4980
|
-
const delta = { x: 0, y: 0 };
|
|
5088
|
+
shapeClustersToAlign.forEach(({ shapes: shapes2, pageBounds }) => {
|
|
5089
|
+
const delta = new Vec();
|
|
4981
5090
|
switch (operation) {
|
|
4982
5091
|
case "top": {
|
|
4983
5092
|
delta.y = commonBounds.minY - pageBounds.minY;
|
|
@@ -5004,9 +5113,16 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
5004
5113
|
break;
|
|
5005
5114
|
}
|
|
5006
5115
|
}
|
|
5007
|
-
const
|
|
5008
|
-
|
|
5009
|
-
|
|
5116
|
+
for (const shape of shapes2) {
|
|
5117
|
+
const shapeDelta = delta.clone();
|
|
5118
|
+
const parent = this.getShapeParent(shape);
|
|
5119
|
+
if (parent) {
|
|
5120
|
+
const parentTransform = this.getShapePageTransform(parent);
|
|
5121
|
+
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5122
|
+
}
|
|
5123
|
+
shapeDelta.add(shape);
|
|
5124
|
+
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5125
|
+
}
|
|
5010
5126
|
});
|
|
5011
5127
|
this.updateShapes(changes);
|
|
5012
5128
|
return this;
|
|
@@ -5026,47 +5142,95 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
5026
5142
|
* @public
|
|
5027
5143
|
*/
|
|
5028
5144
|
distributeShapes(shapes, operation) {
|
|
5029
|
-
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
5030
5145
|
if (this.getIsReadonly()) return this;
|
|
5031
|
-
|
|
5032
|
-
const
|
|
5033
|
-
const
|
|
5034
|
-
const
|
|
5035
|
-
|
|
5036
|
-
)
|
|
5146
|
+
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
5147
|
+
const shapesToDistributeFirstPass = compact(ids.map((id) => this.getShape(id)));
|
|
5148
|
+
const shapeClustersToDistribute = [];
|
|
5149
|
+
const allBounds = [];
|
|
5150
|
+
const visited = /* @__PURE__ */ new Set();
|
|
5151
|
+
for (const shape of shapesToDistributeFirstPass) {
|
|
5152
|
+
if (visited.has(shape.id)) continue;
|
|
5153
|
+
visited.add(shape.id);
|
|
5154
|
+
const shapePageBounds = this.getShapePageBounds(shape);
|
|
5155
|
+
if (!shapePageBounds) continue;
|
|
5156
|
+
if (!this.getShapeUtil(shape).canBeLaidOut?.(shape, {
|
|
5157
|
+
type: "distribute",
|
|
5158
|
+
shapes: shapesToDistributeFirstPass
|
|
5159
|
+
})) {
|
|
5160
|
+
continue;
|
|
5161
|
+
}
|
|
5162
|
+
const shapesMovingTogether = [shape];
|
|
5163
|
+
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
5164
|
+
this.collectShapesViaArrowBindings({
|
|
5165
|
+
bindings: this.getBindingsToShape(shape.id, "arrow"),
|
|
5166
|
+
initialShapes: shapesToDistributeFirstPass,
|
|
5167
|
+
resultShapes: shapesMovingTogether,
|
|
5168
|
+
resultBounds: boundsOfShapesMovingTogether,
|
|
5169
|
+
visited
|
|
5170
|
+
});
|
|
5171
|
+
const commonPageBounds = Box.Common(boundsOfShapesMovingTogether);
|
|
5172
|
+
if (!commonPageBounds) continue;
|
|
5173
|
+
shapeClustersToDistribute.push({
|
|
5174
|
+
shapes: shapesMovingTogether,
|
|
5175
|
+
pageBounds: commonPageBounds
|
|
5176
|
+
});
|
|
5177
|
+
allBounds.push(commonPageBounds);
|
|
5178
|
+
}
|
|
5179
|
+
if (shapeClustersToDistribute.length < 3) return this;
|
|
5037
5180
|
let val;
|
|
5038
5181
|
let min;
|
|
5039
5182
|
let max;
|
|
5040
|
-
let mid;
|
|
5041
5183
|
let dim;
|
|
5042
5184
|
if (operation === "horizontal") {
|
|
5043
5185
|
val = "x";
|
|
5044
5186
|
min = "minX";
|
|
5045
5187
|
max = "maxX";
|
|
5046
|
-
mid = "midX";
|
|
5047
5188
|
dim = "width";
|
|
5048
5189
|
} else {
|
|
5049
5190
|
val = "y";
|
|
5050
5191
|
min = "minY";
|
|
5051
5192
|
max = "maxY";
|
|
5052
|
-
mid = "midY";
|
|
5053
5193
|
dim = "height";
|
|
5054
5194
|
}
|
|
5055
5195
|
const changes = [];
|
|
5056
|
-
const first =
|
|
5057
|
-
|
|
5058
|
-
)
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5196
|
+
const first = shapeClustersToDistribute.sort((a, b) => a.pageBounds[min] - b.pageBounds[min])[0];
|
|
5197
|
+
const last2 = shapeClustersToDistribute.sort((a, b) => b.pageBounds[max] - a.pageBounds[max])[0];
|
|
5198
|
+
if (first === last2) {
|
|
5199
|
+
const excludedShapeIds = new Set(first.shapes.map((s) => s.id));
|
|
5200
|
+
return this.distributeShapes(
|
|
5201
|
+
ids.filter((id) => !excludedShapeIds.has(id)),
|
|
5202
|
+
operation
|
|
5203
|
+
);
|
|
5204
|
+
}
|
|
5205
|
+
const shapeClustersToMove = shapeClustersToDistribute.filter((shape) => shape !== first && shape !== last2).sort((a, b) => {
|
|
5206
|
+
if (a.pageBounds[min] === b.pageBounds[min]) {
|
|
5207
|
+
return a.shapes[0].id < b.shapes[0].id ? -1 : 1;
|
|
5208
|
+
}
|
|
5209
|
+
return a.pageBounds[min] - b.pageBounds[min];
|
|
5069
5210
|
});
|
|
5211
|
+
const maxFirst = first.pageBounds[max];
|
|
5212
|
+
const range = last2.pageBounds[min] - maxFirst;
|
|
5213
|
+
const summedShapeDimensions = shapeClustersToMove.reduce((acc, s) => acc + s.pageBounds[dim], 0);
|
|
5214
|
+
const gap = (range - summedShapeDimensions) / (shapeClustersToMove.length + 1);
|
|
5215
|
+
for (let v = maxFirst + gap, i = 0; i < shapeClustersToMove.length; i++) {
|
|
5216
|
+
const { shapes: shapes2, pageBounds } = shapeClustersToMove[i];
|
|
5217
|
+
const delta = new Vec();
|
|
5218
|
+
delta[val] = v - pageBounds[val];
|
|
5219
|
+
if (v + pageBounds[dim] > last2.pageBounds[max] - 1) {
|
|
5220
|
+
delta[val] = last2.pageBounds[max] - pageBounds[max] - 1;
|
|
5221
|
+
}
|
|
5222
|
+
for (const shape of shapes2) {
|
|
5223
|
+
const shapeDelta = delta.clone();
|
|
5224
|
+
const parent = this.getShapeParent(shape);
|
|
5225
|
+
if (parent) {
|
|
5226
|
+
const parentTransform = this.getShapePageTransform(parent);
|
|
5227
|
+
if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
|
|
5228
|
+
}
|
|
5229
|
+
shapeDelta.add(shape);
|
|
5230
|
+
changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
|
|
5231
|
+
}
|
|
5232
|
+
v += pageBounds[dim] + gap;
|
|
5233
|
+
}
|
|
5070
5234
|
this.updateShapes(changes);
|
|
5071
5235
|
return this;
|
|
5072
5236
|
}
|
|
@@ -5087,59 +5251,78 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
5087
5251
|
stretchShapes(shapes, operation) {
|
|
5088
5252
|
const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
|
|
5089
5253
|
if (this.getIsReadonly()) return this;
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
const
|
|
5094
|
-
const
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
const scale = new Vec(1, commonBounds.height / pageBounds.height);
|
|
5109
|
-
this.resizeShape(shape.id, scale, {
|
|
5110
|
-
initialBounds: bounds,
|
|
5111
|
-
scaleOrigin: new Vec(pageBounds.center.x, commonBounds.minY),
|
|
5112
|
-
isAspectRatioLocked: this.getShapeUtil(shape).isAspectRatioLocked(shape),
|
|
5113
|
-
scaleAxisRotation: 0
|
|
5114
|
-
});
|
|
5115
|
-
}
|
|
5116
|
-
});
|
|
5117
|
-
break;
|
|
5118
|
-
}
|
|
5119
|
-
case "horizontal": {
|
|
5120
|
-
this.run(() => {
|
|
5121
|
-
for (const shape of shapesToStretch) {
|
|
5122
|
-
const bounds = shapeBounds[shape.id];
|
|
5123
|
-
const pageBounds = shapePageBounds[shape.id];
|
|
5124
|
-
const pageRotation = this.getShapePageTransform(shape).rotation();
|
|
5125
|
-
if (pageRotation % PI2) continue;
|
|
5126
|
-
const localOffset = new Vec(commonBounds.minX - pageBounds.minX, 0);
|
|
5127
|
-
const parentTransform = this.getShapeParentTransform(shape);
|
|
5128
|
-
if (parentTransform) localOffset.rot(-parentTransform.rotation());
|
|
5129
|
-
const { x, y } = Vec.Add(localOffset, shape);
|
|
5130
|
-
this.updateShapes([{ id: shape.id, type: shape.type, x, y }]);
|
|
5131
|
-
const scale = new Vec(commonBounds.width / pageBounds.width, 1);
|
|
5132
|
-
this.resizeShape(shape.id, scale, {
|
|
5133
|
-
initialBounds: bounds,
|
|
5134
|
-
scaleOrigin: new Vec(commonBounds.minX, pageBounds.center.y),
|
|
5135
|
-
isAspectRatioLocked: this.getShapeUtil(shape).isAspectRatioLocked(shape),
|
|
5136
|
-
scaleAxisRotation: 0
|
|
5137
|
-
});
|
|
5138
|
-
}
|
|
5139
|
-
});
|
|
5140
|
-
break;
|
|
5254
|
+
const shapesToStretchFirstPass = compact(ids.map((id) => this.getShape(id))).filter(
|
|
5255
|
+
(s) => this.getShapePageTransform(s)?.rotation() % (PI / 2) === 0
|
|
5256
|
+
);
|
|
5257
|
+
const shapeClustersToStretch = [];
|
|
5258
|
+
const allBounds = [];
|
|
5259
|
+
const visited = /* @__PURE__ */ new Set();
|
|
5260
|
+
for (const shape of shapesToStretchFirstPass) {
|
|
5261
|
+
if (visited.has(shape.id)) continue;
|
|
5262
|
+
visited.add(shape.id);
|
|
5263
|
+
const shapePageBounds = this.getShapePageBounds(shape);
|
|
5264
|
+
if (!shapePageBounds) continue;
|
|
5265
|
+
const shapesMovingTogether = [shape];
|
|
5266
|
+
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
5267
|
+
if (!this.getShapeUtil(shape).canBeLaidOut?.(shape, {
|
|
5268
|
+
type: "stretch",
|
|
5269
|
+
shapes: shapesToStretchFirstPass
|
|
5270
|
+
})) {
|
|
5271
|
+
continue;
|
|
5141
5272
|
}
|
|
5273
|
+
this.collectShapesViaArrowBindings({
|
|
5274
|
+
bindings: this.getBindingsToShape(shape.id, "arrow"),
|
|
5275
|
+
initialShapes: shapesToStretchFirstPass,
|
|
5276
|
+
resultShapes: shapesMovingTogether,
|
|
5277
|
+
resultBounds: boundsOfShapesMovingTogether,
|
|
5278
|
+
visited
|
|
5279
|
+
});
|
|
5280
|
+
const commonPageBounds = Box.Common(boundsOfShapesMovingTogether);
|
|
5281
|
+
if (!commonPageBounds) continue;
|
|
5282
|
+
shapeClustersToStretch.push({
|
|
5283
|
+
shapes: shapesMovingTogether,
|
|
5284
|
+
pageBounds: commonPageBounds
|
|
5285
|
+
});
|
|
5286
|
+
allBounds.push(commonPageBounds);
|
|
5287
|
+
}
|
|
5288
|
+
if (shapeClustersToStretch.length < 2) return this;
|
|
5289
|
+
const commonBounds = Box.Common(allBounds);
|
|
5290
|
+
let val;
|
|
5291
|
+
let min;
|
|
5292
|
+
let dim;
|
|
5293
|
+
if (operation === "horizontal") {
|
|
5294
|
+
val = "x";
|
|
5295
|
+
min = "minX";
|
|
5296
|
+
dim = "width";
|
|
5297
|
+
} else {
|
|
5298
|
+
val = "y";
|
|
5299
|
+
min = "minY";
|
|
5300
|
+
dim = "height";
|
|
5142
5301
|
}
|
|
5302
|
+
this.run(() => {
|
|
5303
|
+
shapeClustersToStretch.forEach(({ shapes: shapes2, pageBounds }) => {
|
|
5304
|
+
const localOffset = new Vec();
|
|
5305
|
+
localOffset[val] = commonBounds[min] - pageBounds[min];
|
|
5306
|
+
const scaleOrigin = pageBounds.center.clone();
|
|
5307
|
+
scaleOrigin[val] = commonBounds[min];
|
|
5308
|
+
const scale = new Vec(1, 1);
|
|
5309
|
+
scale[val] = commonBounds[dim] / pageBounds[dim];
|
|
5310
|
+
for (const shape of shapes2) {
|
|
5311
|
+
const shapeLocalOffset = localOffset.clone();
|
|
5312
|
+
const parentTransform = this.getShapeParentTransform(shape);
|
|
5313
|
+
if (parentTransform) localOffset.rot(-parentTransform.rotation());
|
|
5314
|
+
shapeLocalOffset.add(shape);
|
|
5315
|
+
const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
|
|
5316
|
+
this.updateShape(changes);
|
|
5317
|
+
this.resizeShape(shape.id, scale, {
|
|
5318
|
+
initialBounds: this.getShapeGeometry(shape).bounds,
|
|
5319
|
+
scaleOrigin,
|
|
5320
|
+
isAspectRatioLocked: this.getShapeUtil(shape).isAspectRatioLocked(shape),
|
|
5321
|
+
scaleAxisRotation: 0
|
|
5322
|
+
});
|
|
5323
|
+
}
|
|
5324
|
+
});
|
|
5325
|
+
});
|
|
5143
5326
|
return this;
|
|
5144
5327
|
}
|
|
5145
5328
|
/**
|
|
@@ -7389,7 +7572,6 @@ __decorateElement(_init, 1, "getPages", _getPages_dec, Editor);
|
|
|
7389
7572
|
__decorateElement(_init, 1, "getCurrentPageId", _getCurrentPageId_dec, Editor);
|
|
7390
7573
|
__decorateElement(_init, 1, "getCurrentPageShapeIdsSorted", _getCurrentPageShapeIdsSorted_dec, Editor);
|
|
7391
7574
|
__decorateElement(_init, 1, "_getAllAssetsQuery", __getAllAssetsQuery_dec, Editor);
|
|
7392
|
-
__decorateElement(_init, 1, "_getShapeGeometryCache", __getShapeGeometryCache_dec, Editor);
|
|
7393
7575
|
__decorateElement(_init, 1, "_getShapeHandlesCache", __getShapeHandlesCache_dec, Editor);
|
|
7394
7576
|
__decorateElement(_init, 1, "_getShapePageTransformCache", __getShapePageTransformCache_dec, Editor);
|
|
7395
7577
|
__decorateElement(_init, 1, "_getShapePageBoundsCache", __getShapePageBoundsCache_dec, Editor);
|
|
@@ -7479,7 +7661,7 @@ function withIsolatedShapes(editor, shapeIds, callback) {
|
|
|
7479
7661
|
result = Result.err(error);
|
|
7480
7662
|
}
|
|
7481
7663
|
});
|
|
7482
|
-
editor.store.applyDiff(reverseRecordsDiff(changes));
|
|
7664
|
+
editor.store.applyDiff(reverseRecordsDiff(changes), { runCallbacks: false });
|
|
7483
7665
|
},
|
|
7484
7666
|
{ history: "ignore" }
|
|
7485
7667
|
);
|