فهرست منبع

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
Aakansha Doshi 3 سال پیش
والد
کامیت
ef62390841
6فایلهای تغییر یافته به همراه62 افزوده شده و 31 حذف شده
  1. 16 3
      src/actions/actionProperties.tsx
  2. 11 1
      src/actions/actionStyles.ts
  3. 1 1
      src/constants.ts
  4. 5 5
      src/element/newElement.ts
  5. 19 14
      src/element/textElement.ts
  6. 10 7
      src/element/textWysiwyg.tsx

+ 16 - 3
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;
         }
 

+ 11 - 1
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;
         }

+ 1 - 1
src/constants.ts

@@ -182,4 +182,4 @@ export const VERSIONS = {
   excalidrawLibrary: 2,
 } as const;
 
-export const PADDING = 30;
+export const BOUND_TEXT_PADDING = 30;

+ 5 - 5
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<ExcalidrawGenericElement, "id" | "type" | "isDeleted" | "updated">,
@@ -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 });

+ 19 - 14
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<string> = [];
   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) => {

+ 10 - 7
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) {