Browse Source

fix: copy bound text style when copying element having bound text (#5305)

* fix: copy bound text style when copying element having bound text

* fix

* fix tests
Aakansha Doshi 3 năm trước cách đây
mục cha
commit
84b47a2ed5

+ 1 - 1
src/actions/actionStyles.test.tsx

@@ -48,7 +48,7 @@ describe("actionStyles", () => {
     Keyboard.withModifierKeys({ ctrl: true, alt: true }, () => {
       Keyboard.codeDown(CODES.C);
     });
-    const secondRect = JSON.parse(copiedStyles);
+    const secondRect = JSON.parse(copiedStyles)[0];
     expect(secondRect.id).toBe(h.elements[1].id);
 
     mouse.reset();

+ 48 - 18
src/actions/actionStyles.ts

@@ -12,7 +12,9 @@ import {
   DEFAULT_FONT_FAMILY,
   DEFAULT_TEXT_ALIGN,
 } from "../constants";
-import { getContainerElement } from "../element/textElement";
+import { getBoundTextElement } from "../element/textElement";
+import { hasBoundTextElement } from "../element/typeChecks";
+import { getSelectedElements } from "../scene";
 
 // `copiedStyles` is exported only for tests.
 export let copiedStyles: string = "{}";
@@ -21,9 +23,15 @@ export const actionCopyStyles = register({
   name: "copyStyles",
   trackEvent: { category: "element" },
   perform: (elements, appState) => {
+    const elementsCopied = [];
     const element = elements.find((el) => appState.selectedElementIds[el.id]);
+    elementsCopied.push(element);
+    if (element && hasBoundTextElement(element)) {
+      const boundTextElement = getBoundTextElement(element);
+      elementsCopied.push(boundTextElement);
+    }
     if (element) {
-      copiedStyles = JSON.stringify(element);
+      copiedStyles = JSON.stringify(elementsCopied);
     }
     return {
       appState: {
@@ -42,37 +50,59 @@ export const actionPasteStyles = register({
   name: "pasteStyles",
   trackEvent: { category: "element" },
   perform: (elements, appState) => {
-    const pastedElement = JSON.parse(copiedStyles);
+    const elementsCopied = JSON.parse(copiedStyles);
+    const pastedElement = elementsCopied[0];
+    const boundTextElement = elementsCopied[1];
     if (!isExcalidrawElement(pastedElement)) {
       return { elements, commitToHistory: false };
     }
+
+    const selectedElements = getSelectedElements(elements, appState, true);
+    const selectedElementIds = selectedElements.map((element) => element.id);
     return {
       elements: elements.map((element) => {
-        if (appState.selectedElementIds[element.id]) {
+        if (selectedElementIds.includes(element.id)) {
+          let elementStylesToCopyFrom = pastedElement;
+          if (isTextElement(element) && element.containerId) {
+            elementStylesToCopyFrom = boundTextElement;
+          }
+          if (!elementStylesToCopyFrom) {
+            return element;
+          }
           let newElement = newElementWith(element, {
-            backgroundColor: pastedElement?.backgroundColor,
-            strokeWidth: pastedElement?.strokeWidth,
-            strokeColor: pastedElement?.strokeColor,
-            strokeStyle: pastedElement?.strokeStyle,
-            fillStyle: pastedElement?.fillStyle,
-            opacity: pastedElement?.opacity,
-            roughness: pastedElement?.roughness,
+            backgroundColor: elementStylesToCopyFrom?.backgroundColor,
+            strokeWidth: elementStylesToCopyFrom?.strokeWidth,
+            strokeColor: elementStylesToCopyFrom?.strokeColor,
+            strokeStyle: elementStylesToCopyFrom?.strokeStyle,
+            fillStyle: elementStylesToCopyFrom?.fillStyle,
+            opacity: elementStylesToCopyFrom?.opacity,
+            roughness: elementStylesToCopyFrom?.roughness,
           });
 
           if (isTextElement(newElement)) {
             newElement = newElementWith(newElement, {
-              fontSize: pastedElement?.fontSize || DEFAULT_FONT_SIZE,
-              fontFamily: pastedElement?.fontFamily || DEFAULT_FONT_FAMILY,
-              textAlign: pastedElement?.textAlign || DEFAULT_TEXT_ALIGN,
+              fontSize: elementStylesToCopyFrom?.fontSize || DEFAULT_FONT_SIZE,
+              fontFamily:
+                elementStylesToCopyFrom?.fontFamily || DEFAULT_FONT_FAMILY,
+              textAlign:
+                elementStylesToCopyFrom?.textAlign || DEFAULT_TEXT_ALIGN,
             });
-
-            redrawTextBoundingBox(newElement, getContainerElement(newElement));
+            let container = null;
+            if (newElement.containerId) {
+              container =
+                selectedElements.find(
+                  (element) =>
+                    isTextElement(newElement) &&
+                    element.id === newElement.containerId,
+                ) || null;
+            }
+            redrawTextBoundingBox(newElement, container);
           }
 
           if (newElement.type === "arrow") {
             newElement = newElementWith(newElement, {
-              startArrowhead: pastedElement.startArrowhead,
-              endArrowhead: pastedElement.endArrowhead,
+              startArrowhead: elementStylesToCopyFrom.startArrowhead,
+              endArrowhead: elementStylesToCopyFrom.endArrowhead,
             });
           }
 

+ 2 - 2
src/tests/contextmenu.test.tsx

@@ -289,7 +289,7 @@ describe("contextMenu element", () => {
     expect(copiedStyles).toBe("{}");
     fireEvent.click(queryByText(contextMenu as HTMLElement, "Copy styles")!);
     expect(copiedStyles).not.toBe("{}");
-    const element = JSON.parse(copiedStyles);
+    const element = JSON.parse(copiedStyles)[0];
     expect(element).toEqual(API.getSelectedElement());
   });
 
@@ -329,7 +329,7 @@ describe("contextMenu element", () => {
     });
     let contextMenu = UI.queryContextMenu();
     fireEvent.click(queryByText(contextMenu as HTMLElement, "Copy styles")!);
-    const secondRect = JSON.parse(copiedStyles);
+    const secondRect = JSON.parse(copiedStyles)[0];
     expect(secondRect.id).toBe(h.elements[1].id);
 
     mouse.reset();