From ef6239084199dc6f5df52c7a8a429b8dc068df93 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Thu, 23 Dec 2021 17:02:35 +0530 Subject: [PATCH] fix: set height correctly when text properties updated while editing in container until first submit (#4469) * fix: set height correctly when text properties updated while editing in container * rename PADDING to BOUND_TEXT_PADDING --- src/actions/actionProperties.tsx | 19 +++++++++++++++--- src/actions/actionStyles.ts | 12 +++++++++++- src/constants.ts | 2 +- src/element/newElement.ts | 10 +++++----- src/element/textElement.ts | 33 ++++++++++++++++++-------------- src/element/textWysiwyg.tsx | 17 +++++++++------- 6 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/actions/actionProperties.tsx b/src/actions/actionProperties.tsx index cc3bbbdb..70b06f1f 100644 --- a/src/actions/actionProperties.tsx +++ b/src/actions/actionProperties.tsx @@ -61,6 +61,7 @@ import { isSomeElementSelected, } from "../scene"; import { hasStrokeColor } from "../scene/comparisons"; +import Scene from "../scene/Scene"; import { register } from "./register"; const changeProperty = ( @@ -431,7 +432,11 @@ export const actionChangeFontSize = register({ const element: ExcalidrawTextElement = newElementWith(el, { fontSize: value, }); - redrawTextBoundingBox(element); + let container = null; + if (el.containerId) { + container = Scene.getScene(el)!.getElement(el.containerId); + } + redrawTextBoundingBox(element, container); return element; } @@ -492,7 +497,11 @@ export const actionChangeFontFamily = register({ const element: ExcalidrawTextElement = newElementWith(el, { fontFamily: value, }); - redrawTextBoundingBox(element); + let container = null; + if (el.containerId) { + container = Scene.getScene(el)!.getElement(el.containerId); + } + redrawTextBoundingBox(element, container); return element; } @@ -556,7 +565,11 @@ export const actionChangeTextAlign = register({ const element: ExcalidrawTextElement = newElementWith(el, { textAlign: value, }); - redrawTextBoundingBox(element); + let container = null; + if (el.containerId) { + container = Scene.getScene(el)!.getElement(el.containerId); + } + redrawTextBoundingBox(element, container); return element; } diff --git a/src/actions/actionStyles.ts b/src/actions/actionStyles.ts index 4a8b54af..5b843c9f 100644 --- a/src/actions/actionStyles.ts +++ b/src/actions/actionStyles.ts @@ -12,6 +12,9 @@ import { DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, } from "../constants"; +import Scene from "../scene/Scene"; +import { isBoundToContainer } from "../element/typeChecks"; +import { ExcalidrawTextElement } from "../element/types"; // `copiedStyles` is exported only for tests. export let copiedStyles: string = "{}"; @@ -61,7 +64,14 @@ export const actionPasteStyles = register({ fontFamily: pastedElement?.fontFamily || DEFAULT_FONT_FAMILY, textAlign: pastedElement?.textAlign || DEFAULT_TEXT_ALIGN, }); - redrawTextBoundingBox(newElement); + let container = null; + + if (isBoundToContainer(element)) { + container = Scene.getScene(element)!.getElement( + element.containerId, + ); + } + redrawTextBoundingBox(element as ExcalidrawTextElement, container); } return newElement; } diff --git a/src/constants.ts b/src/constants.ts index 23f826c6..dfa579d2 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -182,4 +182,4 @@ export const VERSIONS = { excalidrawLibrary: 2, } as const; -export const PADDING = 30; +export const BOUND_TEXT_PADDING = 30; diff --git a/src/element/newElement.ts b/src/element/newElement.ts index 8c995959..f0ab9e4c 100644 --- a/src/element/newElement.ts +++ b/src/element/newElement.ts @@ -24,7 +24,7 @@ import { getResizedElementAbsoluteCoords } from "./bounds"; import { measureText } from "./textElement"; import { isBoundToContainer } from "./typeChecks"; import Scene from "../scene/Scene"; -import { PADDING } from "../constants"; +import { BOUND_TEXT_PADDING } from "../constants"; type ElementConstructorOpts = MarkOptional< Omit, @@ -219,11 +219,11 @@ const getAdjustedDimensions = ( const container = Scene.getScene(element)!.getElement(element.containerId)!; let height = container.height; let width = container.width; - if (nextHeight > height - PADDING * 2) { - height = nextHeight + PADDING * 2; + if (nextHeight > height - BOUND_TEXT_PADDING * 2) { + height = nextHeight + BOUND_TEXT_PADDING * 2; } - if (nextWidth > width - PADDING * 2) { - width = nextWidth + PADDING * 2; + if (nextWidth > width - BOUND_TEXT_PADDING * 2) { + width = nextWidth + BOUND_TEXT_PADDING * 2; } if (height !== container.height || width !== container.width) { mutateElement(container, { height, width }); diff --git a/src/element/textElement.ts b/src/element/textElement.ts index 1b11e654..e4d98941 100644 --- a/src/element/textElement.ts +++ b/src/element/textElement.ts @@ -7,15 +7,17 @@ import { NonDeletedExcalidrawElement, } from "./types"; import { mutateElement } from "./mutateElement"; -import { PADDING } from "../constants"; +import { BOUND_TEXT_PADDING } from "../constants"; import { MaybeTransformHandleType } from "./transformHandles"; import Scene from "../scene/Scene"; -export const redrawTextBoundingBox = (element: ExcalidrawTextElement) => { - let maxWidth; - if (element.containerId) { - maxWidth = element.width; - } +export const redrawTextBoundingBox = ( + element: ExcalidrawTextElement, + container: ExcalidrawElement | null, +) => { + const maxWidth = container + ? container.width - BOUND_TEXT_PADDING * 2 + : undefined; const metrics = measureText( element.originalText, getFontString(element), @@ -87,7 +89,7 @@ export const handleBindTextResize = ( minCharWidthTillNow = getMinCharWidth(getFontString(textElement)); // check if the diff has exceeded min char width needed const diff = Math.abs( - element.width - textElement.width + PADDING * 2, + element.width - textElement.width + BOUND_TEXT_PADDING * 2, ); if (diff >= minCharWidthTillNow) { text = wrapText( @@ -107,8 +109,8 @@ export const handleBindTextResize = ( nextBaseLine = dimensions.baseline; } // increase height in case text element height exceeds - if (nextHeight > element.height - PADDING * 2) { - containerHeight = nextHeight + PADDING * 2; + if (nextHeight > element.height - BOUND_TEXT_PADDING * 2) { + containerHeight = nextHeight + BOUND_TEXT_PADDING * 2; const diff = containerHeight - element.height; // fix the y coord when resizing from ne/nw/n const updatedY = @@ -127,9 +129,9 @@ export const handleBindTextResize = ( mutateElement(textElement, { text, // preserve padding and set width correctly - width: element.width - PADDING * 2, + width: element.width - BOUND_TEXT_PADDING * 2, height: nextHeight, - x: element.x + PADDING, + x: element.x + BOUND_TEXT_PADDING, y: updatedY, baseline: nextBaseLine, }); @@ -207,7 +209,7 @@ export const wrapText = ( font: FontString, containerWidth: number, ) => { - const maxWidth = containerWidth - PADDING * 2; + const maxWidth = containerWidth - BOUND_TEXT_PADDING * 2; const lines: Array = []; const originalLines = text.split("\n"); @@ -343,11 +345,14 @@ export const charWidth = (() => { }; })(); export const getApproxMinLineWidth = (font: FontString) => { - return measureText(DUMMY_TEXT.split("").join("\n"), font).width + PADDING * 2; + return ( + measureText(DUMMY_TEXT.split("").join("\n"), font).width + + BOUND_TEXT_PADDING * 2 + ); }; export const getApproxMinLineHeight = (font: FontString) => { - return getApproxLineHeight(font) + PADDING * 2; + return getApproxLineHeight(font) + BOUND_TEXT_PADDING * 2; }; export const getMinCharWidth = (font: FontString) => { diff --git a/src/element/textWysiwyg.tsx b/src/element/textWysiwyg.tsx index 7a60abce..74bb24ff 100644 --- a/src/element/textWysiwyg.tsx +++ b/src/element/textWysiwyg.tsx @@ -6,7 +6,7 @@ import { } from "../utils"; import Scene from "../scene/Scene"; import { isBoundToContainer, isTextElement } from "./typeChecks"; -import { CLASSES, PADDING } from "../constants"; +import { CLASSES, BOUND_TEXT_PADDING } from "../constants"; import { ExcalidrawBindableElement, ExcalidrawElement, @@ -129,8 +129,11 @@ export const textWysiwyg = ({ approxLineHeight = isTextElement(updatedElement) ? getApproxLineHeight(getFontString(updatedElement)) : 0; - if (updatedElement.height > currentContainer.height - PADDING * 2) { - const nextHeight = updatedElement.height + PADDING * 2; + if ( + updatedElement.height > + currentContainer.height - BOUND_TEXT_PADDING * 2 + ) { + const nextHeight = updatedElement.height + BOUND_TEXT_PADDING * 2; originalContainerHeight = nextHeight; mutateElement(container, { height: nextHeight }); container = { ...container, height: nextHeight }; @@ -141,12 +144,12 @@ export const textWysiwyg = ({ if (!originalContainerHeight) { originalContainerHeight = container.height; } - maxWidth = container.width - PADDING * 2; - maxHeight = container.height - PADDING * 2; + maxWidth = container.width - BOUND_TEXT_PADDING * 2; + maxHeight = container.height - BOUND_TEXT_PADDING * 2; width = maxWidth; // The coordinates of text box set a distance of // 30px to preserve padding - coordX = container.x + PADDING; + coordX = container.x + BOUND_TEXT_PADDING; // autogrow container height if text exceeds if (height > maxHeight) { const diff = Math.min(height - maxHeight, approxLineHeight); @@ -465,7 +468,7 @@ export const textWysiwyg = ({ height: editorHeight, width: Number(editable.style.width.slice(0, -2)), // preserve padding - x: container.x + PADDING, + x: container.x + BOUND_TEXT_PADDING, }); const boundTextElementId = getBoundTextElementId(container); if (!boundTextElementId || boundTextElementId !== element.id) {