fix: Bindings at partially overlapping binding areas (#9536)
This commit is contained in:
parent
958597dfaa
commit
0a19c93509
@ -384,6 +384,48 @@ export const getSuggestedBindingsForArrows = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const maybeSuggestBindingsForLinearElementAtCoords = (
|
||||||
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
|
/** scene coords */
|
||||||
|
pointerCoords: {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}[],
|
||||||
|
scene: Scene,
|
||||||
|
zoom: AppState["zoom"],
|
||||||
|
// During line creation the start binding hasn't been written yet
|
||||||
|
// into `linearElement`
|
||||||
|
oppositeBindingBoundElement?: ExcalidrawBindableElement | null,
|
||||||
|
): ExcalidrawBindableElement[] =>
|
||||||
|
Array.from(
|
||||||
|
pointerCoords.reduce(
|
||||||
|
(acc: Set<NonDeleted<ExcalidrawBindableElement>>, coords) => {
|
||||||
|
const hoveredBindableElement = getHoveredElementForBinding(
|
||||||
|
coords,
|
||||||
|
scene.getNonDeletedElements(),
|
||||||
|
scene.getNonDeletedElementsMap(),
|
||||||
|
zoom,
|
||||||
|
isElbowArrow(linearElement),
|
||||||
|
isElbowArrow(linearElement),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
hoveredBindableElement != null &&
|
||||||
|
!isLinearElementSimpleAndAlreadyBound(
|
||||||
|
linearElement,
|
||||||
|
oppositeBindingBoundElement?.id,
|
||||||
|
hoveredBindableElement,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
acc.add(hoveredBindableElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
new Set() as Set<NonDeleted<ExcalidrawBindableElement>>,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
export const maybeBindLinearElement = (
|
export const maybeBindLinearElement = (
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
@ -513,7 +555,7 @@ export const isLinearElementSimpleAndAlreadyBound = (
|
|||||||
|
|
||||||
const isLinearElementSimple = (
|
const isLinearElementSimple = (
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
): boolean => linearElement.points.length < 3;
|
): boolean => linearElement.points.length < 3 && !isElbowArrow(linearElement);
|
||||||
|
|
||||||
const unbindLinearElement = (
|
const unbindLinearElement = (
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
getGridPoint,
|
getGridPoint,
|
||||||
invariant,
|
invariant,
|
||||||
tupleToCoors,
|
tupleToCoors,
|
||||||
|
viewportCoordsToSceneCoords,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -45,6 +46,7 @@ import {
|
|||||||
bindOrUnbindLinearElement,
|
bindOrUnbindLinearElement,
|
||||||
getHoveredElementForBinding,
|
getHoveredElementForBinding,
|
||||||
isBindingEnabled,
|
isBindingEnabled,
|
||||||
|
maybeSuggestBindingsForLinearElementAtCoords,
|
||||||
} from "./binding";
|
} from "./binding";
|
||||||
import {
|
import {
|
||||||
getElementAbsoluteCoords,
|
getElementAbsoluteCoords,
|
||||||
@ -275,18 +277,13 @@ export class LinearElementEditor {
|
|||||||
app: AppClassProperties,
|
app: AppClassProperties,
|
||||||
scenePointerX: number,
|
scenePointerX: number,
|
||||||
scenePointerY: number,
|
scenePointerY: number,
|
||||||
maybeSuggestBinding: (
|
|
||||||
element: NonDeleted<ExcalidrawLinearElement>,
|
|
||||||
pointSceneCoords: { x: number; y: number }[],
|
|
||||||
) => void,
|
|
||||||
linearElementEditor: LinearElementEditor,
|
linearElementEditor: LinearElementEditor,
|
||||||
scene: Scene,
|
): Pick<AppState, keyof AppState> | null {
|
||||||
): LinearElementEditor | null {
|
|
||||||
if (!linearElementEditor) {
|
if (!linearElementEditor) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { elementId } = linearElementEditor;
|
const { elementId } = linearElementEditor;
|
||||||
const elementsMap = scene.getNonDeletedElementsMap();
|
const elementsMap = app.scene.getNonDeletedElementsMap();
|
||||||
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
||||||
let customLineAngle = linearElementEditor.customLineAngle;
|
let customLineAngle = linearElementEditor.customLineAngle;
|
||||||
if (!element) {
|
if (!element) {
|
||||||
@ -347,7 +344,7 @@ export class LinearElementEditor {
|
|||||||
|
|
||||||
LinearElementEditor.movePoints(
|
LinearElementEditor.movePoints(
|
||||||
element,
|
element,
|
||||||
scene,
|
app.scene,
|
||||||
new Map([
|
new Map([
|
||||||
[
|
[
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
@ -375,7 +372,7 @@ export class LinearElementEditor {
|
|||||||
|
|
||||||
LinearElementEditor.movePoints(
|
LinearElementEditor.movePoints(
|
||||||
element,
|
element,
|
||||||
scene,
|
app.scene,
|
||||||
new Map(
|
new Map(
|
||||||
selectedPointsIndices.map((pointIndex) => {
|
selectedPointsIndices.map((pointIndex) => {
|
||||||
const newPointPosition: LocalPoint =
|
const newPointPosition: LocalPoint =
|
||||||
@ -407,46 +404,59 @@ export class LinearElementEditor {
|
|||||||
|
|
||||||
const boundTextElement = getBoundTextElement(element, elementsMap);
|
const boundTextElement = getBoundTextElement(element, elementsMap);
|
||||||
if (boundTextElement) {
|
if (boundTextElement) {
|
||||||
handleBindTextResize(element, scene, false);
|
handleBindTextResize(element, app.scene, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// suggest bindings for first and last point if selected
|
// suggest bindings for first and last point if selected
|
||||||
|
let suggestedBindings: ExcalidrawBindableElement[] = [];
|
||||||
if (isBindingElement(element, false)) {
|
if (isBindingElement(element, false)) {
|
||||||
|
const firstSelectedIndex = selectedPointsIndices[0] === 0;
|
||||||
|
const lastSelectedIndex =
|
||||||
|
selectedPointsIndices[selectedPointsIndices.length - 1] ===
|
||||||
|
element.points.length - 1;
|
||||||
const coords: { x: number; y: number }[] = [];
|
const coords: { x: number; y: number }[] = [];
|
||||||
|
|
||||||
const firstSelectedIndex = selectedPointsIndices[0];
|
if (!firstSelectedIndex !== !lastSelectedIndex) {
|
||||||
if (firstSelectedIndex === 0) {
|
coords.push({ x: scenePointerX, y: scenePointerY });
|
||||||
coords.push(
|
} else {
|
||||||
tupleToCoors(
|
if (firstSelectedIndex) {
|
||||||
LinearElementEditor.getPointGlobalCoordinates(
|
coords.push(
|
||||||
element,
|
tupleToCoors(
|
||||||
element.points[0],
|
LinearElementEditor.getPointGlobalCoordinates(
|
||||||
elementsMap,
|
element,
|
||||||
|
element.points[0],
|
||||||
|
elementsMap,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const lastSelectedIndex =
|
if (lastSelectedIndex) {
|
||||||
selectedPointsIndices[selectedPointsIndices.length - 1];
|
coords.push(
|
||||||
if (lastSelectedIndex === element.points.length - 1) {
|
tupleToCoors(
|
||||||
coords.push(
|
LinearElementEditor.getPointGlobalCoordinates(
|
||||||
tupleToCoors(
|
element,
|
||||||
LinearElementEditor.getPointGlobalCoordinates(
|
element.points[
|
||||||
element,
|
selectedPointsIndices[selectedPointsIndices.length - 1]
|
||||||
element.points[lastSelectedIndex],
|
],
|
||||||
elementsMap,
|
elementsMap,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coords.length) {
|
if (coords.length) {
|
||||||
maybeSuggestBinding(element, coords);
|
suggestedBindings = maybeSuggestBindingsForLinearElementAtCoords(
|
||||||
|
element,
|
||||||
|
coords,
|
||||||
|
app.scene,
|
||||||
|
app.state.zoom,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const newLinearElementEditor = {
|
||||||
...linearElementEditor,
|
...linearElementEditor,
|
||||||
selectedPointsIndices,
|
selectedPointsIndices,
|
||||||
segmentMidPointHoveredCoords:
|
segmentMidPointHoveredCoords:
|
||||||
@ -466,6 +476,15 @@ export class LinearElementEditor {
|
|||||||
isDragging: true,
|
isDragging: true,
|
||||||
customLineAngle,
|
customLineAngle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...app.state,
|
||||||
|
editingLinearElement: app.state.editingLinearElement
|
||||||
|
? newLinearElementEditor
|
||||||
|
: null,
|
||||||
|
selectedLinearElement: newLinearElementEditor,
|
||||||
|
suggestedBindings,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -479,6 +498,7 @@ export class LinearElementEditor {
|
|||||||
): LinearElementEditor {
|
): LinearElementEditor {
|
||||||
const elementsMap = scene.getNonDeletedElementsMap();
|
const elementsMap = scene.getNonDeletedElementsMap();
|
||||||
const elements = scene.getNonDeletedElements();
|
const elements = scene.getNonDeletedElements();
|
||||||
|
const pointerCoords = viewportCoordsToSceneCoords(event, appState);
|
||||||
|
|
||||||
const { elementId, selectedPointsIndices, isDragging, pointerDownState } =
|
const { elementId, selectedPointsIndices, isDragging, pointerDownState } =
|
||||||
editingLinearElement;
|
editingLinearElement;
|
||||||
@ -534,13 +554,15 @@ export class LinearElementEditor {
|
|||||||
|
|
||||||
const bindingElement = isBindingEnabled(appState)
|
const bindingElement = isBindingEnabled(appState)
|
||||||
? getHoveredElementForBinding(
|
? getHoveredElementForBinding(
|
||||||
tupleToCoors(
|
(selectedPointsIndices?.length ?? 0) > 1
|
||||||
LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
? tupleToCoors(
|
||||||
element,
|
LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||||
selectedPoint!,
|
element,
|
||||||
elementsMap,
|
selectedPoint!,
|
||||||
),
|
elementsMap,
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
: pointerCoords,
|
||||||
elements,
|
elements,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
appState.zoom,
|
appState.zoom,
|
||||||
|
@ -14,7 +14,12 @@ import {
|
|||||||
isLineElement,
|
isLineElement,
|
||||||
} from "@excalidraw/element";
|
} from "@excalidraw/element";
|
||||||
|
|
||||||
import { KEYS, arrayToMap, updateActiveTool } from "@excalidraw/common";
|
import {
|
||||||
|
KEYS,
|
||||||
|
arrayToMap,
|
||||||
|
tupleToCoors,
|
||||||
|
updateActiveTool,
|
||||||
|
} from "@excalidraw/common";
|
||||||
import { isPathALoop } from "@excalidraw/element";
|
import { isPathALoop } from "@excalidraw/element";
|
||||||
|
|
||||||
import { isInvisiblySmallElement } from "@excalidraw/element";
|
import { isInvisiblySmallElement } from "@excalidraw/element";
|
||||||
@ -43,12 +48,16 @@ export const actionFinalize = register({
|
|||||||
trackEvent: false,
|
trackEvent: false,
|
||||||
perform: (elements, appState, data, app) => {
|
perform: (elements, appState, data, app) => {
|
||||||
const { interactiveCanvas, focusContainer, scene } = app;
|
const { interactiveCanvas, focusContainer, scene } = app;
|
||||||
|
const { event, sceneCoords } =
|
||||||
|
(data as {
|
||||||
|
event?: PointerEvent;
|
||||||
|
sceneCoords?: { x: number; y: number };
|
||||||
|
}) ?? {};
|
||||||
const elementsMap = scene.getNonDeletedElementsMap();
|
const elementsMap = scene.getNonDeletedElementsMap();
|
||||||
|
|
||||||
if (data?.event && appState.selectedLinearElement) {
|
if (event && appState.selectedLinearElement) {
|
||||||
const linearElementEditor = LinearElementEditor.handlePointerUp(
|
const linearElementEditor = LinearElementEditor.handlePointerUp(
|
||||||
data.event,
|
event,
|
||||||
appState.selectedLinearElement,
|
appState.selectedLinearElement,
|
||||||
appState,
|
appState,
|
||||||
app.scene,
|
app.scene,
|
||||||
@ -204,12 +213,17 @@ export const actionFinalize = register({
|
|||||||
element.points.length > 1 &&
|
element.points.length > 1 &&
|
||||||
isBindingEnabled(appState)
|
isBindingEnabled(appState)
|
||||||
) {
|
) {
|
||||||
const [x, y] = LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
const coords =
|
||||||
element,
|
sceneCoords ??
|
||||||
-1,
|
tupleToCoors(
|
||||||
arrayToMap(elements),
|
LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||||
);
|
element,
|
||||||
maybeBindLinearElement(element, appState, { x, y }, scene);
|
-1,
|
||||||
|
arrayToMap(elements),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
maybeBindLinearElement(element, appState, coords, scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,12 +105,12 @@ import {
|
|||||||
import {
|
import {
|
||||||
getObservedAppState,
|
getObservedAppState,
|
||||||
getCommonBounds,
|
getCommonBounds,
|
||||||
|
maybeSuggestBindingsForLinearElementAtCoords,
|
||||||
getElementAbsoluteCoords,
|
getElementAbsoluteCoords,
|
||||||
bindOrUnbindLinearElements,
|
bindOrUnbindLinearElements,
|
||||||
fixBindingsAfterDeletion,
|
fixBindingsAfterDeletion,
|
||||||
getHoveredElementForBinding,
|
getHoveredElementForBinding,
|
||||||
isBindingEnabled,
|
isBindingEnabled,
|
||||||
isLinearElementSimpleAndAlreadyBound,
|
|
||||||
shouldEnableBindingForPointerEvent,
|
shouldEnableBindingForPointerEvent,
|
||||||
updateBoundElements,
|
updateBoundElements,
|
||||||
getSuggestedBindingsForArrows,
|
getSuggestedBindingsForArrows,
|
||||||
@ -237,7 +237,6 @@ import {
|
|||||||
import type { LocalPoint, Radians } from "@excalidraw/math";
|
import type { LocalPoint, Radians } from "@excalidraw/math";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ExcalidrawBindableElement,
|
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
ExcalidrawFreeDrawElement,
|
ExcalidrawFreeDrawElement,
|
||||||
ExcalidrawGenericElement,
|
ExcalidrawGenericElement,
|
||||||
@ -5883,11 +5882,15 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
// and point
|
// and point
|
||||||
const { newElement } = this.state;
|
const { newElement } = this.state;
|
||||||
if (isBindingElement(newElement, false)) {
|
if (isBindingElement(newElement, false)) {
|
||||||
this.maybeSuggestBindingsForLinearElementAtCoords(
|
this.setState({
|
||||||
newElement,
|
suggestedBindings: maybeSuggestBindingsForLinearElementAtCoords(
|
||||||
[scenePointer],
|
newElement,
|
||||||
this.state.startBoundElement,
|
[scenePointer],
|
||||||
);
|
this.scene,
|
||||||
|
this.state.zoom,
|
||||||
|
this.state.startBoundElement,
|
||||||
|
),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.maybeSuggestBindingAtCursor(scenePointer, false);
|
this.maybeSuggestBindingAtCursor(scenePointer, false);
|
||||||
}
|
}
|
||||||
@ -8217,31 +8220,19 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newLinearElementEditor = LinearElementEditor.handlePointDragging(
|
const newState = LinearElementEditor.handlePointDragging(
|
||||||
event,
|
event,
|
||||||
this,
|
this,
|
||||||
pointerCoords.x,
|
pointerCoords.x,
|
||||||
pointerCoords.y,
|
pointerCoords.y,
|
||||||
(element, pointsSceneCoords) => {
|
|
||||||
this.maybeSuggestBindingsForLinearElementAtCoords(
|
|
||||||
element,
|
|
||||||
pointsSceneCoords,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
linearElementEditor,
|
linearElementEditor,
|
||||||
this.scene,
|
|
||||||
);
|
);
|
||||||
if (newLinearElementEditor) {
|
if (newState) {
|
||||||
pointerDownState.lastCoords.x = pointerCoords.x;
|
pointerDownState.lastCoords.x = pointerCoords.x;
|
||||||
pointerDownState.lastCoords.y = pointerCoords.y;
|
pointerDownState.lastCoords.y = pointerCoords.y;
|
||||||
pointerDownState.drag.hasOccurred = true;
|
pointerDownState.drag.hasOccurred = true;
|
||||||
|
|
||||||
this.setState({
|
this.setState(newState);
|
||||||
editingLinearElement: this.state.editingLinearElement
|
|
||||||
? newLinearElementEditor
|
|
||||||
: null,
|
|
||||||
selectedLinearElement: newLinearElementEditor,
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -8720,11 +8711,15 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
|
|
||||||
if (isBindingElement(newElement, false)) {
|
if (isBindingElement(newElement, false)) {
|
||||||
// When creating a linear element by dragging
|
// When creating a linear element by dragging
|
||||||
this.maybeSuggestBindingsForLinearElementAtCoords(
|
this.setState({
|
||||||
newElement,
|
suggestedBindings: maybeSuggestBindingsForLinearElementAtCoords(
|
||||||
[pointerCoords],
|
newElement,
|
||||||
this.state.startBoundElement,
|
[pointerCoords],
|
||||||
);
|
this.scene,
|
||||||
|
this.state.zoom,
|
||||||
|
this.state.startBoundElement,
|
||||||
|
),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pointerDownState.lastCoords.x = pointerCoords.x;
|
pointerDownState.lastCoords.x = pointerCoords.x;
|
||||||
@ -8919,16 +8914,17 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
|
|
||||||
const hitElements = pointerDownState.hit.allHitElements;
|
const hitElements = pointerDownState.hit.allHitElements;
|
||||||
|
|
||||||
|
const sceneCoords = viewportCoordsToSceneCoords(
|
||||||
|
{ clientX: childEvent.clientX, clientY: childEvent.clientY },
|
||||||
|
this.state,
|
||||||
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.state.activeTool.type === "selection" &&
|
this.state.activeTool.type === "selection" &&
|
||||||
!pointerDownState.boxSelection.hasOccurred &&
|
!pointerDownState.boxSelection.hasOccurred &&
|
||||||
!pointerDownState.resize.isResizing &&
|
!pointerDownState.resize.isResizing &&
|
||||||
!hitElements.some((el) => this.state.selectedElementIds[el.id])
|
!hitElements.some((el) => this.state.selectedElementIds[el.id])
|
||||||
) {
|
) {
|
||||||
const sceneCoords = viewportCoordsToSceneCoords(
|
|
||||||
{ clientX: childEvent.clientX, clientY: childEvent.clientY },
|
|
||||||
this.state,
|
|
||||||
);
|
|
||||||
const hitLockedElement = this.getElementAtPosition(
|
const hitLockedElement = this.getElementAtPosition(
|
||||||
sceneCoords.x,
|
sceneCoords.x,
|
||||||
sceneCoords.y,
|
sceneCoords.y,
|
||||||
@ -9029,6 +9025,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
} else if (this.state.selectedLinearElement.isDragging) {
|
} else if (this.state.selectedLinearElement.isDragging) {
|
||||||
this.actionManager.executeAction(actionFinalize, "ui", {
|
this.actionManager.executeAction(actionFinalize, "ui", {
|
||||||
event: childEvent,
|
event: childEvent,
|
||||||
|
sceneCoords,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9123,7 +9120,10 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
isBindingEnabled(this.state) &&
|
isBindingEnabled(this.state) &&
|
||||||
isBindingElement(newElement, false)
|
isBindingElement(newElement, false)
|
||||||
) {
|
) {
|
||||||
this.actionManager.executeAction(actionFinalize);
|
this.actionManager.executeAction(actionFinalize, "ui", {
|
||||||
|
event: childEvent,
|
||||||
|
sceneCoords,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.setState({ suggestedBindings: [], startBoundElement: null });
|
this.setState({ suggestedBindings: [], startBoundElement: null });
|
||||||
if (!activeTool.locked) {
|
if (!activeTool.locked) {
|
||||||
@ -9706,7 +9706,8 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
pointerDownState.drag.hasOccurred ||
|
(pointerDownState.drag.hasOccurred &&
|
||||||
|
!this.state.selectedLinearElement) ||
|
||||||
isResizing ||
|
isResizing ||
|
||||||
isRotating ||
|
isRotating ||
|
||||||
isCropping
|
isCropping
|
||||||
@ -10172,49 +10173,6 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private maybeSuggestBindingsForLinearElementAtCoords = (
|
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
|
||||||
/** scene coords */
|
|
||||||
pointerCoords: {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
}[],
|
|
||||||
// During line creation the start binding hasn't been written yet
|
|
||||||
// into `linearElement`
|
|
||||||
oppositeBindingBoundElement?: ExcalidrawBindableElement | null,
|
|
||||||
): void => {
|
|
||||||
if (!pointerCoords.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const suggestedBindings = pointerCoords.reduce(
|
|
||||||
(acc: NonDeleted<ExcalidrawBindableElement>[], coords) => {
|
|
||||||
const hoveredBindableElement = getHoveredElementForBinding(
|
|
||||||
coords,
|
|
||||||
this.scene.getNonDeletedElements(),
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
this.state.zoom,
|
|
||||||
isElbowArrow(linearElement),
|
|
||||||
isElbowArrow(linearElement),
|
|
||||||
);
|
|
||||||
if (
|
|
||||||
hoveredBindableElement != null &&
|
|
||||||
!isLinearElementSimpleAndAlreadyBound(
|
|
||||||
linearElement,
|
|
||||||
oppositeBindingBoundElement?.id,
|
|
||||||
hoveredBindableElement,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
acc.push(hoveredBindableElement);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
this.setState({ suggestedBindings });
|
|
||||||
};
|
|
||||||
|
|
||||||
private clearSelection(hitElement: ExcalidrawElement | null): void {
|
private clearSelection(hitElement: ExcalidrawElement | null): void {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
||||||
|
@ -224,7 +224,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"strokeWidth": 2,
|
"strokeWidth": 2,
|
||||||
"type": "arrow",
|
"type": "arrow",
|
||||||
"updated": 1,
|
"updated": 1,
|
||||||
"version": 37,
|
"version": 35,
|
||||||
"width": "98.40611",
|
"width": "98.40611",
|
||||||
"x": 1,
|
"x": 1,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
@ -348,7 +348,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"focus": "0.02970",
|
"focus": "0.02970",
|
||||||
"gap": 1,
|
"gap": 1,
|
||||||
},
|
},
|
||||||
"version": 35,
|
"version": 33,
|
||||||
},
|
},
|
||||||
"inserted": {
|
"inserted": {
|
||||||
"endBinding": {
|
"endBinding": {
|
||||||
@ -372,7 +372,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"focus": "0.02000",
|
"focus": "0.02000",
|
||||||
"gap": 1,
|
"gap": 1,
|
||||||
},
|
},
|
||||||
"version": 32,
|
"version": 30,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -427,7 +427,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
"startBinding": null,
|
"startBinding": null,
|
||||||
"version": 37,
|
"version": 35,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
},
|
},
|
||||||
"inserted": {
|
"inserted": {
|
||||||
@ -447,7 +447,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"focus": "0.02970",
|
"focus": "0.02970",
|
||||||
"gap": 1,
|
"gap": 1,
|
||||||
},
|
},
|
||||||
"version": 35,
|
"version": 33,
|
||||||
"y": "35.82151",
|
"y": "35.82151",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -828,7 +828,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"strokeWidth": 2,
|
"strokeWidth": 2,
|
||||||
"type": "arrow",
|
"type": "arrow",
|
||||||
"updated": 1,
|
"updated": 1,
|
||||||
"version": 33,
|
"version": 31,
|
||||||
"width": 0,
|
"width": 0,
|
||||||
"x": 149,
|
"x": 149,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
@ -878,7 +878,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"id4": {
|
"id4": {
|
||||||
"deleted": {
|
"deleted": {
|
||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"version": 32,
|
"version": 30,
|
||||||
},
|
},
|
||||||
"inserted": {
|
"inserted": {
|
||||||
"endBinding": {
|
"endBinding": {
|
||||||
@ -886,7 +886,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"focus": -0,
|
"focus": -0,
|
||||||
"gap": 1,
|
"gap": 1,
|
||||||
},
|
},
|
||||||
"version": 30,
|
"version": 28,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -922,7 +922,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"id4": {
|
"id4": {
|
||||||
"deleted": {
|
"deleted": {
|
||||||
"startBinding": null,
|
"startBinding": null,
|
||||||
"version": 33,
|
"version": 31,
|
||||||
},
|
},
|
||||||
"inserted": {
|
"inserted": {
|
||||||
"startBinding": {
|
"startBinding": {
|
||||||
@ -930,7 +930,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
|||||||
"focus": 0,
|
"focus": 0,
|
||||||
"gap": 1,
|
"gap": 1,
|
||||||
},
|
},
|
||||||
"version": 32,
|
"version": 30,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user