From 1cfbc4b2cad4f7839783a0c3ec6c25a3851f174a Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Fri, 18 Jul 2025 18:28:33 +0200 Subject: [PATCH] z-index update --- packages/element/src/binding.ts | 5 ++--- packages/element/src/zindex.ts | 14 ++++++++----- .../excalidraw/actions/actionFinalize.tsx | 21 +++++++++++++------ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/element/src/binding.ts b/packages/element/src/binding.ts index 79bdb84299..292f79f00c 100644 --- a/packages/element/src/binding.ts +++ b/packages/element/src/binding.ts @@ -55,7 +55,6 @@ import { import { aabbForElement, elementCenterPoint } from "./bounds"; import { updateElbowArrowPoints } from "./elbowArrow"; -import { moveArrowAboveBindable } from "./zindex"; import type { Scene } from "./Scene"; @@ -173,6 +172,8 @@ export const bindOrUnbindBindingElement = ( LinearElementEditor.movePoints(arrow, scene, updates); } + + return { start, end }; }; const bindOrUnbindBindingElementEdge = ( @@ -606,8 +607,6 @@ export const bindBindingElement = ( }; } - moveArrowAboveBindable(arrow, hoveredElement, scene); - scene.mutateElement(arrow, { [startOrEnd === "start" ? "startBinding" : "endBinding"]: binding, }); diff --git a/packages/element/src/zindex.ts b/packages/element/src/zindex.ts index cc89e8a1d8..78bdcb9cce 100644 --- a/packages/element/src/zindex.ts +++ b/packages/element/src/zindex.ts @@ -14,9 +14,9 @@ import type { Scene } from "./Scene"; import type { ExcalidrawArrowElement, - ExcalidrawBindableElement, ExcalidrawElement, ExcalidrawFrameLikeElement, + OrderedExcalidrawElement, } from "./types"; const isOfTargetFrame = (element: ExcalidrawElement, frameId: string) => { @@ -146,19 +146,23 @@ const getContiguousFrameRangeElements = ( export const moveArrowAboveBindable = ( arrow: ExcalidrawArrowElement, - bindable: ExcalidrawBindableElement, + bindableIds: string[], scene: Scene, -) => { +): readonly OrderedExcalidrawElement[] => { const elements = scene.getElementsIncludingDeleted(); - const bindableIdx = elements.findIndex((el) => el.id === bindable.id); + const bindableIdx = elements.findIndex((el) => bindableIds.includes(el.id)); const arrowIdx = elements.findIndex((el) => el.id === arrow.id); if (arrowIdx !== -1 && bindableIdx !== -1 && arrowIdx < bindableIdx) { const updatedElements = Array.from(elements); const arrow = updatedElements.splice(arrowIdx, 1)[0]; updatedElements.splice(bindableIdx, 0, arrow); - scene.replaceAllElements(updatedElements); + syncMovedIndices(elements, arrayToMap([arrow])); + + return updatedElements; } + + return elements; }; /** diff --git a/packages/excalidraw/actions/actionFinalize.tsx b/packages/excalidraw/actions/actionFinalize.tsx index 5fa597dc9c..ecd07300ae 100644 --- a/packages/excalidraw/actions/actionFinalize.tsx +++ b/packages/excalidraw/actions/actionFinalize.tsx @@ -6,6 +6,7 @@ import { isArrowElement, isValidPolygon, LinearElementEditor, + moveArrowAboveBindable, } from "@excalidraw/element"; import { @@ -49,6 +50,7 @@ export const actionFinalize = register({ label: "", trackEvent: false, perform: (elements, appState, data, app) => { + let newElements = elements; const { interactiveCanvas, focusContainer, scene } = app; const { event, sceneCoords } = (data as { @@ -87,13 +89,22 @@ export const actionFinalize = register({ app.scene, ); - bindOrUnbindBindingElement(element, draggedPoints, scene, appState); + const { start, end } = bindOrUnbindBindingElement( + element, + draggedPoints, + scene, + appState, + ); + const bindableIds = []; + start.element && bindableIds.push(start.element.id); + end.element && bindableIds.push(end.element.id); + newElements = moveArrowAboveBindable(element, bindableIds, scene); if (linearElementEditor !== appState.selectedLinearElement) { // `handlePointerUp()` updated the linear element instance, // so filter out this element if it is too small, // but do an update to all new elements anyway for undo/redo purposes. - let newElements = elements; + if (element && isInvisiblySmallElement(element)) { // TODO: #7348 in theory this gets recorded by the store, so the invisible elements could be restored by the undo/redo, which might be not what we would want newElements = newElements.filter((el) => el.id !== element!.id); @@ -149,7 +160,7 @@ export const actionFinalize = register({ return { elements: element.points.length < 2 || isInvisiblySmallElement(element) - ? elements.filter((el) => el.id !== element.id) + ? newElements.filter((el) => el.id !== element.id) : undefined, appState: { ...appState, @@ -161,8 +172,6 @@ export const actionFinalize = register({ } } - let newElements = elements; - if (window.document.activeElement instanceof HTMLElement) { focusContainer(); } @@ -256,7 +265,7 @@ export const actionFinalize = register({ : LinearElementEditor.getPointAtIndexGlobalCoordinates( element, -1, - arrayToMap(elements), + arrayToMap(newElements), ); const point = LinearElementEditor.pointFromAbsoluteCoords( element,