Переглянути джерело

fix: Dedupe boundElement ids when container duplicated with alt+drag (#5938)

* Dedupe boundElement ids when container duplicated with alt+drag and add spec

* set to null by default
Aakansha Doshi 2 роки тому
батько
коміт
a86224c797

+ 5 - 0
src/element/newElement.ts

@@ -370,6 +370,10 @@ export const deepCopyElement = (val: any, depth: number = 0) => {
         if (depth === 0 && (key === "shape" || key === "canvas")) {
           continue;
         }
+        if (key === "boundElements") {
+          tmp[key] = null;
+          continue;
+        }
         tmp[key] = deepCopyElement(val[key], depth + 1);
       }
     }
@@ -409,6 +413,7 @@ export const duplicateElement = <TElement extends Mutable<ExcalidrawElement>>(
   overrides?: Partial<TElement>,
 ): TElement => {
   let copy: TElement = deepCopyElement(element);
+
   if (isTestEnv()) {
     copy.id = `${copy.id}_copy`;
     // `window.h` may not be defined in some unit tests

+ 1 - 1
src/element/textElement.ts

@@ -111,7 +111,7 @@ export const bindTextToShapeAfterDuplication = (
         const newContainer = sceneElementMap.get(newElementId);
         if (newContainer) {
           mutateElement(newContainer, {
-            boundElements: element.boundElements?.concat({
+            boundElements: (newContainer.boundElements || []).concat({
               type: "text",
               id: newTextElementId,
             }),

+ 35 - 0
src/element/textWysiwyg.test.tsx

@@ -1121,5 +1121,40 @@ describe("textWysiwyg", () => {
       expect(rectangle.height).toBe(166.66666666666669);
       expect(textElement.fontSize).toBe(47.5);
     });
+
+    it("should bind text correctly when container duplicated with alt-drag", async () => {
+      Keyboard.keyPress(KEYS.ENTER);
+
+      const editor = document.querySelector(
+        ".excalidraw-textEditorContainer > textarea",
+      ) as HTMLTextAreaElement;
+      await new Promise((r) => setTimeout(r, 0));
+      fireEvent.change(editor, { target: { value: "Hello" } });
+      editor.blur();
+      expect(h.elements.length).toBe(2);
+
+      mouse.select(rectangle);
+      Keyboard.withModifierKeys({ alt: true }, () => {
+        mouse.down(rectangle.x + 10, rectangle.y + 10);
+        mouse.up(rectangle.x + 10, rectangle.y + 10);
+      });
+      expect(h.elements.length).toBe(4);
+      const duplicatedRectangle = h.elements[0];
+      const duplicatedText = h
+        .elements[1] as ExcalidrawTextElementWithContainer;
+      const originalRect = h.elements[2];
+      const originalText = h.elements[3] as ExcalidrawTextElementWithContainer;
+      expect(originalRect.boundElements).toStrictEqual([
+        { id: originalText.id, type: "text" },
+      ]);
+
+      expect(originalText.containerId).toBe(originalRect.id);
+
+      expect(duplicatedRectangle.boundElements).toStrictEqual([
+        { id: duplicatedText.id, type: "text" },
+      ]);
+
+      expect(duplicatedText.containerId).toBe(duplicatedRectangle.id);
+    });
   });
 });