'How do I confine a dragged cube within boundaries smoothly?

How can I confine a cube that can be dragged using the mouse within the boundaries of a plane smoothly so that if my cursor leaves the plane, the cube is still dragged but only so that it doesn't leave the plane?

First off, here is my code:

import { BoxBufferGeometry, DirectionalLight, Mesh, MeshStandardMaterial, PerspectiveCamera, PlaneBufferGeometry, Raycaster, Scene, Sprite, SpriteMaterial, Vector2, WebGLRenderer } from "three";
import { degToRad } from "three/src/math/MathUtils";

const renderer = new WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.append(renderer.domElement);

// Setup the scene

const scene = new Scene();

const ground = new Mesh(new PlaneBufferGeometry(5, 5, 5), new MeshStandardMaterial());
ground.rotateX(degToRad(-90));
scene.add(ground);

const box = new Mesh(new BoxBufferGeometry(), new MeshStandardMaterial({ color: "green" }));
scene.add(box);

const spriteMaterial = new SpriteMaterial({ color: "red" });
spriteMaterial.depthTest = false;
const pointingObj = new Sprite(spriteMaterial);
pointingObj.scale.set(0.05, 0.05, 0.05);
scene.add(pointingObj);

const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight);
camera.position.set(0, 3, 3);
camera.lookAt(ground.position);
const light = new DirectionalLight("white", 0.5);
camera.add(light);
scene.add(camera);

// Do the raycasting

const raycaster = new Raycaster();
let boxIsGrabbed = false;
document.addEventListener("mousedown", () => {
    const intersections = raycaster.intersectObject(box);
    if (intersections.length > 0)
        boxIsGrabbed = true;
});

const pointer = new Vector2();
document.addEventListener("mousemove", event => {
    // Normalize the coordinates in range -1 to +1
    pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
    pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;

    raycaster.setFromCamera(pointer, camera);

    const intersections = raycaster.intersectObject(ground);
    if (intersections.length > 0) {
        pointingObj.position.copy(intersections[0].point);
        if (boxIsGrabbed)
            box.position.copy(intersections[0].point);
    }
});

document.addEventListener("mouseup", () => {
    boxIsGrabbed = false;
});

renderer.setAnimationLoop(() => {
    renderer.render(scene, camera);
});

If you run it, it looks like this: enter image description here

It works well overall but if you drag the cube out of the plane, it abruptly stops moving the cube and it looks rather ugly.

The way I want it to look is like this:

https://i.imgur.com/6pDExEb.mp4 (this is simulated and doesn't actually work)

This is smooth and still moves the cube in some way, but not outside the boundaries. How can I do it like that? I'm honestly not sure where to start.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source