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:
parent
e1c5c706c6
commit
e201e79cd0
@ -169,8 +169,7 @@ const getAdjustedDimensions = (
|
|||||||
let maxWidth = null;
|
let maxWidth = null;
|
||||||
const container = getContainerElement(element);
|
const container = getContainerElement(element);
|
||||||
if (container) {
|
if (container) {
|
||||||
const containerDims = getContainerDims(container);
|
maxWidth = getMaxContainerWidth(container);
|
||||||
maxWidth = containerDims.width - BOUND_TEXT_PADDING * 2;
|
|
||||||
}
|
}
|
||||||
const {
|
const {
|
||||||
width: nextWidth,
|
width: nextWidth,
|
||||||
@ -258,7 +257,6 @@ export const refreshTextDimensions = (
|
|||||||
) => {
|
) => {
|
||||||
const container = getContainerElement(textElement);
|
const container = getContainerElement(textElement);
|
||||||
if (container) {
|
if (container) {
|
||||||
// text = wrapText(text, getFontString(textElement), container.width);
|
|
||||||
text = wrapText(
|
text = wrapText(
|
||||||
text,
|
text,
|
||||||
getFontString(textElement),
|
getFontString(textElement),
|
||||||
|
@ -19,13 +19,12 @@ export const redrawTextBoundingBox = (
|
|||||||
) => {
|
) => {
|
||||||
let maxWidth = undefined;
|
let maxWidth = undefined;
|
||||||
let text = textElement.text;
|
let text = textElement.text;
|
||||||
|
|
||||||
if (container) {
|
if (container) {
|
||||||
maxWidth = getMaxContainerWidth(container);
|
maxWidth = getMaxContainerWidth(container);
|
||||||
text = wrapText(
|
text = wrapText(
|
||||||
textElement.originalText,
|
textElement.originalText,
|
||||||
getFontString(textElement),
|
getFontString(textElement),
|
||||||
getMaxContainerWidth(container),
|
maxWidth,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const metrics = measureText(
|
const metrics = measureText(
|
||||||
@ -230,10 +229,9 @@ export const measureText = (
|
|||||||
const baseline = span.offsetTop + span.offsetHeight;
|
const baseline = span.offsetTop + span.offsetHeight;
|
||||||
// Since span adds 1px extra width to the container
|
// Since span adds 1px extra width to the container
|
||||||
const width = container.offsetWidth + 1;
|
const width = container.offsetWidth + 1;
|
||||||
|
|
||||||
const height = container.offsetHeight;
|
const height = container.offsetHeight;
|
||||||
document.body.removeChild(container);
|
|
||||||
|
|
||||||
|
document.body.removeChild(container);
|
||||||
return { width, height, baseline };
|
return { width, height, baseline };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,11 +10,13 @@ import { BOUND_TEXT_PADDING, FONT_FAMILY } from "../constants";
|
|||||||
import {
|
import {
|
||||||
ExcalidrawTextElement,
|
ExcalidrawTextElement,
|
||||||
ExcalidrawTextElementWithContainer,
|
ExcalidrawTextElementWithContainer,
|
||||||
|
FontString,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import * as textElementUtils from "./textElement";
|
import * as textElementUtils from "./textElement";
|
||||||
import { API } from "../tests/helpers/api";
|
import { API } from "../tests/helpers/api";
|
||||||
import { mutateElement } from "./mutateElement";
|
import { mutateElement } from "./mutateElement";
|
||||||
import { resize } from "../tests/utils";
|
import { resize } from "../tests/utils";
|
||||||
|
import { getMaxContainerWidth } from "./newElement";
|
||||||
// Unmount ReactDOM from root
|
// Unmount ReactDOM from root
|
||||||
ReactDOM.unmountComponentAtNode(document.getElementById("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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
getBoundTextElementId,
|
getBoundTextElementId,
|
||||||
getContainerDims,
|
getContainerDims,
|
||||||
getContainerElement,
|
getContainerElement,
|
||||||
|
measureText,
|
||||||
wrapText,
|
wrapText,
|
||||||
} from "./textElement";
|
} from "./textElement";
|
||||||
import {
|
import {
|
||||||
@ -29,6 +30,7 @@ import {
|
|||||||
import { actionZoomIn, actionZoomOut } from "../actions/actionCanvas";
|
import { actionZoomIn, actionZoomOut } from "../actions/actionCanvas";
|
||||||
import App from "../components/App";
|
import App from "../components/App";
|
||||||
import { getMaxContainerWidth } from "./newElement";
|
import { getMaxContainerWidth } from "./newElement";
|
||||||
|
import { parseClipboard } from "../clipboard";
|
||||||
|
|
||||||
const normalizeText = (text: string) => {
|
const normalizeText = (text: string) => {
|
||||||
return (
|
return (
|
||||||
@ -275,6 +277,31 @@ export const textWysiwyg = ({
|
|||||||
updateWysiwygStyle();
|
updateWysiwygStyle();
|
||||||
|
|
||||||
if (onChange) {
|
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 = () => {
|
editable.oninput = () => {
|
||||||
const updatedTextElement = Scene.getScene(element)?.getElement(
|
const updatedTextElement = Scene.getScene(element)?.getElement(
|
||||||
id,
|
id,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user