mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
[skip ci] Stats binding behavior changes and test updates
This commit is contained in:
parent
ce10087edc
commit
db9e501d35
5 changed files with 50 additions and 18 deletions
|
@ -541,7 +541,7 @@ const isLinearElementSimple = (
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
): boolean => linearElement.points.length < 3;
|
): boolean => linearElement.points.length < 3;
|
||||||
|
|
||||||
const unbindLinearElement = (
|
export const unbindLinearElement = (
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
startOrEnd: "start" | "end",
|
startOrEnd: "start" | "end",
|
||||||
): ExcalidrawBindableElement["id"] | null => {
|
): ExcalidrawBindableElement["id"] | null => {
|
||||||
|
|
|
@ -130,7 +130,7 @@ export const isLinearElementType = (
|
||||||
export const isBindingElement = (
|
export const isBindingElement = (
|
||||||
element?: ExcalidrawElement | null,
|
element?: ExcalidrawElement | null,
|
||||||
includeLocked = true,
|
includeLocked = true,
|
||||||
): element is ExcalidrawLinearElement => {
|
): element is ExcalidrawArrowElement => {
|
||||||
return (
|
return (
|
||||||
element != null &&
|
element != null &&
|
||||||
(!element.locked || includeLocked === true) &&
|
(!element.locked || includeLocked === true) &&
|
||||||
|
|
|
@ -12,7 +12,7 @@ import type { ExcalidrawElement } from "@excalidraw/element/types";
|
||||||
import { angleIcon } from "../icons";
|
import { angleIcon } from "../icons";
|
||||||
|
|
||||||
import DragInput from "./DragInput";
|
import DragInput from "./DragInput";
|
||||||
import { getStepSizedValue, isPropertyEditable } from "./utils";
|
import { getStepSizedValue, isPropertyEditable, updateBindings } from "./utils";
|
||||||
|
|
||||||
import type { DragInputCallbackType } from "./DragInput";
|
import type { DragInputCallbackType } from "./DragInput";
|
||||||
import type Scene from "../../scene/Scene";
|
import type Scene from "../../scene/Scene";
|
||||||
|
@ -47,6 +47,7 @@ const handleDegreeChange: DragInputCallbackType<AngleProps["property"]> = ({
|
||||||
mutateElement(latestElement, {
|
mutateElement(latestElement, {
|
||||||
angle: nextAngle,
|
angle: nextAngle,
|
||||||
});
|
});
|
||||||
|
updateBindings(latestElement, elementsMap);
|
||||||
|
|
||||||
const boundTextElement = getBoundTextElement(latestElement, elementsMap);
|
const boundTextElement = getBoundTextElement(latestElement, elementsMap);
|
||||||
if (boundTextElement && !isArrowElement(latestElement)) {
|
if (boundTextElement && !isArrowElement(latestElement)) {
|
||||||
|
@ -72,6 +73,7 @@ const handleDegreeChange: DragInputCallbackType<AngleProps["property"]> = ({
|
||||||
mutateElement(latestElement, {
|
mutateElement(latestElement, {
|
||||||
angle: nextAngle,
|
angle: nextAngle,
|
||||||
});
|
});
|
||||||
|
updateBindings(latestElement, elementsMap);
|
||||||
|
|
||||||
const boundTextElement = getBoundTextElement(latestElement, elementsMap);
|
const boundTextElement = getBoundTextElement(latestElement, elementsMap);
|
||||||
if (boundTextElement && !isArrowElement(latestElement)) {
|
if (boundTextElement && !isArrowElement(latestElement)) {
|
||||||
|
|
|
@ -140,7 +140,9 @@ describe("binding with linear elements", () => {
|
||||||
expect(linear.startBinding).not.toBe(null);
|
expect(linear.startBinding).not.toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remain bound to linear element on small angle change", async () => {
|
// UX RATIONALE: Since we force a fixed distance from elements angle changes
|
||||||
|
// would result in a "jump" the moment the bound object is moved
|
||||||
|
it("should not remain bound to linear element on any angle change", async () => {
|
||||||
const linear = h.elements[1] as ExcalidrawLinearElement;
|
const linear = h.elements[1] as ExcalidrawLinearElement;
|
||||||
const inputAngle = UI.queryStatsProperty("A")?.querySelector(
|
const inputAngle = UI.queryStatsProperty("A")?.querySelector(
|
||||||
".drag-input",
|
".drag-input",
|
||||||
|
@ -148,7 +150,7 @@ describe("binding with linear elements", () => {
|
||||||
|
|
||||||
expect(linear.startBinding).not.toBe(null);
|
expect(linear.startBinding).not.toBe(null);
|
||||||
UI.updateInput(inputAngle, String("1"));
|
UI.updateInput(inputAngle, String("1"));
|
||||||
expect(linear.startBinding).not.toBe(null);
|
expect(linear.startBinding).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should unbind linear element on large position change", async () => {
|
it("should unbind linear element on large position change", async () => {
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { pointFrom, pointRotateRads } from "@excalidraw/math";
|
||||||
import { mutateElement } from "@excalidraw/element/mutateElement";
|
import { mutateElement } from "@excalidraw/element/mutateElement";
|
||||||
import { getBoundTextElement } from "@excalidraw/element/textElement";
|
import { getBoundTextElement } from "@excalidraw/element/textElement";
|
||||||
import {
|
import {
|
||||||
|
isBindableElement,
|
||||||
|
isBindingElement,
|
||||||
isFrameLikeElement,
|
isFrameLikeElement,
|
||||||
isTextElement,
|
isTextElement,
|
||||||
} from "@excalidraw/element/typeChecks";
|
} from "@excalidraw/element/typeChecks";
|
||||||
|
@ -13,6 +15,11 @@ import {
|
||||||
isInGroup,
|
isInGroup,
|
||||||
} from "@excalidraw/element/groups";
|
} from "@excalidraw/element/groups";
|
||||||
|
|
||||||
|
import {
|
||||||
|
unbindLinearElement,
|
||||||
|
updateBoundElements,
|
||||||
|
} from "@excalidraw/element/binding";
|
||||||
|
|
||||||
import type { Radians } from "@excalidraw/math";
|
import type { Radians } from "@excalidraw/math";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
@ -152,6 +159,8 @@ export const moveElement = (
|
||||||
shouldInformMutation,
|
shouldInformMutation,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
updateBindings(latestElement, elementsMap);
|
||||||
|
|
||||||
const boundTextElement = getBoundTextElement(
|
const boundTextElement = getBoundTextElement(
|
||||||
originalElement,
|
originalElement,
|
||||||
originalElementsMap,
|
originalElementsMap,
|
||||||
|
@ -190,3 +199,22 @@ export const getAtomicUnits = (
|
||||||
});
|
});
|
||||||
return _atomicUnits;
|
return _atomicUnits;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updateBindings = (
|
||||||
|
latestElement: ExcalidrawElement,
|
||||||
|
elementsMap: NonDeletedSceneElementsMap,
|
||||||
|
options?: {
|
||||||
|
simultaneouslyUpdated?: readonly ExcalidrawElement[];
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
if (isBindingElement(latestElement)) {
|
||||||
|
if (latestElement.startBinding) {
|
||||||
|
unbindLinearElement(latestElement, "start");
|
||||||
|
}
|
||||||
|
if (latestElement.endBinding) {
|
||||||
|
unbindLinearElement(latestElement, "end");
|
||||||
|
}
|
||||||
|
} else if (isBindableElement(latestElement)) {
|
||||||
|
updateBoundElements(latestElement, elementsMap, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue