|
@@ -2,8 +2,12 @@ import { render, waitFor } from "./test-utils";
|
|
import ExcalidrawApp from "../excalidraw-app";
|
|
import ExcalidrawApp from "../excalidraw-app";
|
|
import { API } from "./helpers/api";
|
|
import { API } from "./helpers/api";
|
|
import { MIME_TYPES } from "../constants";
|
|
import { MIME_TYPES } from "../constants";
|
|
-import { LibraryItem } from "../types";
|
|
|
|
|
|
+import { LibraryItem, LibraryItems } from "../types";
|
|
import { UI } from "./helpers/ui";
|
|
import { UI } from "./helpers/ui";
|
|
|
|
+import { serializeLibraryAsJSON } from "../data/json";
|
|
|
|
+import { distributeLibraryItemsOnSquareGrid } from "../data/library";
|
|
|
|
+import { ExcalidrawGenericElement } from "../element/types";
|
|
|
|
+import { getCommonBoundingBox } from "../element/bounds";
|
|
|
|
|
|
const { h } = window;
|
|
const { h } = window;
|
|
|
|
|
|
@@ -37,7 +41,7 @@ describe("library", () => {
|
|
await API.readFile("./fixtures/fixture_library.excalidrawlib", "utf8"),
|
|
await API.readFile("./fixtures/fixture_library.excalidrawlib", "utf8"),
|
|
).library[0];
|
|
).library[0];
|
|
await API.drop(
|
|
await API.drop(
|
|
- new Blob([JSON.stringify(libraryItems)], {
|
|
|
|
|
|
+ new Blob([serializeLibraryAsJSON([libraryItems])], {
|
|
type: MIME_TYPES.excalidrawlib,
|
|
type: MIME_TYPES.excalidrawlib,
|
|
}),
|
|
}),
|
|
);
|
|
);
|
|
@@ -53,7 +57,7 @@ describe("library", () => {
|
|
await API.readFile("./fixtures/fixture_library.excalidrawlib", "utf8"),
|
|
await API.readFile("./fixtures/fixture_library.excalidrawlib", "utf8"),
|
|
).library[0];
|
|
).library[0];
|
|
await API.drop(
|
|
await API.drop(
|
|
- new Blob([JSON.stringify(libraryItems)], {
|
|
|
|
|
|
+ new Blob([serializeLibraryAsJSON([libraryItems])], {
|
|
type: MIME_TYPES.excalidrawlib,
|
|
type: MIME_TYPES.excalidrawlib,
|
|
}),
|
|
}),
|
|
);
|
|
);
|
|
@@ -63,3 +67,111 @@ describe("library", () => {
|
|
expect(h.state.activeTool.type).toBe("selection");
|
|
expect(h.state.activeTool.type).toBe("selection");
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
+
|
|
|
|
+describe("distributeLibraryItemsOnSquareGrid()", () => {
|
|
|
|
+ it("should distribute items on a grid", async () => {
|
|
|
|
+ const createLibraryItem = (
|
|
|
|
+ elements: ExcalidrawGenericElement[],
|
|
|
|
+ ): LibraryItem => {
|
|
|
|
+ return {
|
|
|
|
+ id: `id-${Date.now()}`,
|
|
|
|
+ elements,
|
|
|
|
+ status: "unpublished",
|
|
|
|
+ created: Date.now(),
|
|
|
|
+ };
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const PADDING = 50;
|
|
|
|
+
|
|
|
|
+ const el1 = API.createElement({
|
|
|
|
+ id: "id1",
|
|
|
|
+ width: 100,
|
|
|
|
+ height: 100,
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 0,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const el2 = API.createElement({
|
|
|
|
+ id: "id2",
|
|
|
|
+ width: 100,
|
|
|
|
+ height: 80,
|
|
|
|
+ x: -100,
|
|
|
|
+ y: -50,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const el3 = API.createElement({
|
|
|
|
+ id: "id3",
|
|
|
|
+ width: 40,
|
|
|
|
+ height: 50,
|
|
|
|
+ x: -100,
|
|
|
|
+ y: -50,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const el4 = API.createElement({
|
|
|
|
+ id: "id4",
|
|
|
|
+ width: 50,
|
|
|
|
+ height: 50,
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 0,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const el5 = API.createElement({
|
|
|
|
+ id: "id5",
|
|
|
|
+ width: 70,
|
|
|
|
+ height: 100,
|
|
|
|
+ x: 40,
|
|
|
|
+ y: 0,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const libraryItems: LibraryItems = [
|
|
|
|
+ createLibraryItem([el1]),
|
|
|
|
+ createLibraryItem([el2]),
|
|
|
|
+ createLibraryItem([el3]),
|
|
|
|
+ createLibraryItem([el4, el5]),
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ const distributed = distributeLibraryItemsOnSquareGrid(libraryItems);
|
|
|
|
+ // assert the returned library items are flattened to elements
|
|
|
|
+ expect(distributed.length).toEqual(
|
|
|
|
+ libraryItems.map((x) => x.elements).flat().length,
|
|
|
|
+ );
|
|
|
|
+ expect(distributed).toEqual(
|
|
|
|
+ expect.arrayContaining([
|
|
|
|
+ expect.objectContaining({
|
|
|
|
+ id: el1.id,
|
|
|
|
+ x: 0,
|
|
|
|
+ y: 0,
|
|
|
|
+ }),
|
|
|
|
+ expect.objectContaining({
|
|
|
|
+ id: el2.id,
|
|
|
|
+ x:
|
|
|
|
+ el1.width +
|
|
|
|
+ PADDING +
|
|
|
|
+ (getCommonBoundingBox([el4, el5]).width - el2.width) / 2,
|
|
|
|
+ y: Math.abs(el1.height - el2.height) / 2,
|
|
|
|
+ }),
|
|
|
|
+ expect.objectContaining({
|
|
|
|
+ id: el3.id,
|
|
|
|
+ x: Math.abs(el1.width - el3.width) / 2,
|
|
|
|
+ y:
|
|
|
|
+ Math.max(el1.height, el2.height) +
|
|
|
|
+ PADDING +
|
|
|
|
+ Math.abs(el3.height - Math.max(el4.height, el5.height)) / 2,
|
|
|
|
+ }),
|
|
|
|
+ expect.objectContaining({
|
|
|
|
+ id: el4.id,
|
|
|
|
+ x: Math.max(el1.width, el2.width) + PADDING,
|
|
|
|
+ y: Math.max(el1.height, el2.height) + PADDING,
|
|
|
|
+ }),
|
|
|
|
+ expect.objectContaining({
|
|
|
|
+ id: el5.id,
|
|
|
|
+ x: Math.max(el1.width, el2.width) + PADDING + Math.abs(el5.x - el4.x),
|
|
|
|
+ y:
|
|
|
|
+ Math.max(el1.height, el2.height) +
|
|
|
|
+ PADDING +
|
|
|
|
+ Math.abs(el5.y - el4.y),
|
|
|
|
+ }),
|
|
|
|
+ ]),
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
+});
|