fix: Fully nested shapes

This commit is contained in:
Mark Tolmacs
2025-09-11 16:39:41 +02:00
parent 9ac0f8231c
commit 8d7af92719

View File

@@ -1,5 +1,6 @@
import { KEYS, arrayToMap, invariant, isTransparent } from "@excalidraw/common"; import { KEYS, arrayToMap, invariant, isTransparent } from "@excalidraw/common";
import { isElementInsideBBox } from "@excalidraw/utils";
import { import {
lineSegment, lineSegment,
pointFrom, pointFrom,
@@ -21,11 +22,7 @@ import type { AppState } from "@excalidraw/excalidraw/types";
import type { MapEntry, Mutable } from "@excalidraw/common/utility-types"; import type { MapEntry, Mutable } from "@excalidraw/common/utility-types";
import { import { getCenterForBounds, getElementBounds } from "./bounds";
doBoundsIntersect,
getCenterForBounds,
getElementBounds,
} from "./bounds";
import { import {
getAllHoveredElementAtPoint, getAllHoveredElementAtPoint,
getHoveredElementForBinding, getHoveredElementForBinding,
@@ -763,13 +760,6 @@ export const updateBoundElements = (
: elementsMap.get(element.endBinding.elementId) : elementsMap.get(element.endBinding.elementId)
: null; : null;
let startBounds: Bounds | null = null;
let endBounds: Bounds | null = null;
if (startBindingElement && endBindingElement) {
startBounds = getElementBounds(startBindingElement, elementsMap);
endBounds = getElementBounds(endBindingElement, elementsMap);
}
// `linearElement` is being moved/scaled already, just update the binding // `linearElement` is being moved/scaled already, just update the binding
if (simultaneouslyUpdatedElementIds.has(element.id)) { if (simultaneouslyUpdatedElementIds.has(element.id)) {
return; return;
@@ -784,11 +774,10 @@ export const updateBoundElements = (
isBindableElement(bindableElement) && isBindableElement(bindableElement) &&
(bindingProp === "startBinding" || bindingProp === "endBinding") && (bindingProp === "startBinding" || bindingProp === "endBinding") &&
(changedElement.id === element[bindingProp]?.elementId || (changedElement.id === element[bindingProp]?.elementId ||
(changedElement.id === changedElement.id ===
element[ element[
bindingProp === "startBinding" ? "endBinding" : "startBinding" bindingProp === "startBinding" ? "endBinding" : "startBinding"
]?.elementId && ]?.elementId)
!doBoundsIntersect(startBounds, endBounds)))
) { ) {
const point = updateBoundPoint( const point = updateBoundPoint(
element, element,
@@ -1252,39 +1241,50 @@ export const updateBoundPoint = (
const pointIndex = const pointIndex =
startOrEnd === "startBinding" ? 0 : arrow.points.length - 1; startOrEnd === "startBinding" ? 0 : arrow.points.length - 1;
const otherBinding =
startOrEnd === "startBinding" ? arrow.endBinding : arrow.startBinding;
const otherBindableElement =
otherBinding &&
(elementsMap.get(otherBinding.elementId)! as ExcalidrawBindableElement);
const bounds = getElementBounds(bindableElement, elementsMap);
const isNested =
otherBindableElement && isElementInsideBBox(otherBindableElement, bounds);
const maybeOutlineGlobal = const maybeOutlineGlobal =
binding.mode === "orbit" && bindableElement binding.mode === "orbit" && bindableElement
? bindPointToSnapToElementOutline( ? isNested
{ ? global
...arrow, : bindPointToSnapToElementOutline(
x: pointIndex === 0 ? global[0] : arrow.x, {
y: pointIndex === 0 ? global[1] : arrow.y, ...arrow,
points: x: pointIndex === 0 ? global[0] : arrow.x,
pointIndex === 0 y: pointIndex === 0 ? global[1] : arrow.y,
? [ points:
pointFrom<LocalPoint>(0, 0), pointIndex === 0
...arrow.points ? [
.slice(1) pointFrom<LocalPoint>(0, 0),
.map((p) => ...arrow.points
pointFrom<LocalPoint>( .slice(1)
p[0] - (global[0] - arrow.x), .map((p) =>
p[1] - (global[1] - arrow.y), pointFrom<LocalPoint>(
p[0] - (global[0] - arrow.x),
p[1] - (global[1] - arrow.y),
),
), ),
]
: [
...arrow.points.slice(0, -1),
pointFrom<LocalPoint>(
global[0] - arrow.x,
global[1] - arrow.y,
), ),
] ],
: [ },
...arrow.points.slice(0, -1), bindableElement,
pointFrom<LocalPoint>( pointIndex === 0 ? "start" : "end",
global[0] - arrow.x, elementsMap,
global[1] - arrow.y, customIntersector,
), )
],
},
bindableElement,
pointIndex === 0 ? "start" : "end",
elementsMap,
customIntersector,
)
: global; : global;
return LinearElementEditor.pointFromAbsoluteCoords( return LinearElementEditor.pointFromAbsoluteCoords(