<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Draggable and Resizable Boxes with Grid Snapping</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f0f0f0;
            overflow: hidden;
        }

        .container {
            position: relative;
            width: 80%;
            height: 80%;
            background-color: #fff;
            border: 1px solid #ddd;
            background-image: linear-gradient(to right, #ddd 1px, transparent 1px),
                              linear-gradient(to bottom, #ddd 1px, transparent 1px);
            background-size: 30px 30px; /* Grid size 30x30 */
        }

        .draggable-box {
            position: absolute;
            background-color: #ff5722;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: move;
            box-sizing: border-box;
            height: 30px; /* Match grid cell height */
        }

        .resize-handle {
            width: 10px;
            height: 100%;
            background-color: #000;
            position: absolute;
            top: 0;
            cursor: ew-resize;
        }

        .resize-handle.right {
            right: 0;
        }

        .resize-handle.left {
            left: 0;
        }

        .vertical-guide {
            position: absolute;
            width: 1px;
            height: 100%;
            background-color: blue;
            top: 0;
            display: none; /* Hidden by default */
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="draggable-box" id="box1">
            Box 1
            <div class="resize-handle right" id="handle1-right"></div>
            <div class="resize-handle left" id="handle1-left"></div>
        </div>
        <div class="draggable-box" id="box2">
            Box 2
            <div class="resize-handle right" id="handle2-right"></div>
            <div class="resize-handle left" id="handle2-left"></div>
        </div>
        <!-- Vertical guide line -->
        <div class="vertical-guide" id="vertical-guide"></div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const gridSize = 30; // Size of the grid cells

            function snapToGrid(value, gridSize) {
                return Math.round(value / gridSize) * gridSize;
            }

            const boxes = document.querySelectorAll('.draggable-box');
            const verticalGuide = document.getElementById('vertical-guide');

            boxes.forEach(box => {
                let offsetX, offsetY, rect;
                const rightResizeHandle = box.querySelector('.resize-handle.right');
                const leftResizeHandle = box.querySelector('.resize-handle.left');

                function onMouseMove(e) {
                    const containerRect = box.parentNode.getBoundingClientRect();
                    const newLeft = snapToGrid(e.clientX - offsetX - containerRect.left, gridSize);
                    const newTop = snapToGrid(e.clientY - offsetY - containerRect.top, gridSize);

                    box.style.left = `${Math.max(0, Math.min(containerRect.width - box.offsetWidth, newLeft))}px`;
                    box.style.top = `${Math.max(0, Math.min(containerRect.height - box.offsetHeight, newTop))}px`;
                }

                function onMouseDown(e) {
                    if (e.target === rightResizeHandle || e.target === leftResizeHandle) return; // Skip dragging if resizing

                    rect = box.getBoundingClientRect();
                    offsetX = e.clientX - rect.left;
                    offsetY = e.clientY - rect.top;

                    function onMouseMoveThrottled(e) {
                        requestAnimationFrame(() => onMouseMove(e));
                    }

                    document.addEventListener('mousemove', onMouseMoveThrottled);
                    document.addEventListener('mouseup', () => {
                        document.removeEventListener('mousemove', onMouseMoveThrottled);
                    }, { once: true });
                }

                box.addEventListener('mousedown', onMouseDown);

                // Handle resizing from the right
                rightResizeHandle.addEventListener('mousedown', (e) => {
                    e.preventDefault(); // Prevent text selection

                    const startWidth = box.offsetWidth;
                    const startX = e.clientX;

                    // Show the vertical guide and position it at the start of resizing
                    verticalGuide.style.display = 'block';
                    verticalGuide.style.left = `${box.getBoundingClientRect().right}px`;

                    function onResizeMouseMove(e) {
                        const newWidth = snapToGrid(Math.max(50, startWidth + (e.clientX - startX)), gridSize);
                        box.style.width = `${newWidth}px`;

                        // Move the vertical guide to follow the resize handle on the right
                        const rightEdge = box.getBoundingClientRect().right;
                        verticalGuide.style.left = `${rightEdge}px`;
                    }

                    function onResizeMouseUp() {
                        document.removeEventListener('mousemove', onResizeMouseMove);
                        document.removeEventListener('mouseup', onResizeMouseUp);

                        // Hide the vertical guide when resizing stops
                        verticalGuide.style.display = 'none';
                    }

                    document.addEventListener('mousemove', onResizeMouseMove);
                    document.addEventListener('mouseup', onResizeMouseUp);
                });

                // Handle resizing from the left
                leftResizeHandle.addEventListener('mousedown', (e) => {
                    e.preventDefault(); // Prevent text selection

                    const startWidth = box.offsetWidth;
                    const startLeft = box.getBoundingClientRect().left;
                    const startX = e.clientX;

                    // Show the vertical guide and position it at the left handle
                    verticalGuide.style.display = 'block';
                    verticalGuide.style.left = `${startLeft}px`;

                    function onResizeMouseMove(e) {
                        const deltaX = e.clientX - startX;
                        const newWidth = snapToGrid(Math.max(50, startWidth - deltaX), gridSize);

                        // Adjust the left position based on the new width to prevent jumping
                        const newLeft = snapToGrid(startLeft + deltaX, gridSize);

                        // Update the box's width and left position
                        box.style.width = `${newWidth}px`;
                        box.style.left = `${newLeft}px`;

                        // Move the vertical guide to follow the resize handle on the left
                        verticalGuide.style.left = `${newLeft}px`;
                    }

                    function onResizeMouseUp() {
                        document.removeEventListener('mousemove', onResizeMouseMove);
                        document.removeEventListener('mouseup', onResizeMouseUp);

                        // Hide the vertical guide when resizing stops
                        verticalGuide.style.display = 'none';
                    }

                    document.addEventListener('mousemove', onResizeMouseMove);
                    document.addEventListener('mouseup', onResizeMouseUp);
                });
            });
        });
    </script>
</body>
</html>
issue is that when i left resize the box the box suddenly jumps to right then start resizing