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

Code before:
            points: getArrowLocalFixedPoints(element, elementsMap),
          }
        : {
            x: element.x + (rotatedCX - cx),
            y: element.y + (rotatedCY - cy),
            angle: normalizeRadians((centerAngle + origAngle) as Radians),
          };

      scene.mutateElement(element, updates);

      updateBoundElements(element, scene, {
        simultaneouslyUpdated: elements,
      });

      const boundText = getBoundTextElement(element, elementsMap);
      if (boundText && !isArrowElement(element)) {
        scene.mutateElement(boundText, {
          x: boundText.x + (rotatedCX - cx),
          y: boundText.y + (rotatedCY - cy),
          angle: normalizeRadians((centerAngle + origAngle) as Radians),
        });
      }
    }
  }

  scene.triggerUpdate();
};

export const getResizeOffsetXY = (
  transformHandleType: MaybeTransformHandleType,
  selectedElements: NonDeletedExcalidrawElement[],
  elementsMap: ElementsMap,
  x: number,
  y: number,
): [number, number] => {
  const [x1, y1, x2, y2] =
    selectedElements.length === 1
      ? getElementAbsoluteCoords(selectedElements[0], elementsMap)
      : getCommonBounds(selectedElements);
  const cx = (x1 + x2) / 2;
  const cy = (y1 + y2) / 2;
  const angle = (
    selectedElements.length === 1 ? selectedElements[0].angle : 0
  ) as Radians;
  [x, y] = pointRotateRads(
    pointFrom(x, y),
    pointFrom(cx, cy),
    -angle as Radians,
  );
  switch (transformHandleType) {
    case "n":

Review comment (suggestion):
“I was wondering — could you clarify why `element` is treated as a single shape in this context, rather than a group or list? I’m also curious how that design choice affects the handling of bound text. Additionally, is there a specific reason why `ArrowElement` is excluded from this logic?”

Code after:
        originalElements.get(element.id)?.angle ?? element.angle;
      const [rotatedCX, rotatedCY] = pointRotateRads(
        pointFrom(cx, cy),
        pointFrom(centerX, centerY),
        (centerAngle + origAngle - element.angle) as Radians,
      );

      const updates = isElbowArrow(element)
        ? {
            // Needed to re-route the arrow
            points: getArrowLocalFixedPoints(element, elementsMap),
          }
        : {
            x: element.x + (rotatedCX - cx),
            y: element.y + (rotatedCY - cy),
            angle: normalizeRadians((centerAngle + origAngle) as Radians),
          };

      scene.mutateElement(element, updates);

      updateBoundElements(element, scene, {
        simultaneouslyUpdated: elements,
      });

      const boundText = getBoundTextElement(element, elementsMap);
      if (boundText && !isArrowElement(element)) {
        const { x, y } = computeBoundTextPosition(
          element,
          boundText,
          elementsMap,
        );

        scene.mutateElement(boundText, {
          x,
          y,
          angle: normalizeRadians((centerAngle + origAngle) as Radians),
        });
      }
    }
  }

  scene.triggerUpdate();
};

export const getResizeOffsetXY = (
  transformHandleType: MaybeTransformHandleType,
  selectedElements: NonDeletedExcalidrawElement[],
  elementsMap: ElementsMap,
  x: number,
  y: number,
): [number, number] => {