How to select only the GridHelper for DragControls dragging, not one of its child objects

I am new to this forum, not sure if this is how to post a question with some code, but I need some help please.

I have scene with some GridHelper objects to represent ‘pulleys’ which I need to drag but if I click on a child object of the GridHelper only the child is dragged, not the complete GridHelper.

// each pulley is a GridHelper with some child objects such as circle and ‘rim’ added for presentation
// I need to drag the GridHelper with its children in the dragcontrols
// but if the child object is clicked in the dragcontrols only the child is dragged
// if the GridHelper is clicked it move with the child objects - this is the required behavior

Sample project code based on Sean Bradley code follows

<!DOCTYPE html>

<html lang="en">

    <head>

        <meta charset="utf-8" />

        <meta name="viewport" content="width=device-width, initial-scale=1" />

        <title>Three.js TypeScript Tutorials by Sean Bradley : https://sbcode.net/threejs</title>

        <style>

            body {

                overflow: hidden;

                margin: 0px;

            }

        </style>

    </head>

    <body>

        <script type="module" src="bundle.js"></script>

    </body>

</html>

client.ts script

import * as THREE from 'three'

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

//import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'

import { DragControls } from 'three/examples/jsm/controls/DragControls'

import Stats from 'three/examples/jsm/libs/stats.module'

const scene = new THREE.Scene()

scene.add(new THREE.AxesHelper(5))

const light = new THREE.SpotLight()

light.position.set(12.5, 12.5, 12.5)

light.castShadow = true

light.shadow.mapSize.width = 1024

light.shadow.mapSize.height = 1024

scene.add(light)

const camera = new THREE.PerspectiveCamera(

    75,

    window.innerWidth / window.innerHeight,

    0.1,

    1000

)

camera.position.set(0, 0, 200)

const renderer = new THREE.WebGLRenderer()

//renderer.shadowMap.enabled = true

//renderer.outputEncoding = THREE.sRGBEncoding

renderer.setSize(window.innerWidth, window.innerHeight)

document.body.appendChild(renderer.domElement)

scene.background = new THREE.Color(0xffffff);

const controls = new OrbitControls(camera, renderer.domElement)

controls.enableDamping = true

controls.enableRotate = false

let cvDragObjects:  THREE.Object3D[] = [];

const dragcontrols = new DragControls(cvDragObjects, camera, renderer.domElement)

const pickableObjects: THREE.Mesh[] = []

let intersectedObject: THREE.Object3D | null

const originalMaterials: { [id: string]: THREE.Material | THREE.Material[] } =

    {}

const highlightedMaterial = new THREE.MeshBasicMaterial({

    wireframe: true,

    color: 0x00ff00

})

// create some data to draw

// each pulley is a GridHelper with some child objects such as circle and 'rim' added for presentation

// I need to drag the GridHelper with its children in the dragcontrols

// but if the child object is clicked in the dragcontrols only the child is dragged

// if the GridHelper is clicked it move with the child objects - this is the required behavior

let data = []

const datarow1 = { pType: "Bend", screenSize: 16, screenX: -50, screenZ: 50 }

data.push(datarow1)

const datarow2 = { pType: "Bend", screenSize: 12, screenX: 100, screenZ: 100 }

data.push(datarow2)

const datarow3 = { pType: "Bend", screenSize: 20, screenX: 50, screenZ: 100 }

data.push(datarow3)

const drive = { pType: "Drive", screenSize: 18, screenX: 150, screenZ: 70 }

data.push(drive)

const cv = new THREE.Object3D(); // main object in scene

// add the pulleys to the cv object

data.forEach(element => {

    const pull = drawPulley(element)

    cvDragObjects.push(pull)

    cv.add(pull)

});

scene.add(cv);

function drawPulley(dr1: any) {

    //var combinedgeometry = new THREE.Geometry();

    var rimmaterial = new THREE.LineBasicMaterial({ color: 0x000000 });

    var cenmaterial = new THREE.MeshBasicMaterial({ color: 0xa7a2a2 });

    var whitematerial = new THREE.MeshBasicMaterial({ color: 0xf7f7f7 });

    var redmaterial = new THREE.MeshBasicMaterial({ color: 0xf81010 });

    var blackmaterial = new THREE.MeshBasicMaterial({ color: 0x171616 });

    var bluematerial = new THREE.MeshBasicMaterial({ color: 0x1212fa });

    var gridhelpermaterial = new THREE.MeshBasicMaterial({ color: 0xa7a2a2, transparent: true, opacity: 0.01, visible: false });

    //var pulleyGrid = new THREE.PolarGridHelper(dr1.r, 16, 8, 4, cenmaterial.color, cenmaterial.color);

    var pulleyGrid = new THREE.GridHelper(dr1.screenSize * 0.5, 2, gridhelpermaterial.color, gridhelpermaterial.color);

    //pulleyGrid.rotateX(Math.PI / 2);

    if (dr1.pType === 'Drive') {

        //var r = dr1.r * .98;

        var r = dr1.screenSize * 0.5 * .98;

        var startAngle = 0;

        var angleIncr = Math.PI * 0.5;

        var geometry1 = new THREE.CircleGeometry(r, 32, startAngle, angleIncr);

        var circle1 = new THREE.Mesh(geometry1, redmaterial);

        circle1.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'driveface',

            isDragable: false

        };

        pulleyGrid.add(circle1);

        //pulleyGrid.attach(circle1);

        startAngle = startAngle + angleIncr;

        var geometry2 = new THREE.CircleGeometry(r, 32, startAngle, angleIncr);

        var circle2 = new THREE.Mesh(geometry2, whitematerial);

        circle2.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'driveface',

            isDragable: false

        };

        pulleyGrid.add(circle2);

        //pulleyGrid.attach(circle2);

        startAngle = startAngle + angleIncr;

        var geometry3 = new THREE.CircleGeometry(r, 32, startAngle, angleIncr);

        var circle3 = new THREE.Mesh(geometry3, redmaterial);

        circle3.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'driveface',

            isDragable: false

        };

        pulleyGrid.add(circle3);

        //pulleyGrid.attach(circle3);

        startAngle = startAngle + angleIncr;

        var geometry4 = new THREE.CircleGeometry(r, 32, startAngle, angleIncr);

        var circle4 = new THREE.Mesh(geometry4, whitematerial);

        circle4.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'driveface',

            isDragable: false

        };

        pulleyGrid.add(circle4);

        //pulleyGrid.attach(circle4);

    }

    else if (dr1.pType === 'Brake') {

        //var r = dr1.r * .98;

        var r = dr1.screenSize * 0.5 * .98;

        var startAngle = 0;

        var angleIncr = Math.PI * 0.5;

        var geometry1 = new THREE.CircleGeometry(r, 32, startAngle, angleIncr);

        var circle1 = new THREE.Mesh(geometry1, bluematerial);

        circle1.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'brakeface',

            isDragable: false

        };

        pulleyGrid.add(circle1);

        startAngle = startAngle + angleIncr;

        var geometry2 = new THREE.CircleGeometry(r, 32, startAngle, angleIncr);

        var circle2 = new THREE.Mesh(geometry2, whitematerial);

        circle2.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'brakeface',

            isDragable: false

        };

        pulleyGrid.add(circle2);

        startAngle = startAngle + angleIncr;

        var geometry3 = new THREE.CircleGeometry(r, 32, startAngle, angleIncr);

        var circle3 = new THREE.Mesh(geometry3, bluematerial);

        circle3.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'brakeface',

            isDragable: false

        };

        pulleyGrid.add(circle3);

        startAngle = startAngle + angleIncr;

        var geometry4 = new THREE.CircleGeometry(r, 32, startAngle, angleIncr);

        var circle4 = new THREE.Mesh(geometry4, whitematerial);

        circle4.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'brakeface',

            isDragable: false

        };

        pulleyGrid.add(circle4);

    }

    else if (dr1.pType === 'Takeup') {

        var r = dr1.screenSize * 0.5 * .98;

        var x = Math.cos(30 * Math.PI / 180) * r;

        var y = Math.sin(30 * Math.PI / 180) * r;

        var z = 0;

        //var material = new THREE.MeshStandardMaterial({ color: 0x000000 });

        var material = new THREE.MeshBasicMaterial({ color: 0x000000 });

        //create a triangular geometry

        //var geometry = new THREE.Geometry();

        const points = [];

        points.push(new THREE.Vector3(-x, -y, 0)); // use anticlockwise winding otherwise not shown

        points.push(new THREE.Vector3(x, -y, 0));

        points.push(new THREE.Vector3(0, r, 0));

        var geometry = new THREE.BufferGeometry().setFromPoints(points);

        //create a new face using vertices 0, 1, 2

        var normal = new THREE.Vector3(0, 0, 0); //optional

        var color = new THREE.Color(0x171616); //optional

        var materialIndex = 0; //optional

        //var vertexColors = [new THREE.Color(0x000000),

        //    new THREE.Color(0x000000),

        //    new THREE.Color(0x000000)];

        //var face = new THREE.Face3(0, 1, 2, normal, color, materialIndex);

        // code below not working Face3 removed

        // var face = new THREE.Face3(0, 1, 2);

        // //add the face to the geometry's faces array

        // geometry.faces.push(face);

        // //geometry.faces[0].vertexColors = vertexColors;

        // geometry.computeFaceNormals();

        geometry.computeVertexNormals();

        var facemesh = new THREE.Mesh(geometry, material);

        facemesh.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'takeupface',

            isDragable: false

        };

        pulleyGrid.add(facemesh);

    }

    else { // normal pulley

        var geometry1 = new THREE.CircleGeometry(dr1.screenSize * 0.5 - 1, 32);

        var circle1 = new THREE.Mesh(geometry1, cenmaterial);

        circle1.userData = {

            isLineItem: false,

            isPullItem: true,

            no: -1,

            pType: 'takeupface',

            isDragable: false

        };

        pulleyGrid.add(circle1);

        // var pullFace = this.drawPulleyFace(dr1.screenSize * 0.5, cenmaterial);

        // pulleyGrid.add(pullFace);

    }

    var rim = drawPulleyRim(dr1.screenSize * 0.5, rimmaterial);

    pulleyGrid.add(rim);

    //pulleyGrid.rotation.x = Math.PI / 2;

    pulleyGrid.userData = {

        isLineItem: false,

        isPullItem: true,

        no: dr1.no,

        pType: dr1.pType,

        isDragable: true

    };

    pulleyGrid.position.set(dr1.screenX, dr1.screenZ, 0/*dr1.y*/);

    pulleyGrid.name = dr1.pType + '-' + dr1.no;

    //console.log('pulleyGrid', pulleyGrid);

    return pulleyGrid;

};

function drawPulleyFace(radius: number, material: THREE.MeshBasicMaterial) {

    //var geometry1 = new THREE.CircleGeometry(dr1.r, 32);

    var geometry1 = new THREE.CircleGeometry(radius - 1, 32);

    //var circle1 = new THREE.Mesh(geometry1, cenmaterial, 0, Math.PI * 2);

    var circle1 = new THREE.Mesh(geometry1, material);

    //circle1.name('pulleyFill') // no name property

    //pulleyGrid.add(circle1);

    //circle1.removeEventListener;

    circle1.userData = {

        isLineItem: false,

        isPullItem: true,

        no: -1,

        pType: 'pulleyface',

        isDragable: false

    };

    return circle1;

}

function drawPulleyRim(radius: number, material: THREE.LineBasicMaterial) {

    var segmentCount = 32;

    //geometry = new THREE.Geometry();

    //geometry = new THREE.BufferGeometry();

    //material = new THREE.LineBasicMaterial({ color: 0x555 });

    const vertices = [];

    for (var i = 0; i <= segmentCount; i++) {

        var theta = (i / segmentCount) * Math.PI * 2;

        // geometry.vertices.push(

        //   new THREE.Vector3(

        //     Math.cos(theta) * radius,

        //     Math.sin(theta) * radius,

        //     0));

        // see https://sbcode.net/threejs/geometry-to-buffergeometry/ on jow to use the new BufferGeometry

        vertices.push(

            new THREE.Vector3(

                Math.cos(theta) * radius,

                Math.sin(theta) * radius,

                0));

    }

    // draw a second rim for extra thickness

    for (var i = 0; i <= segmentCount; i++) {

        var theta = (i / segmentCount) * Math.PI * 2;

        vertices.push(

            new THREE.Vector3(

                Math.cos(theta) * (radius - 0.5),

                Math.sin(theta) * (radius - 0.5),

                0));

    }

    //geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );

    let geometry = new THREE.BufferGeometry().setFromPoints(vertices);

    let rim = new THREE.Line(geometry, material);

    rim.userData = {

        isLineItem: false,

        isPullItem: true,

        no: -1,

        pType: 'pulleyrim',

        isDragable: false

    };

    return rim;

};

window.addEventListener('resize', onWindowResize, false)

function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight

    camera.updateProjectionMatrix()

    renderer.setSize(window.innerWidth, window.innerHeight)

    render()

}

const raycaster = new THREE.Raycaster()

let intersects: THREE.Intersection[]

// document.addEventListener('mousemove', onDocumentMouseMove, false)

// function onDocumentMouseMove(event: MouseEvent) {

//     raycaster.setFromCamera(

//         {

//             x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,

//             y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1

//         },

//         camera

//     )

//     intersects = raycaster.intersectObjects(pickableObjects, false)

//     if (intersects.length > 0) {

//         intersectedObject = intersects[0].object

//     } else {

//         intersectedObject = null

//     }

//     pickableObjects.forEach((o: THREE.Mesh, i) => {

//         if (intersectedObject && intersectedObject.name === o.name) {

//             pickableObjects[i].material = highlightedMaterial

//         } else {

//             pickableObjects[i].material = originalMaterials[o.name]

//         }

//     })

// }

const stats = Stats()

document.body.appendChild(stats.dom)

function animate() {

    requestAnimationFrame(animate)

    controls.update()

    render()

    stats.update()

}

function render() {

    renderer.render(scene, camera)

}

animate()