fix: Elbow arrow fixes

This commit is contained in:
Mark Tolmacs
2025-08-13 17:55:57 +02:00
parent 7afaad5111
commit 81a26b67de
3 changed files with 35 additions and 50 deletions

View File

@@ -145,6 +145,7 @@ export const bindOrUnbindBindingElement = (
...opts,
},
);
bindOrUnbindBindingElementEdge(arrow, start, "start", scene);
bindOrUnbindBindingElementEdge(arrow, end, "end", scene);
if (!isElbowArrow(arrow) && (start.focusPoint || end.focusPoint)) {

View File

@@ -155,8 +155,8 @@ describe("elbow arrow routing", () => {
expect(arrow.width).toEqual(90);
expect(arrow.height).toEqual(200);
});
it("can generate proper points for bound elbow arrow", () => {
const scene = new Scene();
const rectangle1 = API.createElement({
type: "rectangle",
x: -150,
@@ -180,17 +180,15 @@ describe("elbow arrow routing", () => {
height: 200,
points: [pointFrom(0, 0), pointFrom(90, 200)],
}) as ExcalidrawElbowArrowElement;
scene.insertElement(rectangle1);
scene.insertElement(rectangle2);
scene.insertElement(arrow);
API.setElements([rectangle1, rectangle2, arrow]);
bindBindingElement(arrow, rectangle1, "orbit", "start", scene);
bindBindingElement(arrow, rectangle2, "orbit", "end", scene);
bindBindingElement(arrow, rectangle1, "orbit", "start", h.scene);
bindBindingElement(arrow, rectangle2, "orbit", "end", h.scene);
expect(arrow.startBinding).not.toBe(null);
expect(arrow.endBinding).not.toBe(null);
h.app.scene.mutateElement(arrow, {
h.scene.mutateElement(arrow, {
points: [pointFrom<LocalPoint>(0, 0), pointFrom<LocalPoint>(90, 200)],
});

View File

@@ -769,6 +769,27 @@ class App extends React.Component<AppProps, AppState> {
this.actionManager.registerAction(createRedoAction(this.history));
}
// setState: React.Component<AppProps, AppState>["setState"] = (
// state,
// callback?,
// ) => {
// let newState: Parameters<typeof this.setState>[0] = null;
// if (typeof state === "function") {
// newState = state(this.state, this.props) as Pick<
// AppState,
// keyof AppState
// >;
// } else {
// newState = state as Pick<AppState, keyof AppState>;
// }
// if (newState && Object.hasOwn(newState, "selectedLinearElement")) {
// console.trace(!!newState.selectedLinearElement);
// }
// super.setState(newState, callback);
// };
updateEditorAtom = <Value, Args extends unknown[], Result>(
atom: WritableAtom<Value, Args, Result>,
...args: Args
@@ -2519,47 +2540,6 @@ class App extends React.Component<AppProps, AppState> {
return this.setState(...args);
},
},
watchState: {
configurable: true,
value: (
callback:
| ((
prevState: Parameters<typeof setState>,
nextState: Parameters<typeof setState> | null,
) => void)
| undefined,
) => {
if (callback) {
(window as any).__originalSetState = this.setState;
this.setState = new Proxy(this.setState, {
apply: (target, thisArg, [state, cb]) => {
const prevState = thisArg.state;
let newState: Parameters<typeof setState> | null = null;
// Log state change for debugging
if (typeof state === "function") {
newState = state(prevState, this.props);
} else if (state) {
newState = state;
}
try {
callback(prevState, newState);
} catch (error) {
console.warn("Error in watchState callback:", error);
}
if (newState) {
target.bind(thisArg)(newState as any, cb);
}
},
});
} else if ((window as any).__originalSetState) {
this.setState = (window as any).__originalSetState;
delete (window as any).__originalSetState;
}
},
},
app: {
configurable: true,
value: this,
@@ -8160,7 +8140,13 @@ class App extends React.Component<AppProps, AppState> {
lastCommittedPoint:
multiElement.points[multiElement.points.length - 1],
});
this.actionManager.executeAction(actionFinalize);
this.actionManager.executeAction(actionFinalize, "ui", {
event: event.nativeEvent,
sceneCoords: {
x: pointerDownState.origin.x,
y: pointerDownState.origin.y,
},
});
return;
}
@@ -8347,7 +8333,7 @@ class App extends React.Component<AppProps, AppState> {
this.setState((prevState) => {
let linearElementEditor = null;
let nextSelectedElementIds = prevState.selectedElementIds;
if (isSimpleArrow(element)) {
if (isBindingElement(element)) {
const linearElement = new LinearElementEditor(
element,
this.scene.getNonDeletedElementsMap(),