Repository: excalidraw/excalidraw
File: src/components/App.tsx (TypeScript)

Code before:
          isWritableElement(target))
      ) {
        return;
      }
      const data = await parseClipboard(event);
      if (this.props.onPaste) {
        if (await this.props.onPaste(data, event)) {
          return;
        }
      }
      if (data.errorMessage) {
        this.setState({ errorMessage: data.errorMessage });
      } else if (data.spreadsheet) {
        this.setState({
          pasteDialog: {
            data: data.spreadsheet,
            shown: true,
          },
        });
      } else if (data.elements) {
        this.addElementsFromPasteOrLibrary(data.elements);
      } else if (data.text) {
        this.addTextFromPaste(data.text);
      }
      this.selectShapeTool("selection");
      event?.preventDefault();
    },
  );

  private addElementsFromPasteOrLibrary = (
    clipboardElements: readonly ExcalidrawElement[],
    clientX = cursorX,
    clientY = cursorY,
  ) => {
    const [minX, minY, maxX, maxY] = getCommonBounds(clipboardElements);

    const elementsCenterX = distance(minX, maxX) / 2;
    const elementsCenterY = distance(minY, maxY) / 2;

    const { x, y } = viewportCoordsToSceneCoords(
      { clientX, clientY },
      this.state,
    );

    const dx = x - elementsCenterX;
    const dy = y - elementsCenterY;
    const groupIdMap = new Map();

    const [gridX, gridY] = getGridPoint(dx, dy, this.state.gridSize);

    const oldIdToDuplicatedId = new Map();

Review comment (suggestion):
api change so that callers don't have to do the positioning calculation themselves (which could be error prone coz they'd not know which coordinate system to use)

Code after:
      }
      if (data.errorMessage) {
        this.setState({ errorMessage: data.errorMessage });
      } else if (data.spreadsheet) {
        this.setState({
          pasteDialog: {
            data: data.spreadsheet,
            shown: true,
          },
        });
      } else if (data.elements) {
        this.addElementsFromPasteOrLibrary({
          elements: data.elements,
          position: "cursor",
        });
      } else if (data.text) {
        this.addTextFromPaste(data.text);
      }
      this.selectShapeTool("selection");
      event?.preventDefault();
    },
  );

  private addElementsFromPasteOrLibrary = (opts: {
    elements: readonly ExcalidrawElement[];
    position: { clientX: number; clientY: number } | "cursor" | "center";
  }) => {
    const [minX, minY, maxX, maxY] = getCommonBounds(opts.elements);

    const elementsCenterX = distance(minX, maxX) / 2;
    const elementsCenterY = distance(minY, maxY) / 2;

    const clientX =
      typeof opts.position === "object"
        ? opts.position.clientX
        : opts.position === "cursor"
        ? cursorX
        : this.state.width / 2 + this.state.offsetLeft;
    const clientY =
      typeof opts.position === "object"
        ? opts.position.clientY
        : opts.position === "cursor"
        ? cursorY
        : this.state.height / 2 + this.state.offsetTop;

    const { x, y } = viewportCoordsToSceneCoords(
      { clientX, clientY },
      this.state,
    );

    const dx = x - elementsCenterX;