PuruVJ / neodrag

One Draggable to rule them all 💍
https://neodrag.dev
MIT License
1.59k stars 48 forks source link

Can't drag elements inside shadow DOM #107

Closed davidkudera closed 1 year ago

davidkudera commented 1 year ago

So far, the only code I found preventing using this library in shadow DOM is this condition: https://github.com/PuruVJ/neodrag/blob/5a848a68ad886061938e4ed8ddb101f4fd89be4b/packages/core/src/index.ts#L400-L403

The problem is with e.target which has some parent custom element instead of the one I'm actually trying to drag.

I'm now testing if this simple patch is sufficient:

// use composedPath instead of e.target
const eventTarget = e.composedPath()[0];
if (dragEls.some((el) => el.contains(eventTarget)) && !cancelElementContains(cancelEls, [eventTarget])) {
  currentlyDraggedEl = dragEls.length === 1 ? node : dragEls.find((el) => el.contains(eventTarget));
  active = true;
}

I can send a PR if you want me to, but I'm unsure if using composedPath is a good solution for you or if you have maybe a better idea. Fixing this makes it possible to use this library with Lit before there is a specific Lit implementation (which is my use case).

davidkudera commented 1 year ago

@PuruVJ thanks for fixing this and sorry for bothering you with this issue again. Unfortunately, I was too slow and just now I found another limitation. My previous solution fixed dragging only for custom element roots (meaning no dragging of elements inside of shadow roots).

This is the updated patch I'm testing now:

const eventTarget = e.composedPath()[0];
    if (dragEls.some((el) => el.contains(eventTarget) || (el.shadowRoot !== null && el.shadowRoot.contains(eventTarget))) && !cancelElementContains(cancelEls, [eventTarget])) {
      currentlyDraggedEl = dragEls.length === 1 ? node : dragEls.find((el) => el.contains(eventTarget));
      active = true;
    }

The only difference is that I'm calling contains() on the shadowRoot if it exists.

PuruVJ commented 1 year ago

Released in 2.0.3