@tldraw/editor 4.5.0-canary.a6e749bd3e95 → 4.5.0-canary.b245c8ea38ef
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 +6 -0
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/editor/Editor.js +89 -87
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +10 -0
- package/dist-cjs/lib/primitives/geometry/Geometry2d.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 +6 -0
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/editor/Editor.mjs +90 -88
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +10 -0
- package/dist-esm/lib/primitives/geometry/Geometry2d.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/editor/Editor.ts +123 -124
- package/src/lib/primitives/geometry/Geometry2d.ts +12 -0
- package/src/version.ts +3 -3
package/dist-cjs/index.d.ts
CHANGED
|
@@ -4268,6 +4268,11 @@ export declare abstract class Geometry2d {
|
|
|
4268
4268
|
private _length?;
|
|
4269
4269
|
get length(): number;
|
|
4270
4270
|
getLength(_filters?: Geometry2dFilters): number;
|
|
4271
|
+
/**
|
|
4272
|
+
* Called after a hit test succeeds. Return `true` to reject the hit and allow
|
|
4273
|
+
* shapes behind this one to be selected instead (e.g. transparent image pixels).
|
|
4274
|
+
*/
|
|
4275
|
+
ignoreHit(_point: VecLike): boolean;
|
|
4271
4276
|
abstract getSvgPathData(first: boolean): string;
|
|
4272
4277
|
}
|
|
4273
4278
|
|
|
@@ -8426,6 +8431,7 @@ export declare class TransformedGeometry2d extends Geometry2d {
|
|
|
8426
8431
|
intersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters): Vec[];
|
|
8427
8432
|
intersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters): VecLike[];
|
|
8428
8433
|
intersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters): VecLike[];
|
|
8434
|
+
ignoreHit(point: VecLike): boolean;
|
|
8429
8435
|
transform(transform: MatModel, opts?: TransformedGeometry2dOptions): Geometry2d;
|
|
8430
8436
|
getSvgPathData(): string;
|
|
8431
8437
|
}
|
package/dist-cjs/index.js
CHANGED
|
@@ -369,7 +369,7 @@ var import_LocalIndexedDb = require("./lib/utils/sync/LocalIndexedDb");
|
|
|
369
369
|
var import_uniq = require("./lib/utils/uniq");
|
|
370
370
|
(0, import_utils.registerTldrawLibraryVersion)(
|
|
371
371
|
"@tldraw/editor",
|
|
372
|
-
"4.5.0-canary.
|
|
372
|
+
"4.5.0-canary.b245c8ea38ef",
|
|
373
373
|
"cjs"
|
|
374
374
|
);
|
|
375
375
|
//# sourceMappingURL=index.js.map
|
|
@@ -3990,6 +3990,9 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
|
|
|
3990
3990
|
if (geometry.isClosed) {
|
|
3991
3991
|
if (distance <= outerMargin || hitInside && distance <= 0 && distance > -innerMargin) {
|
|
3992
3992
|
if (geometry.isFilled || isGroup && geometry.children[0].isFilled) {
|
|
3993
|
+
if (geometry.ignoreHit(pointInShapeSpace)) {
|
|
3994
|
+
continue;
|
|
3995
|
+
}
|
|
3993
3996
|
return inMarginClosestToEdgeHit || shape;
|
|
3994
3997
|
} else {
|
|
3995
3998
|
if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
|
|
@@ -6725,38 +6728,10 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
|
|
|
6725
6728
|
const bindingIdMap = new Map(
|
|
6726
6729
|
preserveIds ? bindings.map((binding) => [binding.id, binding.id]) : bindings.map((binding) => [binding.id, (0, import_tlschema.createBindingId)()])
|
|
6727
6730
|
);
|
|
6728
|
-
let pasteParentId =
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
for (const shape of this.getSelectedShapes()) {
|
|
6732
|
-
if (lowestDepth === 0) break;
|
|
6733
|
-
const isFrame = this.isShapeOfType(shape, "frame");
|
|
6734
|
-
const ancestors = this.getShapeAncestors(shape);
|
|
6735
|
-
if (isFrame) ancestors.push(shape);
|
|
6736
|
-
const depth = isFrame ? ancestors.length + 1 : ancestors.length;
|
|
6737
|
-
if (depth < lowestDepth) {
|
|
6738
|
-
lowestDepth = depth;
|
|
6739
|
-
lowestAncestors = ancestors;
|
|
6740
|
-
pasteParentId = isFrame ? shape.id : shape.parentId;
|
|
6741
|
-
} else if (depth === lowestDepth) {
|
|
6742
|
-
if (lowestAncestors.length !== ancestors.length) {
|
|
6743
|
-
throw Error(`Ancestors: ${lowestAncestors.length} !== ${ancestors.length}`);
|
|
6744
|
-
}
|
|
6745
|
-
if (lowestAncestors.length === 0) {
|
|
6746
|
-
pasteParentId = currentPageId;
|
|
6747
|
-
break;
|
|
6748
|
-
} else {
|
|
6749
|
-
pasteParentId = currentPageId;
|
|
6750
|
-
for (let i = 0; i < lowestAncestors.length; i++) {
|
|
6751
|
-
if (ancestors[i] !== lowestAncestors[i]) break;
|
|
6752
|
-
pasteParentId = ancestors[i].id;
|
|
6753
|
-
}
|
|
6754
|
-
}
|
|
6755
|
-
}
|
|
6756
|
-
}
|
|
6731
|
+
let pasteParentId = currentPageId;
|
|
6732
|
+
const shapesById = new Map(shapes.map((s) => [s.id, s]));
|
|
6733
|
+
const rootShapesFromContent = (0, import_utils.compact)(rootShapeIds.map((id) => shapesById.get(id)));
|
|
6757
6734
|
if (point) {
|
|
6758
|
-
const shapesById = new Map(shapes.map((shape) => [shape.id, shape]));
|
|
6759
|
-
const rootShapesFromContent = (0, import_utils.compact)(rootShapeIds.map((id) => shapesById.get(id)));
|
|
6760
6735
|
if (rootShapesFromContent.length > 0) {
|
|
6761
6736
|
const targetParent = this.getShapeAtPoint(point, {
|
|
6762
6737
|
hitInside: true,
|
|
@@ -6764,38 +6739,55 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
|
|
|
6764
6739
|
hitLocked: true,
|
|
6765
6740
|
filter: (shape) => {
|
|
6766
6741
|
const util = this.getShapeUtil(shape);
|
|
6767
|
-
if (!util.canReceiveNewChildrenOfType) return false;
|
|
6768
6742
|
return rootShapesFromContent.every(
|
|
6769
|
-
(rootShape) => util.canReceiveNewChildrenOfType(shape, rootShape.type)
|
|
6743
|
+
(rootShape) => util.canReceiveNewChildrenOfType?.(shape, rootShape.type)
|
|
6770
6744
|
);
|
|
6771
6745
|
}
|
|
6772
6746
|
});
|
|
6773
|
-
pasteParentId = targetParent
|
|
6774
|
-
}
|
|
6775
|
-
}
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
const
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6747
|
+
pasteParentId = targetParent?.id ?? currentPageId;
|
|
6748
|
+
}
|
|
6749
|
+
} else if (!preservePosition) {
|
|
6750
|
+
const selectedShapes = this.getSelectedShapes();
|
|
6751
|
+
let selectedParent = null;
|
|
6752
|
+
const canAcceptAll = (candidate) => {
|
|
6753
|
+
const util = this.getShapeUtil(candidate);
|
|
6754
|
+
return rootShapesFromContent.every(
|
|
6755
|
+
(rs) => util.canReceiveNewChildrenOfType?.(candidate, rs.type)
|
|
6756
|
+
);
|
|
6757
|
+
};
|
|
6758
|
+
for (const shape of selectedShapes) {
|
|
6759
|
+
const candidate = canAcceptAll(shape) ? shape : this.findShapeAncestor(shape, canAcceptAll) ?? ((0, import_tlschema.isShapeId)(shape.parentId) ? this.getShape(shape.parentId) : null);
|
|
6760
|
+
if (!candidate) {
|
|
6761
|
+
selectedParent = null;
|
|
6762
|
+
break;
|
|
6763
|
+
}
|
|
6764
|
+
if (!selectedParent) {
|
|
6765
|
+
selectedParent = candidate;
|
|
6766
|
+
} else if (selectedParent.id !== candidate.id) {
|
|
6767
|
+
const spAncestors = this.getShapeAncestors(selectedParent);
|
|
6768
|
+
if (canAcceptAll(selectedParent)) spAncestors.push(selectedParent);
|
|
6769
|
+
const acceptingAncestors = spAncestors.filter(canAcceptAll);
|
|
6770
|
+
const candidateAncestorIds = /* @__PURE__ */ new Set([
|
|
6771
|
+
candidate.id,
|
|
6772
|
+
...this.getShapeAncestors(candidate).map((a) => a.id)
|
|
6773
|
+
]);
|
|
6774
|
+
let common = null;
|
|
6775
|
+
for (let i = acceptingAncestors.length - 1; i >= 0; i--) {
|
|
6776
|
+
if (candidateAncestorIds.has(acceptingAncestors[i].id)) {
|
|
6777
|
+
common = acceptingAncestors[i];
|
|
6778
|
+
break;
|
|
6787
6779
|
}
|
|
6788
6780
|
}
|
|
6781
|
+
selectedParent = common;
|
|
6782
|
+
if (!selectedParent) break;
|
|
6789
6783
|
}
|
|
6790
|
-
} else {
|
|
6791
|
-
pasteParentId = currentPageId;
|
|
6792
6784
|
}
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6785
|
+
if (selectedParent && shapeIdMap.has(selectedParent.id)) {
|
|
6786
|
+
selectedParent = null;
|
|
6787
|
+
}
|
|
6788
|
+
if (selectedParent) {
|
|
6789
|
+
pasteParentId = selectedParent.id;
|
|
6790
|
+
}
|
|
6799
6791
|
}
|
|
6800
6792
|
let index = this.getHighestIndexForParent(pasteParentId);
|
|
6801
6793
|
const rootShapes = [];
|
|
@@ -6859,22 +6851,17 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
|
|
|
6859
6851
|
})
|
|
6860
6852
|
);
|
|
6861
6853
|
this.run(() => {
|
|
6862
|
-
if (assetsToCreate.length > 0)
|
|
6863
|
-
this.createAssets(assetsToCreate);
|
|
6864
|
-
}
|
|
6854
|
+
if (assetsToCreate.length > 0) this.createAssets(assetsToCreate);
|
|
6865
6855
|
this.createShapes(newShapes);
|
|
6866
6856
|
this.createBindings(newBindings);
|
|
6867
|
-
if (select)
|
|
6868
|
-
this.select(...rootShapes.map((s) => s.id));
|
|
6869
|
-
}
|
|
6857
|
+
if (select) this.select(...rootShapes.map((s) => s.id));
|
|
6870
6858
|
if (pasteParentId !== currentPageId) {
|
|
6871
6859
|
this.reparentShapes(
|
|
6872
6860
|
rootShapes.map((s) => s.id),
|
|
6873
6861
|
pasteParentId
|
|
6874
6862
|
);
|
|
6875
6863
|
}
|
|
6876
|
-
const
|
|
6877
|
-
const bounds = import_Box.Box.Common(newCreatedShapes.map((s) => this.getShapePageBounds(s)));
|
|
6864
|
+
const rootBounds = import_Box.Box.Common((0, import_utils.compact)(rootShapes.map((s) => this.getShapePageBounds(s.id))));
|
|
6878
6865
|
if (point === void 0) {
|
|
6879
6866
|
if (!(0, import_tlschema.isPageId)(pasteParentId)) {
|
|
6880
6867
|
const shape = this.getShape(pasteParentId);
|
|
@@ -6882,40 +6869,44 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
|
|
|
6882
6869
|
this.getShapePageTransform(shape),
|
|
6883
6870
|
this.getShapeGeometry(shape).bounds.center
|
|
6884
6871
|
);
|
|
6872
|
+
} else if (preservePosition) {
|
|
6873
|
+
point = rootBounds.center;
|
|
6885
6874
|
} else {
|
|
6886
6875
|
const viewportPageBounds = this.getViewportPageBounds();
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
}
|
|
6893
|
-
}
|
|
6894
|
-
if (rootShapes.length === 1) {
|
|
6895
|
-
const onlyRoot = rootShapes[0];
|
|
6896
|
-
if (this.isShapeOfType(onlyRoot, "frame")) {
|
|
6897
|
-
while (this.getShapesAtPoint(point).some(
|
|
6898
|
-
(shape) => this.isShapeOfType(shape, "frame") && shape.props.w === onlyRoot.props.w && shape.props.h === onlyRoot.props.h
|
|
6899
|
-
)) {
|
|
6900
|
-
point.x += bounds.w + 16;
|
|
6901
|
-
}
|
|
6876
|
+
const anyOverlap = rootShapes.some((s) => {
|
|
6877
|
+
const b = this.getShapePageBounds(s.id);
|
|
6878
|
+
return b && viewportPageBounds.collides(b);
|
|
6879
|
+
});
|
|
6880
|
+
point = anyOverlap ? rootBounds.center : viewportPageBounds.center;
|
|
6902
6881
|
}
|
|
6903
6882
|
}
|
|
6904
6883
|
const pageCenter = import_Box.Box.Common(
|
|
6905
6884
|
(0, import_utils.compact)(rootShapes.map(({ id }) => this.getShapePageBounds(id)))
|
|
6906
6885
|
).center;
|
|
6907
6886
|
const offset = import_Vec.Vec.Sub(point, pageCenter);
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6887
|
+
if (offset.x !== 0 || offset.y !== 0) {
|
|
6888
|
+
this.updateShapes(
|
|
6889
|
+
rootShapes.map(({ id }) => {
|
|
6890
|
+
const s = this.getShape(id);
|
|
6891
|
+
const localRotation = this.getShapeParentTransform(id).decompose().rotation;
|
|
6892
|
+
const localDelta = import_Vec.Vec.Rot(offset, -localRotation);
|
|
6893
|
+
return { id: s.id, type: s.type, x: s.x + localDelta.x, y: s.y + localDelta.y };
|
|
6894
|
+
})
|
|
6895
|
+
);
|
|
6896
|
+
}
|
|
6916
6897
|
if ((0, import_tlschema.isPageId)(pasteParentId)) {
|
|
6917
6898
|
const currentRootShapes = (0, import_utils.compact)(rootShapes.map((s) => this.getShape(s.id)));
|
|
6918
|
-
const { reparenting } = (0, import_reparenting.getDroppedShapesToNewParents)(
|
|
6899
|
+
const { reparenting } = (0, import_reparenting.getDroppedShapesToNewParents)(
|
|
6900
|
+
this,
|
|
6901
|
+
currentRootShapes,
|
|
6902
|
+
(shape, parent) => {
|
|
6903
|
+
if (shapeIdMap.has(parent.id)) return false;
|
|
6904
|
+
const shapeBounds = this.getShapePageBounds(shape);
|
|
6905
|
+
const parentBounds = this.getShapePageBounds(parent);
|
|
6906
|
+
if (!shapeBounds || !parentBounds) return false;
|
|
6907
|
+
return parentBounds.containsPoint(shapeBounds.center);
|
|
6908
|
+
}
|
|
6909
|
+
);
|
|
6919
6910
|
reparenting.forEach((childrenToReparent, newParentId) => {
|
|
6920
6911
|
if (childrenToReparent.length === 0) return;
|
|
6921
6912
|
this.reparentShapes(
|
|
@@ -6924,6 +6915,17 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
|
|
|
6924
6915
|
);
|
|
6925
6916
|
});
|
|
6926
6917
|
}
|
|
6918
|
+
const newShapeIdSet = new Set(newShapes.map((s) => s.id));
|
|
6919
|
+
const shapesToKickout = rootShapes.map((s) => s.id).filter((id) => {
|
|
6920
|
+
const shape = this.getShape(id);
|
|
6921
|
+
if (!shape) return false;
|
|
6922
|
+
if ((0, import_tlschema.isPageId)(shape.parentId)) return false;
|
|
6923
|
+
const children = this.getSortedChildIdsForParent(id);
|
|
6924
|
+
return !children.some((childId) => newShapeIdSet.has(childId));
|
|
6925
|
+
});
|
|
6926
|
+
if (shapesToKickout.length > 0) {
|
|
6927
|
+
(0, import_reparenting.kickoutOccludedShapes)(this, shapesToKickout);
|
|
6928
|
+
}
|
|
6927
6929
|
});
|
|
6928
6930
|
return this;
|
|
6929
6931
|
}
|