fix: Allow already inside bound arrows to continue inside binding

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs
2025-09-29 09:51:47 +02:00
parent dbb0a39b22
commit 2a4f7e94b1
2 changed files with 48 additions and 1 deletions

View File

@@ -390,6 +390,7 @@ const bindingStrategyForNewSimpleArrowEndpointDragging = (
const bindingStrategyForSimpleArrowEndpointDragging = (
point: GlobalPoint,
currentBinding: FixedPointBinding | null,
oppositeBinding: FixedPointBinding | null,
elementsMap: NonDeletedSceneElementsMap,
elements: readonly Ordered<NonDeletedExcalidrawElement>[],
@@ -441,6 +442,17 @@ const bindingStrategyForSimpleArrowEndpointDragging = (
return { current: { mode: null }, other };
}
// Already inside binding over the same hit element should remain inside bound
if (
hit.id === currentBinding?.elementId &&
currentBinding.mode === "inside"
) {
return {
current: { mode: "inside", focusPoint: point, element: hit },
other,
};
}
// The dragged point is inside the hovered bindable element
if (oppositeBinding) {
// The opposite binding is on the same element
@@ -579,6 +591,7 @@ export const getBindingStrategyForDraggingBindingElementEndpoints = (
const { current, other } = bindingStrategyForSimpleArrowEndpointDragging(
globalPoint,
arrow.startBinding,
arrow.endBinding,
elementsMap,
elements,
@@ -600,6 +613,7 @@ export const getBindingStrategyForDraggingBindingElementEndpoints = (
);
const { current, other } = bindingStrategyForSimpleArrowEndpointDragging(
globalPoint,
arrow.endBinding,
arrow.startBinding,
elementsMap,
elements,

View File

@@ -1108,6 +1108,38 @@ class App extends React.Component<AppProps, AppState> {
);
}
const startDragged =
this.state.selectedLinearElement?.selectedPointsIndices?.includes(0);
const endDragged =
this.state.selectedLinearElement?.selectedPointsIndices?.includes(
arrow.points.length - 1,
);
const currentBinding = startDragged
? "startBinding"
: endDragged
? "endBinding"
: null;
const isAlreadyInsideBindingToSameElement = startDragged
? arrow.startBinding?.mode === "inside" &&
arrow.startBinding?.elementId === hoveredElement?.id
: endDragged
? arrow.endBinding?.mode === "inside" &&
arrow.endBinding?.elementId === hoveredElement?.id
: false;
if (
currentBinding &&
arrow[currentBinding]?.mode === "inside" &&
hoveredElement?.id !== arrow[currentBinding]?.elementId
) {
// Update binding out of place to orbit mode
this.scene.mutateElement(arrow, {
[currentBinding]: {
...arrow[currentBinding],
mode: "orbit",
},
});
}
if (
!hoveredElement ||
(this.previousHoveredBindableElement &&
@@ -1131,7 +1163,8 @@ class App extends React.Component<AppProps, AppState> {
this.previousHoveredBindableElement = null;
} else if (
!this.bindModeHandler &&
(!this.state.newElement || !arrow.startBinding || isOverlapping)
(!this.state.newElement || !arrow.startBinding || isOverlapping) &&
!isAlreadyInsideBindingToSameElement
) {
// We are hovering a bindable element
this.bindModeHandler = setTimeout(effector, BIND_MODE_TIMEOUT);