mirror of
https://github.com/excalidraw/excalidraw.git
synced 2024-11-10 11:35:52 +01:00
88a2b286c7
* feat: move utils to utils package and make @excalidraw/utils a workspace * remove esm and update types path * remove esm script * fix package.json and yarn.lock * update path * fix * fix lint and test
263 lines
7.1 KiB
TypeScript
263 lines
7.1 KiB
TypeScript
import { Bounds } from "../excalidraw/element/bounds";
|
|
import { API } from "../excalidraw/tests/helpers/api";
|
|
import {
|
|
elementPartiallyOverlapsWithOrContainsBBox,
|
|
elementsOverlappingBBox,
|
|
isElementInsideBBox,
|
|
} from "./withinBounds";
|
|
|
|
const makeElement = (x: number, y: number, width: number, height: number) =>
|
|
API.createElement({
|
|
type: "rectangle",
|
|
x,
|
|
y,
|
|
width,
|
|
height,
|
|
});
|
|
|
|
const makeBBox = (
|
|
minX: number,
|
|
minY: number,
|
|
maxX: number,
|
|
maxY: number,
|
|
): Bounds => [minX, minY, maxX, maxY];
|
|
|
|
describe("isElementInsideBBox()", () => {
|
|
it("should return true if element is fully inside", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
// bbox contains element
|
|
expect(isElementInsideBBox(makeElement(0, 0, 100, 100), bbox)).toBe(true);
|
|
expect(isElementInsideBBox(makeElement(10, 10, 90, 90), bbox)).toBe(true);
|
|
});
|
|
|
|
it("should return false if element is only partially overlapping", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
// element contains bbox
|
|
expect(isElementInsideBBox(makeElement(-10, -10, 110, 110), bbox)).toBe(
|
|
false,
|
|
);
|
|
|
|
// element overlaps bbox from top-left
|
|
expect(isElementInsideBBox(makeElement(-10, -10, 100, 100), bbox)).toBe(
|
|
false,
|
|
);
|
|
// element overlaps bbox from top-right
|
|
expect(isElementInsideBBox(makeElement(90, -10, 100, 100), bbox)).toBe(
|
|
false,
|
|
);
|
|
// element overlaps bbox from bottom-left
|
|
expect(isElementInsideBBox(makeElement(-10, 90, 100, 100), bbox)).toBe(
|
|
false,
|
|
);
|
|
// element overlaps bbox from bottom-right
|
|
expect(isElementInsideBBox(makeElement(90, 90, 100, 100), bbox)).toBe(
|
|
false,
|
|
);
|
|
});
|
|
|
|
it("should return false if element outside", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
// outside diagonally
|
|
expect(isElementInsideBBox(makeElement(110, 110, 100, 100), bbox)).toBe(
|
|
false,
|
|
);
|
|
|
|
// outside on the left
|
|
expect(isElementInsideBBox(makeElement(-110, 10, 50, 50), bbox)).toBe(
|
|
false,
|
|
);
|
|
// outside on the right
|
|
expect(isElementInsideBBox(makeElement(110, 10, 50, 50), bbox)).toBe(false);
|
|
// outside on the top
|
|
expect(isElementInsideBBox(makeElement(10, -110, 50, 50), bbox)).toBe(
|
|
false,
|
|
);
|
|
// outside on the bottom
|
|
expect(isElementInsideBBox(makeElement(10, 110, 50, 50), bbox)).toBe(false);
|
|
});
|
|
|
|
it("should return true if bbox contains element and flag enabled", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
// element contains bbox
|
|
expect(
|
|
isElementInsideBBox(makeElement(-10, -10, 110, 110), bbox, true),
|
|
).toBe(true);
|
|
|
|
// bbox contains element
|
|
expect(isElementInsideBBox(makeElement(0, 0, 100, 100), bbox)).toBe(true);
|
|
expect(isElementInsideBBox(makeElement(10, 10, 90, 90), bbox)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("elementPartiallyOverlapsWithOrContainsBBox()", () => {
|
|
it("should return true if element overlaps, is inside, or contains", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
// bbox contains element
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(0, 0, 100, 100),
|
|
bbox,
|
|
),
|
|
).toBe(true);
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(10, 10, 90, 90),
|
|
bbox,
|
|
),
|
|
).toBe(true);
|
|
|
|
// element contains bbox
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(-10, -10, 110, 110),
|
|
bbox,
|
|
),
|
|
).toBe(true);
|
|
|
|
// element overlaps bbox from top-left
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(-10, -10, 100, 100),
|
|
bbox,
|
|
),
|
|
).toBe(true);
|
|
// element overlaps bbox from top-right
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(90, -10, 100, 100),
|
|
bbox,
|
|
),
|
|
).toBe(true);
|
|
// element overlaps bbox from bottom-left
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(-10, 90, 100, 100),
|
|
bbox,
|
|
),
|
|
).toBe(true);
|
|
// element overlaps bbox from bottom-right
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(90, 90, 100, 100),
|
|
bbox,
|
|
),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("should return false if element does not overlap", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
// outside diagonally
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(110, 110, 100, 100),
|
|
bbox,
|
|
),
|
|
).toBe(false);
|
|
|
|
// outside on the left
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(-110, 10, 50, 50),
|
|
bbox,
|
|
),
|
|
).toBe(false);
|
|
// outside on the right
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(110, 10, 50, 50),
|
|
bbox,
|
|
),
|
|
).toBe(false);
|
|
// outside on the top
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(10, -110, 50, 50),
|
|
bbox,
|
|
),
|
|
).toBe(false);
|
|
// outside on the bottom
|
|
expect(
|
|
elementPartiallyOverlapsWithOrContainsBBox(
|
|
makeElement(10, 110, 50, 50),
|
|
bbox,
|
|
),
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("elementsOverlappingBBox()", () => {
|
|
it("should return elements that overlap bbox", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
const rectOutside = makeElement(110, 110, 100, 100);
|
|
const rectInside = makeElement(10, 10, 90, 90);
|
|
const rectContainingBBox = makeElement(-10, -10, 110, 110);
|
|
const rectOverlappingTopLeft = makeElement(-10, -10, 50, 50);
|
|
|
|
expect(
|
|
elementsOverlappingBBox({
|
|
bounds: bbox,
|
|
type: "overlap",
|
|
elements: [
|
|
rectOutside,
|
|
rectInside,
|
|
rectContainingBBox,
|
|
rectOverlappingTopLeft,
|
|
],
|
|
}),
|
|
).toEqual([rectInside, rectContainingBBox, rectOverlappingTopLeft]);
|
|
});
|
|
|
|
it("should return elements inside/containing bbox", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
const rectOutside = makeElement(110, 110, 100, 100);
|
|
const rectInside = makeElement(10, 10, 90, 90);
|
|
const rectContainingBBox = makeElement(-10, -10, 110, 110);
|
|
const rectOverlappingTopLeft = makeElement(-10, -10, 50, 50);
|
|
|
|
expect(
|
|
elementsOverlappingBBox({
|
|
bounds: bbox,
|
|
type: "contain",
|
|
elements: [
|
|
rectOutside,
|
|
rectInside,
|
|
rectContainingBBox,
|
|
rectOverlappingTopLeft,
|
|
],
|
|
}),
|
|
).toEqual([rectInside, rectContainingBBox]);
|
|
});
|
|
|
|
it("should return elements inside bbox", () => {
|
|
const bbox = makeBBox(0, 0, 100, 100);
|
|
|
|
const rectOutside = makeElement(110, 110, 100, 100);
|
|
const rectInside = makeElement(10, 10, 90, 90);
|
|
const rectContainingBBox = makeElement(-10, -10, 110, 110);
|
|
const rectOverlappingTopLeft = makeElement(-10, -10, 50, 50);
|
|
|
|
expect(
|
|
elementsOverlappingBBox({
|
|
bounds: bbox,
|
|
type: "inside",
|
|
elements: [
|
|
rectOutside,
|
|
rectInside,
|
|
rectContainingBBox,
|
|
rectOverlappingTopLeft,
|
|
],
|
|
}),
|
|
).toEqual([rectInside]);
|
|
});
|
|
|
|
// TODO test linear, freedraw, and diamond element types (+rotated)
|
|
});
|