fix: Tune nested shape binding

This commit is contained in:
Mark Tolmacs
2025-09-11 17:48:56 +02:00
parent 8d7af92719
commit d73e273e63

View File

@@ -347,14 +347,18 @@ const bindingStrategyForNewSimpleArrowEndpointDragging = (
}; };
// We are hovering another element with the end point // We are hovering another element with the end point
const isNested =
hit &&
isElementInsideBBox(otherElement, getElementBounds(hit, elementsMap));
let current: BindingStrategy; let current: BindingStrategy;
if (hit) { if (hit) {
const isInsideBinding = const isInsideBinding =
globalBindMode === "inside" || globalBindMode === "skip"; globalBindMode === "inside" || globalBindMode === "skip";
current = { current = {
mode: isInsideBinding ? "inside" : "orbit", mode: isInsideBinding && !isNested ? "inside" : "orbit",
element: hit, element: hit,
focusPoint: isInsideBinding focusPoint:
isInsideBinding || isNested
? point ? point
: snapToCenter(hit, elementsMap, point), : snapToCenter(hit, elementsMap, point),
}; };
@@ -403,20 +407,22 @@ const bindingStrategyForSimpleArrowEndpointDragging = (
const isMultiPoint = arrow.points.length > 2; const isMultiPoint = arrow.points.length > 2;
const hit = getHoveredElementForBinding(point, elements, elementsMap); const hit = getHoveredElementForBinding(point, elements, elementsMap);
const isNested = oppositeBinding const isOverlapping = oppositeBinding
? getAllHoveredElementAtPoint(point, elements, elementsMap).some( ? getAllHoveredElementAtPoint(point, elements, elementsMap).some(
(el) => el.id === oppositeBinding.elementId, (el) => el.id === oppositeBinding.elementId,
) )
: false; : false;
const oppositeElement = const oppositeElement = oppositeBinding
isNested && oppositeBinding ? (elementsMap.get(oppositeBinding.elementId) as ExcalidrawBindableElement)
? (elementsMap.get(
oppositeBinding.elementId,
) as ExcalidrawBindableElement)
: null; : null;
const otherIsTransparent = oppositeElement const otherIsTransparent =
isOverlapping && oppositeElement
? isTransparent(oppositeElement.backgroundColor) ? isTransparent(oppositeElement.backgroundColor)
: false; : false;
const isNested =
hit &&
oppositeElement &&
isElementInsideBBox(oppositeElement, getElementBounds(hit, elementsMap));
// If the global bind mode is in free binding mode, just bind // If the global bind mode is in free binding mode, just bind
// where the pointer is and keep the other end intact // where the pointer is and keep the other end intact
@@ -424,7 +430,7 @@ const bindingStrategyForSimpleArrowEndpointDragging = (
current = hit current = hit
? { ? {
element: element:
!isNested || !oppositeElement || otherIsTransparent !isOverlapping || !oppositeElement || otherIsTransparent
? hit ? hit
: oppositeElement, : oppositeElement,
focusPoint: point, focusPoint: point,
@@ -464,7 +470,7 @@ const bindingStrategyForSimpleArrowEndpointDragging = (
// eslint-disable-next-line no-else-return // eslint-disable-next-line no-else-return
else { else {
// Handle the nested element case // Handle the nested element case
if (isNested && oppositeElement && !otherIsTransparent) { if (isOverlapping && oppositeElement && !otherIsTransparent) {
current = { current = {
element: oppositeElement, element: oppositeElement,
mode: "inside", mode: "inside",
@@ -474,7 +480,7 @@ const bindingStrategyForSimpleArrowEndpointDragging = (
current = { current = {
element: hit, element: hit,
mode: "orbit", mode: "orbit",
focusPoint: snapToCenter(hit, elementsMap, point), focusPoint: isNested ? point : snapToCenter(hit, elementsMap, point),
}; };
} }