Repository: excalidraw/excalidraw
File: src/element/textElement.ts (TypeScript)

Code before:
      const updatedY =
        !isArrowElement(container) &&
        (transformHandleType === "ne" ||
          transformHandleType === "nw" ||
          transformHandleType === "n")
          ? container.y - diff
          : container.y;
      mutateElement(container, {
        height: containerHeight,
        y: updatedY,
      });
    }

    mutateElement(textElement, {
      text,
      width: nextWidth,
      height: nextHeight,

      baseline: nextBaseLine,
    });
    if (!isArrowElement(container)) {
      const { x, y } = computeBoundTextPosition(
        container,
        textElement as ExcalidrawTextElementWithContainer,
      );
      mutateElement(textElement, { x, y });
    }
  }
};

const computeBoundTextPosition = (
  container: ExcalidrawElement,
  boundTextElement: ExcalidrawTextElementWithContainer,
) => {
  const containerCoords = getContainerCoords(container);
  const maxContainerHeight = getMaxContainerHeight(container);
  const maxContainerWidth = getMaxContainerWidth(container);
  const padding = container.type === "ellipse" ? 0 : BOUND_TEXT_PADDING;

  let x;
  let y;
  if (boundTextElement.verticalAlign === VERTICAL_ALIGN.TOP) {
    y = containerCoords.y + padding;
  } else if (boundTextElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
    y =
      containerCoords.y +
      (maxContainerHeight - boundTextElement.height + padding);
  } else {
    y =
      containerCoords.y +
      (maxContainerHeight / 2 - boundTextElement.height / 2 + padding);

Review comment (performance):
I'd get in the habit of not destructuring + initializing variables + constructing new objects, if not necessary. Here, you can just pass the `computeBoundTextPosition()` as 2nd arg to `mtuateElement` directly.

Not critical, but still somewhat a hot path.

Code after:
      mutateElement(container, {
        height: containerHeight,
        y: updatedY,
      });
    }

    mutateElement(textElement, {
      text,
      width: nextWidth,
      height: nextHeight,
      baseline: nextBaseLine,
    });

    if (!isArrowElement(container)) {
      mutateElement(
        textElement,
        computeBoundTextPosition(
          container,
          textElement as ExcalidrawTextElementWithContainer,
        ),
      );
    }
  }
};

const computeBoundTextPosition = (
  container: ExcalidrawElement,
  boundTextElement: ExcalidrawTextElementWithContainer,
) => {
  const containerCoords = getContainerCoords(container);
  const maxContainerHeight = getMaxContainerHeight(container);
  const maxContainerWidth = getMaxContainerWidth(container);
  const padding = container.type === "ellipse" ? 0 : BOUND_TEXT_PADDING;

  let x;
  let y;
  if (boundTextElement.verticalAlign === VERTICAL_ALIGN.TOP) {
    y = containerCoords.y + padding;
  } else if (boundTextElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
    y =
      containerCoords.y +
      (maxContainerHeight - boundTextElement.height + padding);
  } else {
    y =
      containerCoords.y +
      (maxContainerHeight / 2 - boundTextElement.height / 2 + padding);
  }
  if (boundTextElement.textAlign === TEXT_ALIGN.LEFT) {
    x = containerCoords.x + padding;
  } else if (boundTextElement.textAlign === TEXT_ALIGN.RIGHT) {
    x =