Merge remote-tracking branch 'origin/release' into danieljgeiger-mathjax
This commit is contained in:
commit
38b3d90fa6
@ -3,7 +3,11 @@ import ExcalidrawApp from "../excalidraw-app";
|
|||||||
import { GlobalTestState, render, screen } from "../tests/test-utils";
|
import { GlobalTestState, render, screen } from "../tests/test-utils";
|
||||||
import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
|
import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
|
||||||
import { CODES, KEYS } from "../keys";
|
import { CODES, KEYS } from "../keys";
|
||||||
import { fireEvent } from "../tests/test-utils";
|
import {
|
||||||
|
fireEvent,
|
||||||
|
mockBoundingClientRect,
|
||||||
|
restoreOriginalGetBoundingClientRect,
|
||||||
|
} from "../tests/test-utils";
|
||||||
import { queryByText } from "@testing-library/react";
|
import { queryByText } from "@testing-library/react";
|
||||||
|
|
||||||
import { FONT_FAMILY } from "../constants";
|
import { FONT_FAMILY } from "../constants";
|
||||||
@ -221,11 +225,19 @@ describe("textWysiwyg", () => {
|
|||||||
|
|
||||||
describe("Test container-unbound text", () => {
|
describe("Test container-unbound text", () => {
|
||||||
const { h } = window;
|
const { h } = window;
|
||||||
|
const dimensions = { height: 400, width: 800 };
|
||||||
|
|
||||||
let textarea: HTMLTextAreaElement;
|
let textarea: HTMLTextAreaElement;
|
||||||
let textElement: ExcalidrawTextElement;
|
let textElement: ExcalidrawTextElement;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
mockBoundingClientRect(dimensions);
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await render(<ExcalidrawApp />);
|
await render(<ExcalidrawApp />);
|
||||||
|
//@ts-ignore
|
||||||
|
h.app.refreshDeviceState(h.app.excalidrawContainerRef.current!);
|
||||||
|
|
||||||
textElement = UI.createElement("text");
|
textElement = UI.createElement("text");
|
||||||
|
|
||||||
@ -235,6 +247,10 @@ describe("textWysiwyg", () => {
|
|||||||
)!;
|
)!;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
restoreOriginalGetBoundingClientRect();
|
||||||
|
});
|
||||||
|
|
||||||
it("should add a tab at the start of the first line", () => {
|
it("should add a tab at the start of the first line", () => {
|
||||||
const event = new KeyboardEvent("keydown", { key: KEYS.TAB });
|
const event = new KeyboardEvent("keydown", { key: KEYS.TAB });
|
||||||
textarea.value = "Line#1\nLine#2";
|
textarea.value = "Line#1\nLine#2";
|
||||||
@ -433,6 +449,27 @@ describe("textWysiwyg", () => {
|
|||||||
);
|
);
|
||||||
expect(h.state.zoom.value).toBe(1);
|
expect(h.state.zoom.value).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("text should never go beyond max width", async () => {
|
||||||
|
UI.clickTool("text");
|
||||||
|
mouse.clickAt(750, 300);
|
||||||
|
|
||||||
|
textarea = document.querySelector(
|
||||||
|
".excalidraw-textEditorContainer > textarea",
|
||||||
|
)!;
|
||||||
|
fireEvent.change(textarea, {
|
||||||
|
target: {
|
||||||
|
value:
|
||||||
|
"Excalidraw is an opensource virtual collaborative whiteboard for sketching hand-drawn like diagrams!",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
textarea.dispatchEvent(new Event("input"));
|
||||||
|
await new Promise((cb) => setTimeout(cb, 0));
|
||||||
|
textarea.blur();
|
||||||
|
expect(textarea.style.width).toBe("792px");
|
||||||
|
expect(h.elements[0].width).toBe(1000);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Test container-bound text", () => {
|
describe("Test container-bound text", () => {
|
||||||
@ -631,11 +668,11 @@ describe("textWysiwyg", () => {
|
|||||||
["freedraw", "line"].forEach((type: any) => {
|
["freedraw", "line"].forEach((type: any) => {
|
||||||
it(`shouldn't create text element when pressing 'Enter' key on ${type} `, async () => {
|
it(`shouldn't create text element when pressing 'Enter' key on ${type} `, async () => {
|
||||||
h.elements = [];
|
h.elements = [];
|
||||||
const elemnet = UI.createElement(type, {
|
const element = UI.createElement(type, {
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 50,
|
height: 50,
|
||||||
});
|
});
|
||||||
API.setSelectedElements([elemnet]);
|
API.setSelectedElements([element]);
|
||||||
Keyboard.keyPress(KEYS.ENTER);
|
Keyboard.keyPress(KEYS.ENTER);
|
||||||
expect(h.elements.length).toBe(1);
|
expect(h.elements.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
@ -179,6 +179,10 @@ export const textWysiwyg = ({
|
|||||||
let textElementHeight = Math.max(updatedTextElement.height, maxHeight);
|
let textElementHeight = Math.max(updatedTextElement.height, maxHeight);
|
||||||
|
|
||||||
if (container && updatedTextElement.containerId) {
|
if (container && updatedTextElement.containerId) {
|
||||||
|
textElementHeight = Math.min(
|
||||||
|
getMaxContainerHeight(container),
|
||||||
|
textElementHeight,
|
||||||
|
);
|
||||||
if (isArrowElement(container)) {
|
if (isArrowElement(container)) {
|
||||||
const boundTextCoords =
|
const boundTextCoords =
|
||||||
LinearElementEditor.getBoundTextElementPosition(
|
LinearElementEditor.getBoundTextElementPosition(
|
||||||
@ -187,6 +191,8 @@ export const textWysiwyg = ({
|
|||||||
);
|
);
|
||||||
coordX = boundTextCoords.x;
|
coordX = boundTextCoords.x;
|
||||||
coordY = boundTextCoords.y;
|
coordY = boundTextCoords.y;
|
||||||
|
} else {
|
||||||
|
coordX = Math.max(coordX, getContainerCoords(container).x);
|
||||||
}
|
}
|
||||||
const propertiesUpdated = textPropertiesUpdated(
|
const propertiesUpdated = textPropertiesUpdated(
|
||||||
updatedTextElement,
|
updatedTextElement,
|
||||||
@ -294,8 +300,14 @@ export const textWysiwyg = ({
|
|||||||
const lineHeight = updatedTextElement.containerId
|
const lineHeight = updatedTextElement.containerId
|
||||||
? approxLineHeight
|
? approxLineHeight
|
||||||
: eMetrics.height / lines.length;
|
: eMetrics.height / lines.length;
|
||||||
|
let transformWidth = updatedTextElement.width;
|
||||||
if (!container) {
|
if (!container) {
|
||||||
maxWidth = (appState.width - 8 - viewportX) / appState.zoom.value;
|
maxWidth = (appState.width - 8 - viewportX) / appState.zoom.value;
|
||||||
|
textElementWidth = Math.min(textElementWidth, maxWidth);
|
||||||
|
} else if (isFirefox || isSafari) {
|
||||||
|
// As firefox, Safari needs little higher dimensions on DOM
|
||||||
|
textElementWidth += 0.5;
|
||||||
|
transformWidth += 0.5;
|
||||||
}
|
}
|
||||||
// Horizontal offset in case updatedTextElement has a non-WYSIWYG subtype
|
// Horizontal offset in case updatedTextElement has a non-WYSIWYG subtype
|
||||||
const offWidth = container
|
const offWidth = container
|
||||||
@ -312,13 +324,6 @@ export const textWysiwyg = ({
|
|||||||
? offWidth / 2
|
? offWidth / 2
|
||||||
: 0;
|
: 0;
|
||||||
const { width: w, height: h } = updatedTextElement;
|
const { width: w, height: h } = updatedTextElement;
|
||||||
|
|
||||||
let transformWidth = updatedTextElement.width;
|
|
||||||
// As firefox, Safari needs little higher dimensions on DOM
|
|
||||||
if (isFirefox || isSafari) {
|
|
||||||
textElementWidth += 0.5;
|
|
||||||
transformWidth += 0.5;
|
|
||||||
}
|
|
||||||
// Make sure text editor height doesn't go beyond viewport
|
// Make sure text editor height doesn't go beyond viewport
|
||||||
const editorMaxHeight =
|
const editorMaxHeight =
|
||||||
(appState.height - viewportY) / appState.zoom.value;
|
(appState.height - viewportY) / appState.zoom.value;
|
||||||
|
@ -1307,7 +1307,6 @@ export const renderElementToSvg = (
|
|||||||
);
|
);
|
||||||
const lines = element.text.replace(/\r\n?/g, "\n").split("\n");
|
const lines = element.text.replace(/\r\n?/g, "\n").split("\n");
|
||||||
const lineHeight = element.height / lines.length;
|
const lineHeight = element.height / lines.length;
|
||||||
const verticalOffset = element.height;
|
|
||||||
const horizontalOffset =
|
const horizontalOffset =
|
||||||
element.textAlign === "center"
|
element.textAlign === "center"
|
||||||
? element.width / 2
|
? element.width / 2
|
||||||
@ -1325,13 +1324,14 @@ export const renderElementToSvg = (
|
|||||||
const text = svgRoot.ownerDocument!.createElementNS(SVG_NS, "text");
|
const text = svgRoot.ownerDocument!.createElementNS(SVG_NS, "text");
|
||||||
text.textContent = lines[i];
|
text.textContent = lines[i];
|
||||||
text.setAttribute("x", `${horizontalOffset}`);
|
text.setAttribute("x", `${horizontalOffset}`);
|
||||||
text.setAttribute("y", `${(i + 1) * lineHeight - verticalOffset}`);
|
text.setAttribute("y", `${i * lineHeight}`);
|
||||||
text.setAttribute("font-family", getFontFamilyString(element));
|
text.setAttribute("font-family", getFontFamilyString(element));
|
||||||
text.setAttribute("font-size", `${element.fontSize}px`);
|
text.setAttribute("font-size", `${element.fontSize}px`);
|
||||||
text.setAttribute("fill", element.strokeColor);
|
text.setAttribute("fill", element.strokeColor);
|
||||||
text.setAttribute("text-anchor", textAnchor);
|
text.setAttribute("text-anchor", textAnchor);
|
||||||
text.setAttribute("style", "white-space: pre;");
|
text.setAttribute("style", "white-space: pre;");
|
||||||
text.setAttribute("direction", direction);
|
text.setAttribute("direction", direction);
|
||||||
|
text.setAttribute("dominant-baseline", "text-before-edge");
|
||||||
node.appendChild(text);
|
node.appendChild(text);
|
||||||
}
|
}
|
||||||
root.appendChild(node);
|
root.appendChild(node);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user