fix: cleanup getMaxContainerHeight and getMaxContainerWidth (#6519)

* fix: cleanup getMaxContainerHeight and getMaxContainerWidth

* rename getMaxContainerWidth -> getBoundTextMaxMaxWidth and getMaxContainerHeight -> getBoundTextMaxHeight

* add specs
This commit is contained in:
Aakansha Doshi 2023-04-25 18:06:23 +05:30 committed by GitHub
parent dae81c0a2c
commit da8dd389a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 96 additions and 56 deletions

View File

@ -33,7 +33,7 @@ import {
measureText,
normalizeText,
wrapText,
getMaxContainerWidth,
getBoundTextMaxWidth,
getDefaultLineHeight,
} from "./textElement";
import {
@ -310,7 +310,7 @@ export const refreshTextDimensions = (
text = wrapText(
text,
getFontString(textElement),
getMaxContainerWidth(container),
getBoundTextMaxWidth(container),
);
}
const dimensions = getAdjustedDimensions(textElement, text);

View File

@ -44,10 +44,10 @@ import {
getBoundTextElementId,
getContainerElement,
handleBindTextResize,
getMaxContainerWidth,
getBoundTextMaxWidth,
getApproxMinLineHeight,
measureText,
getMaxContainerHeight,
getBoundTextMaxHeight,
} from "./textElement";
export const normalizeAngle = (angle: number): number => {
@ -204,7 +204,7 @@ const measureFontSizeFromWidth = (
if (hasContainer) {
const container = getContainerElement(element);
if (container) {
width = getMaxContainerWidth(container);
width = getBoundTextMaxWidth(container);
}
}
const nextFontSize = element.fontSize * (nextWidth / width);
@ -435,8 +435,8 @@ export const resizeSingleElement = (
const nextFont = measureFontSizeFromWidth(
boundTextElement,
getMaxContainerWidth(updatedElement),
getMaxContainerHeight(updatedElement),
getBoundTextMaxWidth(updatedElement),
getBoundTextMaxHeight(updatedElement, boundTextElement),
);
if (nextFont === null) {
return;
@ -718,10 +718,10 @@ const resizeMultipleElements = (
const metrics = measureFontSizeFromWidth(
boundTextElement ?? (element.orig as ExcalidrawTextElement),
boundTextElement
? getMaxContainerWidth(updatedElement)
? getBoundTextMaxWidth(updatedElement)
: updatedElement.width,
boundTextElement
? getMaxContainerHeight(updatedElement)
? getBoundTextMaxHeight(updatedElement, boundTextElement)
: updatedElement.height,
);

View File

@ -3,15 +3,15 @@ import { API } from "../tests/helpers/api";
import {
computeContainerDimensionForBoundText,
getContainerCoords,
getMaxContainerWidth,
getMaxContainerHeight,
getBoundTextMaxWidth,
getBoundTextMaxHeight,
wrapText,
detectLineHeight,
getLineHeightInPx,
getDefaultLineHeight,
parseTokens,
} from "./textElement";
import { FontString } from "./types";
import { ExcalidrawTextElementWithContainer, FontString } from "./types";
describe("Test wrapText", () => {
const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
@ -311,7 +311,7 @@ describe("Test measureText", () => {
});
});
describe("Test getMaxContainerWidth", () => {
describe("Test getBoundTextMaxWidth", () => {
const params = {
width: 178,
height: 194,
@ -319,39 +319,76 @@ describe("Test measureText", () => {
it("should return max width when container is rectangle", () => {
const container = API.createElement({ type: "rectangle", ...params });
expect(getMaxContainerWidth(container)).toBe(168);
expect(getBoundTextMaxWidth(container)).toBe(168);
});
it("should return max width when container is ellipse", () => {
const container = API.createElement({ type: "ellipse", ...params });
expect(getMaxContainerWidth(container)).toBe(116);
expect(getBoundTextMaxWidth(container)).toBe(116);
});
it("should return max width when container is diamond", () => {
const container = API.createElement({ type: "diamond", ...params });
expect(getMaxContainerWidth(container)).toBe(79);
expect(getBoundTextMaxWidth(container)).toBe(79);
});
});
describe("Test getMaxContainerHeight", () => {
describe("Test getBoundTextMaxHeight", () => {
const params = {
width: 178,
height: 194,
id: '"container-id',
};
const boundTextElement = API.createElement({
type: "text",
id: "text-id",
x: 560.51171875,
y: 202.033203125,
width: 154,
height: 175,
fontSize: 20,
fontFamily: 1,
text: "Excalidraw is a\nvirtual \nopensource \nwhiteboard for \nsketching \nhand-drawn like\ndiagrams",
textAlign: "center",
verticalAlign: "middle",
containerId: params.id,
}) as ExcalidrawTextElementWithContainer;
it("should return max height when container is rectangle", () => {
const container = API.createElement({ type: "rectangle", ...params });
expect(getMaxContainerHeight(container)).toBe(184);
expect(getBoundTextMaxHeight(container, boundTextElement)).toBe(184);
});
it("should return max height when container is ellipse", () => {
const container = API.createElement({ type: "ellipse", ...params });
expect(getMaxContainerHeight(container)).toBe(127);
expect(getBoundTextMaxHeight(container, boundTextElement)).toBe(127);
});
it("should return max height when container is diamond", () => {
const container = API.createElement({ type: "diamond", ...params });
expect(getMaxContainerHeight(container)).toBe(87);
expect(getBoundTextMaxHeight(container, boundTextElement)).toBe(87);
});
it("should return max height when container is arrow", () => {
const container = API.createElement({
type: "arrow",
...params,
});
expect(getBoundTextMaxHeight(container, boundTextElement)).toBe(194);
});
it("should return max height when container is arrow and height is less than threshold", () => {
const container = API.createElement({
type: "arrow",
...params,
height: 70,
boundElements: [{ type: "text", id: "text-id" }],
});
expect(getBoundTextMaxHeight(container, boundTextElement)).toBe(
boundTextElement.height,
);
});
});
});

View File

@ -65,7 +65,7 @@ export const redrawTextBoundingBox = (
boundTextUpdates.text = textElement.text;
if (container) {
maxWidth = getMaxContainerWidth(container);
maxWidth = getBoundTextMaxWidth(container);
boundTextUpdates.text = wrapText(
textElement.originalText,
getFontString(textElement),
@ -84,7 +84,10 @@ export const redrawTextBoundingBox = (
if (container) {
const containerDims = getContainerDims(container);
const maxContainerHeight = getMaxContainerHeight(container);
const maxContainerHeight = getBoundTextMaxHeight(
container,
textElement as ExcalidrawTextElementWithContainer,
);
let nextHeight = containerDims.height;
if (metrics.height > maxContainerHeight) {
@ -173,8 +176,11 @@ export const handleBindTextResize = (
let nextHeight = textElement.height;
let nextWidth = textElement.width;
const containerDims = getContainerDims(container);
const maxWidth = getMaxContainerWidth(container);
const maxHeight = getMaxContainerHeight(container);
const maxWidth = getBoundTextMaxWidth(container);
const maxHeight = getBoundTextMaxHeight(
container,
textElement as ExcalidrawTextElementWithContainer,
);
let containerHeight = containerDims.height;
let nextBaseLine = textElement.baseline;
if (transformHandleType !== "n" && transformHandleType !== "s") {
@ -246,8 +252,8 @@ export const computeBoundTextPosition = (
);
}
const containerCoords = getContainerCoords(container);
const maxContainerHeight = getMaxContainerHeight(container);
const maxContainerWidth = getMaxContainerWidth(container);
const maxContainerHeight = getBoundTextMaxHeight(container, boundTextElement);
const maxContainerWidth = getBoundTextMaxWidth(container);
let x;
let y;
@ -880,18 +886,10 @@ export const computeContainerDimensionForBoundText = (
return dimension + padding;
};
export const getMaxContainerWidth = (container: ExcalidrawElement) => {
export const getBoundTextMaxWidth = (container: ExcalidrawElement) => {
const width = getContainerDims(container).width;
if (isArrowElement(container)) {
const containerWidth = width - BOUND_TEXT_PADDING * 8 * 2;
if (containerWidth <= 0) {
const boundText = getBoundTextElement(container);
if (boundText) {
return boundText.width;
}
return BOUND_TEXT_PADDING * 8 * 2;
}
return containerWidth;
return width - BOUND_TEXT_PADDING * 8 * 2;
}
if (container.type === "ellipse") {
@ -908,16 +906,15 @@ export const getMaxContainerWidth = (container: ExcalidrawElement) => {
return width - BOUND_TEXT_PADDING * 2;
};
export const getMaxContainerHeight = (container: ExcalidrawElement) => {
export const getBoundTextMaxHeight = (
container: ExcalidrawElement,
boundTextElement: ExcalidrawTextElementWithContainer,
) => {
const height = getContainerDims(container).height;
if (isArrowElement(container)) {
const containerHeight = height - BOUND_TEXT_PADDING * 8 * 2;
if (containerHeight <= 0) {
const boundText = getBoundTextElement(container);
if (boundText) {
return boundText.height;
}
return BOUND_TEXT_PADDING * 8 * 2;
return boundTextElement.height;
}
return height;
}

View File

@ -32,8 +32,8 @@ import {
normalizeText,
redrawTextBoundingBox,
wrapText,
getMaxContainerHeight,
getMaxContainerWidth,
getBoundTextMaxHeight,
getBoundTextMaxWidth,
computeContainerDimensionForBoundText,
detectLineHeight,
} from "./textElement";
@ -205,8 +205,11 @@ export const textWysiwyg = ({
}
}
maxWidth = getMaxContainerWidth(container);
maxHeight = getMaxContainerHeight(container);
maxWidth = getBoundTextMaxWidth(container);
maxHeight = getBoundTextMaxHeight(
container,
updatedTextElement as ExcalidrawTextElementWithContainer,
);
// autogrow container height if text exceeds
if (!isArrowElement(container) && textElementHeight > maxHeight) {
@ -377,7 +380,7 @@ export const textWysiwyg = ({
const wrappedText = wrapText(
`${editable.value}${data}`,
font,
getMaxContainerWidth(container),
getBoundTextMaxWidth(container),
);
const width = getTextWidth(wrappedText, font);
editable.style.width = `${width}px`;
@ -394,7 +397,7 @@ export const textWysiwyg = ({
const wrappedText = wrapText(
normalizeText(editable.value),
font,
getMaxContainerWidth(container!),
getBoundTextMaxWidth(container!),
);
const { width, height } = measureText(
wrappedText,

View File

@ -44,8 +44,8 @@ import {
getContainerCoords,
getContainerElement,
getLineHeightInPx,
getMaxContainerHeight,
getMaxContainerWidth,
getBoundTextMaxHeight,
getBoundTextMaxWidth,
} from "../element/textElement";
import { LinearElementEditor } from "../element/linearElementEditor";
@ -868,14 +868,17 @@ const drawElementFromCanvas = (
"true" &&
hasBoundTextElement(element)
) {
const textElement = getBoundTextElement(
element,
) as ExcalidrawTextElementWithContainer;
const coords = getContainerCoords(element);
context.strokeStyle = "#c92a2a";
context.lineWidth = 3;
context.strokeRect(
(coords.x + renderConfig.scrollX) * window.devicePixelRatio,
(coords.y + renderConfig.scrollY) * window.devicePixelRatio,
getMaxContainerWidth(element) * window.devicePixelRatio,
getMaxContainerHeight(element) * window.devicePixelRatio,
getBoundTextMaxWidth(element) * window.devicePixelRatio,
getBoundTextMaxHeight(element, textElement) * window.devicePixelRatio,
);
}
}

View File

@ -20,7 +20,7 @@ import { resize, rotate } from "./utils";
import {
getBoundTextElementPosition,
wrapText,
getMaxContainerWidth,
getBoundTextMaxWidth,
} from "../element/textElement";
import * as textElementUtils from "../element/textElement";
import { ROUNDNESS, VERTICAL_ALIGN } from "../constants";
@ -729,7 +729,7 @@ describe("Test Linear Elements", () => {
type: "text",
x: 0,
y: 0,
text: wrapText(text, font, getMaxContainerWidth(container)),
text: wrapText(text, font, getBoundTextMaxWidth(container)),
containerId: container.id,
width: 30,
height: 20,
@ -1149,7 +1149,7 @@ describe("Test Linear Elements", () => {
expect(rect.x).toBe(400);
expect(rect.y).toBe(0);
expect(
wrapText(textElement.originalText, font, getMaxContainerWidth(arrow)),
wrapText(textElement.originalText, font, getBoundTextMaxWidth(arrow)),
).toMatchInlineSnapshot(`
"Online whiteboard collaboration
made easy"
@ -1172,7 +1172,7 @@ describe("Test Linear Elements", () => {
false,
);
expect(
wrapText(textElement.originalText, font, getMaxContainerWidth(arrow)),
wrapText(textElement.originalText, font, getBoundTextMaxWidth(arrow)),
).toMatchInlineSnapshot(`
"Online whiteboard
collaboration made