From b477c2ad6bacd13e4251f10acfa5eb6a5117dc94 Mon Sep 17 00:00:00 2001 From: zsviczian Date: Tue, 27 Sep 2022 13:14:41 +0200 Subject: [PATCH] fix: horizontal text alignment for bound text when resizing (#5721) * Update textElement.ts * Add test * don't use modifier keys when not needed Co-authored-by: Aakansha Doshi --- src/element/textElement.ts | 7 ++- src/element/textWysiwyg.test.tsx | 87 +++++++++++++++++++++++++++----- src/tests/resize.test.tsx | 31 ++---------- src/tests/utils.ts | 29 +++++++++++ 4 files changed, 113 insertions(+), 41 deletions(-) create mode 100644 src/tests/utils.ts diff --git a/src/element/textElement.ts b/src/element/textElement.ts index e177f079..b1751cb6 100644 --- a/src/element/textElement.ts +++ b/src/element/textElement.ts @@ -174,7 +174,12 @@ export const handleBindTextResize = ( } else { updatedY = element.y + element.height / 2 - nextHeight / 2; } - const updatedX = element.x + element.width / 2 - nextWidth / 2; + const updatedX = + textElement.textAlign === TEXT_ALIGN.LEFT + ? element.x + BOUND_TEXT_PADDING + : textElement.textAlign === TEXT_ALIGN.RIGHT + ? element.x + element.width - nextWidth - BOUND_TEXT_PADDING + : element.x + element.width / 2 - nextWidth / 2; mutateElement(textElement, { text, width: nextWidth, diff --git a/src/element/textWysiwyg.test.tsx b/src/element/textWysiwyg.test.tsx index de7528be..436b2461 100644 --- a/src/element/textWysiwyg.test.tsx +++ b/src/element/textWysiwyg.test.tsx @@ -14,6 +14,7 @@ import { import * as textElementUtils from "./textElement"; import { API } from "../tests/helpers/api"; import { mutateElement } from "./mutateElement"; +import { resize } from "../tests/utils"; // Unmount ReactDOM from root ReactDOM.unmountComponentAtNode(document.getElementById("root")!); @@ -492,9 +493,7 @@ describe("textWysiwyg", () => { expect(h.elements.length).toBe(1); expect(h.elements[0].id).toBe(rectangle.id); - Keyboard.withModifierKeys({}, () => { - Keyboard.keyPress(KEYS.ENTER); - }); + Keyboard.keyPress(KEYS.ENTER); expect(h.elements.length).toBe(2); @@ -695,9 +694,8 @@ describe("textWysiwyg", () => { // Edit and text by removing second line and it should // still vertically align correctly mouse.select(rectangle); - Keyboard.withModifierKeys({}, () => { - Keyboard.keyPress(KEYS.ENTER); - }); + Keyboard.keyPress(KEYS.ENTER); + editor = document.querySelector( ".excalidraw-textEditorContainer > textarea", ) as HTMLTextAreaElement; @@ -734,9 +732,7 @@ describe("textWysiwyg", () => { expect(h.elements.length).toBe(1); expect(h.elements[0].id).toBe(rectangle.id); - Keyboard.withModifierKeys({}, () => { - Keyboard.keyPress(KEYS.ENTER); - }); + Keyboard.keyPress(KEYS.ENTER); expect(h.elements.length).toBe(2); @@ -771,12 +767,11 @@ describe("textWysiwyg", () => { null, ); }); + it("shouldn't bind to container if container has bound text", async () => { expect(h.elements.length).toBe(1); - Keyboard.withModifierKeys({}, () => { - Keyboard.keyPress(KEYS.ENTER); - }); + Keyboard.keyPress(KEYS.ENTER); expect(h.elements.length).toBe(2); @@ -813,5 +808,73 @@ describe("textWysiwyg", () => { ]); expect(text.containerId).toBe(null); }); + + it("should respect text alignment when resizing", async () => { + Keyboard.keyPress(KEYS.ENTER); + + let editor = document.querySelector( + ".excalidraw-textEditorContainer > textarea", + ) as HTMLTextAreaElement; + await new Promise((r) => setTimeout(r, 0)); + fireEvent.change(editor, { target: { value: "Hello" } }); + editor.blur(); + + // should center align horizontally and vertically by default + resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]); + expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(` + Array [ + 109.5, + 17, + ] + `); + + mouse.select(rectangle); + Keyboard.keyPress(KEYS.ENTER); + + editor = document.querySelector( + ".excalidraw-textEditorContainer > textarea", + ) as HTMLTextAreaElement; + + editor.select(); + + fireEvent.click(screen.getByTitle("Left")); + fireEvent.click(screen.getByTitle("Align bottom")); + await new Promise((r) => setTimeout(r, 0)); + + editor.blur(); + + // should left align horizontally and bottom vertically after resize + resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]); + expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(` + Array [ + 15, + 90, + ] + `); + + mouse.select(rectangle); + Keyboard.keyPress(KEYS.ENTER); + editor = document.querySelector( + ".excalidraw-textEditorContainer > textarea", + ) as HTMLTextAreaElement; + + editor.select(); + + fireEvent.click(screen.getByTitle("Right")); + fireEvent.click(screen.getByTitle("Align top")); + + await new Promise((r) => setTimeout(r, 0)); + + editor.blur(); + + // should right align horizontally and top vertically after resize + resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]); + expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(` + Array [ + 424, + -539, + ] + `); + }); }); }); diff --git a/src/tests/resize.test.tsx b/src/tests/resize.test.tsx index 4e553825..12fb86be 100644 --- a/src/tests/resize.test.tsx +++ b/src/tests/resize.test.tsx @@ -3,18 +3,13 @@ import { render } from "./test-utils"; import App from "../components/App"; import * as Renderer from "../renderer/renderScene"; import { reseed } from "../random"; -import { UI, Pointer, Keyboard, KeyboardModifiers } from "./helpers/ui"; -import { - getTransformHandles, - TransformHandleDirection, -} from "../element/transformHandles"; -import { ExcalidrawElement, ExcalidrawTextElement } from "../element/types"; +import { UI, Keyboard } from "./helpers/ui"; +import { resize } from "./utils"; +import { ExcalidrawTextElement } from "../element/types"; import ExcalidrawApp from "../excalidraw-app"; import { API } from "./helpers/api"; import { KEYS } from "../keys"; -const mouse = new Pointer("mouse"); - // Unmount ReactDOM from root ReactDOM.unmountComponentAtNode(document.getElementById("root")!); @@ -127,26 +122,6 @@ describe("resize rectangle ellipses and diamond elements", () => { ); }); -const resize = ( - element: ExcalidrawElement, - handleDir: TransformHandleDirection, - mouseMove: [number, number], - keyboardModifiers: KeyboardModifiers = {}, -) => { - mouse.select(element); - const handle = getTransformHandles(element, h.state.zoom, "mouse")[ - handleDir - ]!; - const clientX = handle[0] + handle[2] / 2; - const clientY = handle[1] + handle[3] / 2; - Keyboard.withModifierKeys(keyboardModifiers, () => { - mouse.reset(); - mouse.down(clientX, clientY); - mouse.move(mouseMove[0], mouseMove[1]); - mouse.up(); - }); -}; - describe("Test text element", () => { it("should update font size via keyboard", async () => { await render(); diff --git a/src/tests/utils.ts b/src/tests/utils.ts new file mode 100644 index 00000000..4e533d56 --- /dev/null +++ b/src/tests/utils.ts @@ -0,0 +1,29 @@ +import { + getTransformHandles, + TransformHandleDirection, +} from "../element/transformHandles"; +import { ExcalidrawElement } from "../element/types"; +import { Keyboard, KeyboardModifiers, Pointer } from "./helpers/ui"; + +const mouse = new Pointer("mouse"); +const { h } = window; + +export const resize = ( + element: ExcalidrawElement, + handleDir: TransformHandleDirection, + mouseMove: [number, number], + keyboardModifiers: KeyboardModifiers = {}, +) => { + mouse.select(element); + const handle = getTransformHandles(element, h.state.zoom, "mouse")[ + handleDir + ]!; + const clientX = handle[0] + handle[2] / 2; + const clientY = handle[1] + handle[3] / 2; + Keyboard.withModifierKeys(keyboardModifiers, () => { + mouse.reset(); + mouse.down(clientX, clientY); + mouse.move(mouseMove[0], mouseMove[1]); + mouse.up(); + }); +};