| 
					
				 | 
			
			
				@@ -2,8 +2,12 @@ import { render, waitFor } from "./test-utils"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import ExcalidrawApp from "../excalidraw-app"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { API } from "./helpers/api"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { MIME_TYPES } from "../constants"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { LibraryItem } from "../types"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { LibraryItem, LibraryItems } from "../types"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -37,7 +41,7 @@ describe("library", () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       await API.readFile("./fixtures/fixture_library.excalidrawlib", "utf8"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ).library[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     await API.drop( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      new Blob([JSON.stringify(libraryItems)], { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      new Blob([serializeLibraryAsJSON([libraryItems])], { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         type: MIME_TYPES.excalidrawlib, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       }), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -53,7 +57,7 @@ describe("library", () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       await API.readFile("./fixtures/fixture_library.excalidrawlib", "utf8"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ).library[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     await API.drop( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      new Blob([JSON.stringify(libraryItems)], { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      new Blob([serializeLibraryAsJSON([libraryItems])], { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         type: MIME_TYPES.excalidrawlib, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       }), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -63,3 +67,111 @@ describe("library", () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     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), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 |