у меня есть вот такой код
но сецчас округление происходит только вправую сторону
и когда мой примитив прижат к правой грнице, поесле округления он смещается вправо еще больше и вылетает за границу 
что это 
ипсравь это 
import { useEffect, useRef } from 'react';
import Konva from 'konva';
import { IPoint } from '../models/infrastucture/point';
import { useGridStore } from '../store';
import { useDocumentContext } from './useDocumentContext';
import { Subject } from 'rxjs';
import { ISize } from '../models/infrastucture/size';
import { PrimitiveBase } from '../models/base/primitives.base';
import Node = Konva.Node;
import Stage = Konva.Stage;
import Line = Konva.Line;
import Group = Konva.Group;

interface ISizeWithBounds extends ISize {
  minX: number;
  minY: number;
}

const positionSource = new Subject<{ id: string | number; x: number; y: number }>(); // Exported Subject
const orderSource = new Subject<{ [key: string]: number }>();

export const position$ = positionSource.asObservable();
export const order$ = orderSource.asObservable();

interface UseSnapProps {
  id: string | number;
  primitive: PrimitiveBase;
  inGroup: boolean;
}

export const useSnap = <T extends Node>({ id, primitive, inGroup }: UseSnapProps) => {
  const gridSize = useGridStore((state) => state.gridSize);
  const document = useDocumentContext();
  const ref = useRef<T>(null);

  const calculateGroupSize = (elements: Node[]): ISizeWithBounds => {
    // Initialize bounding box coordinates
    let minX = Infinity;
    let minY = Infinity;
    let maxX = -Infinity;
    let maxY = -Infinity;

    const processElement = (element: Node | Line) => {
      if (element instanceof Group) {
        element.children.map((child) => {
          processElement(child as Node);
        });
      }

      if (element instanceof Line) {
        const points = element.points();
        for (let i = 0; i < points.length; i += 2) {
          const pointX = points[i];
          const pointY = points[i + 1];
          minX = Math.min(minX, pointX);
          minY = Math.min(minY, pointY);
          maxX = Math.max(maxX, pointX);
          maxY = Math.max(maxY, pointY);
        }
      }

      const x = element.x();
      const y = element.y();
      const width = element.width();
      const height = element.height();

      // Calculate the element's bounding box
      const elementLeft = x;
      const elementRight = x + width;
      const elementTop = y;
      const elementBottom = y + height;

      // Update the bounding box coordinates
      minX = Math.min(minX, elementLeft);
      minY = Math.min(minY, elementTop);
      maxX = Math.max(maxX, elementRight);
      maxY = Math.max(maxY, elementBottom);
    };

    // Process each element
    elements.forEach(processElement);

    // Calculate the size of the bounding box
    const boundingWidth = maxX - minX;
    const boundingHeight = maxY - minY;

    return { width: boundingWidth, height: boundingHeight, minX: minX, minY: minY };
  };

  const calculatePosition = (node: Node | Stage, newPosition: IPoint) => {
    // Get the node's bounding box dimensions
    const nodeRect: ISizeWithBounds =
      'children' in node ? calculateGroupSize(node.children) : { ...node.size(), minX: 0, minY: 0 };

    if (!document.activePage) {
      return;
    }

    // Bounding Box Constraint Logic
    if (newPosition.x < 0 || (nodeRect.minX < 0 && newPosition.x + nodeRect.minX < 0)) {
      newPosition.x = nodeRect.minX < 0 ? nodeRect.minX * -1 : 0;
    }
    if (newPosition.y < 0 || (nodeRect.minY < 0 && newPosition.y + nodeRect.minY < 0)) {
      newPosition.y = nodeRect.minY < 0 ? nodeRect.minY * -1 : 0;
    }
    if (
      newPosition.x > document.activePage.width - nodeRect.width ||
      (nodeRect.minX < 0 && newPosition.x > document.activePage.width - nodeRect.width - nodeRect.minX)
    ) {
      newPosition.x =
        nodeRect.minX < 0
          ? document.activePage.width - nodeRect.width - nodeRect.minX
          : document.activePage.width - nodeRect.width;
      // newPosition.x = Math.floor(newPosition.x / gridSize) * gridSize;
    }
    if (
      newPosition.y > document.activePage.height - nodeRect.height ||
      (nodeRect.minY < 0 && newPosition.y > document.activePage.height - nodeRect.height - nodeRect.minY)
    )
      newPosition.y =
        nodeRect.minY < 0
          ? document.activePage.height - nodeRect.height - nodeRect.minY
          : document.activePage.height - nodeRect.height;
  };

  // const roundPosition = (x: number, y: number) => {
  //   const newPosition = {
  //     x: Math.round(x / gridSize) * gridSize,
  //     y: Math.round(y / gridSize) * gridSize,
  //   };
  //   if (
  //     newPosition.y > document.activePage.height - nodeRect.height ||
  //     (nodeRect.minY < 0 && newPosition.y > document.activePage.height - nodeRect.height - nodeRect.minY)
  //   )
  //   return newPosition;
  // };

  const updatePosition = (x: number, y: number) => {
    const node = ref.current;
    if (!node) return;

    const newPosition = {
      x: Math.round(x / gridSize) * gridSize,
      y: Math.round(y / gridSize) * gridSize,
    };

    calculatePosition(node, newPosition);

    node.position(newPosition);

    positionSource.next({ id: id, x: newPosition.x, y: newPosition.y }); // Emit changes
  };

  const reorderElements = () => {
    // if (!document.activePage || document.activePage.layers.length === 0) return;
    //
    // let item: Primitives | undefined;
    // let itemLayer: Layer | undefined;
    // let layerIndex: number | undefined;
    // let primitiveIndex: number | undefined;
    // const { activePage } = document;
    //
    // // Ищем элемент по всем слоям
    // for (const layer of activePage.layers) {
    //   const index = layer.primitives.findIndex((p) => p.id === id);
    //   if (index !== -1) {
    //     item = layer.primitives[index];
    //     itemLayer = layer;
    //     layerIndex = index;
    //     primitiveIndex = index;
    //     break;
    //   }
    // }
    //
    // if (!item || !itemLayer || primitiveIndex === undefined || layerIndex === undefined) return;
    //
    // // Удаляем элемент из старой позиции
    // itemLayer.primitives.splice(primitiveIndex, 1);
    //
    // // Вставляем элемент в конец массива
    // itemLayer.primitives.push(item);
    //
    // // Собираем словарь типа id элемента - порядковый номер
    // const orders = itemLayer.primitives.reduce((acc: { [key: string]: number }, primitive, index) => {
    //   acc[primitive.id] = index;
    //   return acc;
    // }, {});
    //
    // // Обновляем порядковые номера
    // orderSource.next(orders);
  };

  const handleDragStart = (e: Konva.KonvaEventObject<DragEvent>) => {
    e.target.moveToTop();
    reorderElements();
  };

  const handleDragMove = (e: Konva.KonvaEventObject<DragEvent>) => {
    const node = e.target;
    const newPosition = {
      x: Math.round(node.x() / gridSize) * gridSize,
      y: Math.round(node.y() / gridSize) * gridSize,
    };

    calculatePosition(node, newPosition);

    node.position(newPosition);
  };

  const handleDragEnd = (e: Konva.KonvaEventObject<DragEvent>) => {
    updatePosition(e.target.x(), e.target.y());
  };

  useEffect(() => {
    !inGroup && updatePosition(primitive.x, primitive.y);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [gridSize]);

  return { ref, handleDragStart, handleDragMove, handleDragEnd };
};

export default useSnap;