fix: prevent binding focus NaN value (#6803)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
This commit is contained in:
parent
8104068bd5
commit
c1247742ea
@ -3,6 +3,7 @@ import {
|
|||||||
ExcalidrawSelectionElement,
|
ExcalidrawSelectionElement,
|
||||||
ExcalidrawTextElement,
|
ExcalidrawTextElement,
|
||||||
FontFamilyValues,
|
FontFamilyValues,
|
||||||
|
PointBinding,
|
||||||
StrokeRoundness,
|
StrokeRoundness,
|
||||||
} from "../element/types";
|
} from "../element/types";
|
||||||
import {
|
import {
|
||||||
@ -83,6 +84,13 @@ const getFontFamilyByName = (fontFamilyName: string): FontFamilyValues => {
|
|||||||
return DEFAULT_FONT_FAMILY;
|
return DEFAULT_FONT_FAMILY;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const repairBinding = (binding: PointBinding | null) => {
|
||||||
|
if (!binding) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return { ...binding, focus: binding.focus || 0 };
|
||||||
|
};
|
||||||
|
|
||||||
const restoreElementWithProperties = <
|
const restoreElementWithProperties = <
|
||||||
T extends Required<Omit<ExcalidrawElement, "customData">> & {
|
T extends Required<Omit<ExcalidrawElement, "customData">> & {
|
||||||
customData?: ExcalidrawElement["customData"];
|
customData?: ExcalidrawElement["customData"];
|
||||||
@ -258,8 +266,8 @@ const restoreElement = (
|
|||||||
(element.type as ExcalidrawElement["type"] | "draw") === "draw"
|
(element.type as ExcalidrawElement["type"] | "draw") === "draw"
|
||||||
? "line"
|
? "line"
|
||||||
: element.type,
|
: element.type,
|
||||||
startBinding: element.startBinding,
|
startBinding: repairBinding(element.startBinding),
|
||||||
endBinding: element.endBinding,
|
endBinding: repairBinding(element.endBinding),
|
||||||
lastCommittedPoint: null,
|
lastCommittedPoint: null,
|
||||||
startArrowhead,
|
startArrowhead,
|
||||||
endArrowhead,
|
endArrowhead,
|
||||||
|
@ -655,18 +655,23 @@ export const determineFocusDistance = (
|
|||||||
const c = line[1];
|
const c = line[1];
|
||||||
const mabs = Math.abs(m);
|
const mabs = Math.abs(m);
|
||||||
const nabs = Math.abs(n);
|
const nabs = Math.abs(n);
|
||||||
|
let ret;
|
||||||
switch (element.type) {
|
switch (element.type) {
|
||||||
case "rectangle":
|
case "rectangle":
|
||||||
case "image":
|
case "image":
|
||||||
case "text":
|
case "text":
|
||||||
case "embeddable":
|
case "embeddable":
|
||||||
case "frame":
|
case "frame":
|
||||||
return c / (hwidth * (nabs + q * mabs));
|
ret = c / (hwidth * (nabs + q * mabs));
|
||||||
|
break;
|
||||||
case "diamond":
|
case "diamond":
|
||||||
return mabs < nabs ? c / (nabs * hwidth) : c / (mabs * hheight);
|
ret = mabs < nabs ? c / (nabs * hwidth) : c / (mabs * hheight);
|
||||||
|
break;
|
||||||
case "ellipse":
|
case "ellipse":
|
||||||
return c / (hwidth * Math.sqrt(n ** 2 + q ** 2 * m ** 2));
|
ret = c / (hwidth * Math.sqrt(n ** 2 + q ** 2 * m ** 2));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return ret || 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const determineFocusPoint = (
|
export const determineFocusPoint = (
|
||||||
|
6
src/global.d.ts
vendored
6
src/global.d.ts
vendored
@ -120,3 +120,9 @@ declare module "image-blob-reduce" {
|
|||||||
const reduce: ImageBlobReduce.ImageBlobReduceStatic;
|
const reduce: ImageBlobReduce.ImageBlobReduceStatic;
|
||||||
export = reduce;
|
export = reduce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare namespace jest {
|
||||||
|
interface Expect {
|
||||||
|
toBeNonNaNNumber(): void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,61 @@ describe("element binding", () => {
|
|||||||
await render(<ExcalidrawApp />);
|
await render(<ExcalidrawApp />);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create valid binding if duplicate start/end points", async () => {
|
||||||
|
const rect = API.createElement({
|
||||||
|
type: "rectangle",
|
||||||
|
x: 0,
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
});
|
||||||
|
const arrow = API.createElement({
|
||||||
|
type: "arrow",
|
||||||
|
x: 100,
|
||||||
|
y: 0,
|
||||||
|
width: 100,
|
||||||
|
height: 1,
|
||||||
|
points: [
|
||||||
|
[0, 0],
|
||||||
|
[0, 0],
|
||||||
|
[100, 0],
|
||||||
|
[100, 0],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
h.elements = [rect, arrow];
|
||||||
|
expect(arrow.startBinding).toBe(null);
|
||||||
|
|
||||||
|
API.setSelectedElements([arrow]);
|
||||||
|
|
||||||
|
expect(API.getSelectedElements()).toEqual([arrow]);
|
||||||
|
mouse.downAt(100, 0);
|
||||||
|
mouse.moveTo(55, 0);
|
||||||
|
mouse.up(0, 0);
|
||||||
|
expect(arrow.startBinding).toEqual({
|
||||||
|
elementId: rect.id,
|
||||||
|
focus: expect.toBeNonNaNNumber(),
|
||||||
|
gap: expect.toBeNonNaNNumber(),
|
||||||
|
});
|
||||||
|
|
||||||
|
mouse.downAt(100, 0);
|
||||||
|
mouse.move(-45, 0);
|
||||||
|
mouse.up();
|
||||||
|
expect(arrow.startBinding).toEqual({
|
||||||
|
elementId: rect.id,
|
||||||
|
focus: expect.toBeNonNaNNumber(),
|
||||||
|
gap: expect.toBeNonNaNNumber(),
|
||||||
|
});
|
||||||
|
|
||||||
|
mouse.down();
|
||||||
|
mouse.move(-50, 0);
|
||||||
|
mouse.up();
|
||||||
|
expect(arrow.startBinding).toBe(null);
|
||||||
|
expect(arrow.endBinding).toEqual({
|
||||||
|
elementId: rect.id,
|
||||||
|
focus: expect.toBeNonNaNNumber(),
|
||||||
|
gap: expect.toBeNonNaNNumber(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
//@TODO fix the test with rotation
|
//@TODO fix the test with rotation
|
||||||
it.skip("rotation of arrow should rebind both ends", () => {
|
it.skip("rotation of arrow should rebind both ends", () => {
|
||||||
const rectLeft = UI.createElement("rectangle", {
|
const rectLeft = UI.createElement("rectangle", {
|
||||||
|
@ -228,3 +228,19 @@ export const togglePopover = (label: string) => {
|
|||||||
|
|
||||||
UI.clickLabeledElement(label);
|
UI.clickLabeledElement(label);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
expect.extend({
|
||||||
|
toBeNonNaNNumber(received) {
|
||||||
|
const pass = typeof received === "number" && !isNaN(received);
|
||||||
|
if (pass) {
|
||||||
|
return {
|
||||||
|
message: () => `expected ${received} not to be a non-NaN number`,
|
||||||
|
pass: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
message: () => `expected ${received} to be a non-NaN number`,
|
||||||
|
pass: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user