fix: compute dimensions of container correctly when text pasted on container (#5845)

* fix: compute dimensions of container correctly when text pasted on container

* add test

* remove only
This commit is contained in:
Aakansha Doshi 2022-11-08 19:50:41 +05:30 committed by GitHub
parent e1c5c706c6
commit e201e79cd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 7 deletions

View File

@ -169,8 +169,7 @@ const getAdjustedDimensions = (
let maxWidth = null;
const container = getContainerElement(element);
if (container) {
const containerDims = getContainerDims(container);
maxWidth = containerDims.width - BOUND_TEXT_PADDING * 2;
maxWidth = getMaxContainerWidth(container);
}
const {
width: nextWidth,
@ -258,7 +257,6 @@ export const refreshTextDimensions = (
) => {
const container = getContainerElement(textElement);
if (container) {
// text = wrapText(text, getFontString(textElement), container.width);
text = wrapText(
text,
getFontString(textElement),

View File

@ -19,13 +19,12 @@ export const redrawTextBoundingBox = (
) => {
let maxWidth = undefined;
let text = textElement.text;
if (container) {
maxWidth = getMaxContainerWidth(container);
text = wrapText(
textElement.originalText,
getFontString(textElement),
getMaxContainerWidth(container),
maxWidth,
);
}
const metrics = measureText(
@ -230,10 +229,9 @@ export const measureText = (
const baseline = span.offsetTop + span.offsetHeight;
// Since span adds 1px extra width to the container
const width = container.offsetWidth + 1;
const height = container.offsetHeight;
document.body.removeChild(container);
document.body.removeChild(container);
return { width, height, baseline };
};

View File

@ -10,11 +10,13 @@ import { BOUND_TEXT_PADDING, FONT_FAMILY } from "../constants";
import {
ExcalidrawTextElement,
ExcalidrawTextElementWithContainer,
FontString,
} from "./types";
import * as textElementUtils from "./textElement";
import { API } from "../tests/helpers/api";
import { mutateElement } from "./mutateElement";
import { resize } from "../tests/utils";
import { getMaxContainerWidth } from "./newElement";
// Unmount ReactDOM from root
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
@ -876,5 +878,44 @@ describe("textWysiwyg", () => {
]
`);
});
it("should compute the dimensions correctly when text pasted", async () => {
Keyboard.keyPress(KEYS.ENTER);
const editor = document.querySelector(
".excalidraw-textEditorContainer > textarea",
) as HTMLTextAreaElement;
await new Promise((r) => setTimeout(r, 0));
const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
const wrappedText = textElementUtils.wrapText(
"Wikipedia is hosted by the Wikimedia Foundation, a non-profit organization that also hosts a range of other projects.",
font,
getMaxContainerWidth(rectangle),
);
jest
.spyOn(textElementUtils, "measureText")
.mockImplementation((text, font, maxWidth) => {
if (text === wrappedText) {
return { width: rectangle.width, height: 200, baseline: 30 };
}
return { width: 0, height: 0, baseline: 0 };
});
//@ts-ignore
editor.onpaste({
preventDefault: () => {},
//@ts-ignore
clipboardData: {
getData: () =>
"Wikipedia is hosted by the Wikimedia Foundation, a non-profit organization that also hosts a range of other projects.",
},
});
await new Promise((cb) => setTimeout(cb, 0));
editor.blur();
expect(rectangle.width).toBe(110);
expect(rectangle.height).toBe(210);
});
});
});

View File

@ -20,6 +20,7 @@ import {
getBoundTextElementId,
getContainerDims,
getContainerElement,
measureText,
wrapText,
} from "./textElement";
import {
@ -29,6 +30,7 @@ import {
import { actionZoomIn, actionZoomOut } from "../actions/actionCanvas";
import App from "../components/App";
import { getMaxContainerWidth } from "./newElement";
import { parseClipboard } from "../clipboard";
const normalizeText = (text: string) => {
return (
@ -275,6 +277,31 @@ export const textWysiwyg = ({
updateWysiwygStyle();
if (onChange) {
editable.onpaste = async (event) => {
event.preventDefault();
const clipboardData = await parseClipboard(event);
if (!clipboardData.text) {
return;
}
const data = normalizeText(clipboardData.text);
const container = getContainerElement(element);
const font = getFontString({
fontSize: app.state.currentItemFontSize,
fontFamily: app.state.currentItemFontFamily,
});
const wrappedText = wrapText(
data,
font,
getMaxContainerWidth(container!),
);
const dimensions = measureText(wrappedText, font);
editable.style.height = `${dimensions.height}px`;
if (data) {
onChange(wrappedText);
}
};
editable.oninput = () => {
const updatedTextElement = Scene.getScene(element)?.getElement(
id,