kutlugsahin / vue-smooth-dnd

Vue wrapper components for smooth-dnd
MIT License
1.73k stars 249 forks source link

Feature: add support for dragover/mouseover events, doing something with mouseposition #201

Open Evertvdw opened 2 years ago

Evertvdw commented 2 years ago

Hello! I've been struggling for quite some hours to get something done with this library which should in my opinion be easier. I eventually found a workaround, so this issue is also for those with similar use cases.

The use case

I have a tree with rows which can be collapsed/expanded and I wanted to be able to reorder that tree, move children around etc. This means that at a give position in the list there are multiple options for the item to go. For example take this tree:

a
    b
    c
        d
e

When I drag b between d and e I have multiple options:

What I wanted to do to solve this is:

  1. At the start of dragging take the clientX position of the mouse and save it
  2. While dragging compare the current clientX position of the mouse and when take the offset of this do determine what option to select.

Current solution

For the 1st step I added a @mousedown handler to the drag-handle of the draggable items. In this handler I extract the mouse clientX and save it. For the 2nd step I had to do this in the @drop-ready handler of the container:

const element = document.querySelector(".smooth-dnd-drop-preview-constant-class");
if (element && !this.dragListener) {
    element.addEventListener("mousemove", (e) => {
        this.dragOver(e as MouseEvent);
    });
    element.addEventListener("touchmove", (e) => {
        this.dragOver(e as TouchEvent);
    });
    this.dragListener = true;
}

In addition to this I had to add custom css:

.smooth-dnd-drop-preview-constant-class {
    pointer-events: all !important;
}

Preferred solution

It would be nice if there would be a better way to get the current mouse position while dragging. With HTML dnd you can set dragover listeners to elements that fire when moving the mouse. I tried to add those everywhere but I could not get that to work. Like to hear your thoughts on this, is this workaround acceptable?