diff --git a/packages/element/src/arrows/focus.ts b/packages/element/src/arrows/focus.ts index fa8018adbe..8a70d3dba1 100644 --- a/packages/element/src/arrows/focus.ts +++ b/packages/element/src/arrows/focus.ts @@ -27,6 +27,7 @@ import type { ElementsMap, ExcalidrawArrowElement, ExcalidrawBindableElement, + FixedPointBinding, NonDeletedSceneElementsMap, PointsPositionUpdates, } from "../types"; @@ -110,10 +111,17 @@ const focusPointUpdate = ( ) => { const pointUpdates = new Map(); + const originalAdjacentBinding = + appState.selectedLinearElement?.initialState + .arrowOtherEndpointInitialBinding; const bindingField = isStartBinding ? "startBinding" : "endBinding"; const adjacentBindingField = isStartBinding ? "endBinding" : "startBinding"; let currentBinding = arrow[bindingField]; - let adjacentBinding = arrow[adjacentBindingField]; + let adjacentBinding = + originalAdjacentBinding?.mode === "orbit" && + arrow[adjacentBindingField]?.mode === "inside" + ? originalAdjacentBinding + : arrow[adjacentBindingField]; // Update the dragged focus point related end if (currentBinding && bindableElement) { @@ -339,6 +347,7 @@ export const handleFocusPointPointerDown = ( ): { hitFocusPoint: "start" | "end" | null; pointerOffset: { x: number; y: number }; + arrowOtherEndpointInitialBinding: FixedPointBinding | null; } => { const pointerPos = pointFrom( pointerDownState.origin.x, @@ -376,6 +385,7 @@ export const handleFocusPointPointerDown = ( x: pointerPos[0] - focusPoint[0], y: pointerPos[1] - focusPoint[1], }, + arrowOtherEndpointInitialBinding: arrow.endBinding, }; } } @@ -411,6 +421,7 @@ export const handleFocusPointPointerDown = ( x: pointerPos[0] - focusPoint[0], y: pointerPos[1] - focusPoint[1], }, + arrowOtherEndpointInitialBinding: arrow.startBinding, }; } } @@ -419,13 +430,14 @@ export const handleFocusPointPointerDown = ( return { hitFocusPoint: null, pointerOffset: { x: 0, y: 0 }, + arrowOtherEndpointInitialBinding: null, }; }; export const handleFocusPointPointerUp = ( linearElementEditor: LinearElementEditor, scene: Scene, -) => { +): { arrowOtherEndpointInitialBinding: FixedPointBinding | null } => { invariant( linearElementEditor.draggedFocusPointBinding, "Must have a dragged focus point at pointer release", @@ -483,6 +495,10 @@ export const handleFocusPointPointerUp = ( ], }); } + + return { + arrowOtherEndpointInitialBinding: null, + }; }; export const handleFocusPointHover = ( diff --git a/packages/element/src/linearElementEditor.ts b/packages/element/src/linearElementEditor.ts index 781825bb52..8d237b5b40 100644 --- a/packages/element/src/linearElementEditor.ts +++ b/packages/element/src/linearElementEditor.ts @@ -1088,10 +1088,7 @@ export class LinearElementEditor { !!app.state.newElement && (app.state.bindMode === "inside" || app.state.bindMode === "skip"), altFocusPoint: null, - arrowOtherEndpointInitialBinding: - linearElementEditor.selectedPointsIndices?.includes(0) - ? element.startBinding - : element.endBinding, + arrowOtherEndpointInitialBinding: element.startBinding, }, selectedPointsIndices: [element.points.length - 1], lastUncommittedPoint: null, @@ -1154,10 +1151,9 @@ export class LinearElementEditor { !!app.state.newElement && (app.state.bindMode === "inside" || app.state.bindMode === "skip"), altFocusPoint: null, - arrowOtherEndpointInitialBinding: - linearElementEditor.selectedPointsIndices?.includes(0) - ? element.startBinding - : element.endBinding, + arrowOtherEndpointInitialBinding: nextSelectedPointsIndices?.includes(0) + ? element.endBinding + : element.startBinding, }, selectedPointsIndices: nextSelectedPointsIndices, pointerOffset: targetPoint diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 4a79e93baf..24056ebcca 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -8396,13 +8396,16 @@ class App extends React.Component { ) as any; if (arrow && isBindingElement(arrow)) { - const { hitFocusPoint, pointerOffset } = - handleFocusPointPointerDown( - arrow, - pointerDownState, - elementsMap, - this.state, - ); + const { + hitFocusPoint, + pointerOffset, + arrowOtherEndpointInitialBinding, + } = handleFocusPointPointerDown( + arrow, + pointerDownState, + elementsMap, + this.state, + ); // If focus point is hit, update state and prevent element selection if (hitFocusPoint) { @@ -8412,6 +8415,10 @@ class App extends React.Component { hoveredFocusPointBinding: hitFocusPoint, draggedFocusPointBinding: hitFocusPoint, pointerOffset, + initialState: { + ...linearElementEditor.initialState, + arrowOtherEndpointInitialBinding, + }, }, }); return false; @@ -10524,14 +10531,19 @@ class App extends React.Component { } if (this.state.selectedLinearElement.draggedFocusPointBinding) { - handleFocusPointPointerUp( - this.state.selectedLinearElement, - this.scene, - ); + const { arrowOtherEndpointInitialBinding } = + handleFocusPointPointerUp( + this.state.selectedLinearElement, + this.scene, + ); this.setState({ selectedLinearElement: { ...this.state.selectedLinearElement, draggedFocusPointBinding: null, + initialState: { + ...this.state.selectedLinearElement.initialState, + arrowOtherEndpointInitialBinding, + }, }, }); } else if (