solid-dnd icon indicating copy to clipboard operation
solid-dnd copied to clipboard

`onDragEnd` doesn't give x or y coordinates

Open bluskript opened this issue 2 years ago • 7 comments

While using this library, I noticed that there doesn't seem to be any way to get the exact x and y coordinate of the dragged item onto the drop area. The onDragEnd function seems to run after transforms are cleared, which means they are 0 when I try to use them. The most comfortable usage would give me exact x and y coordinates relative to the drop area, though relative to the entire window would also be fine.

codesandbox link demonstrating the problem

bluskript avatar May 01 '22 23:05 bluskript

Yeah, technically it makes sense (the drag has ended), but there are cases where it would be useful to defer clearing the transforms until after onDragEnd. E.g. #28

There's a few different ways we could approach this - deferring clearing the transforms, making a 'previous' transform available, having a discrete onDragEnding...

What's your use case for this?

(In the meantime, you can capture the position in onDragMove I guess).

martinpengellyphillips avatar May 02 '22 08:05 martinpengellyphillips

My use-case is I am making a set of elements draggable onto a grid canvas, so in order to find where the user dragged said elements, it has to know its final x and y coordinates and snap to a gridline.

bluskript avatar May 02 '22 12:05 bluskript

oh -- that said, I just tried the onDragMove hack. Seems like... it doesn't fire when dragging overlays...

EDIT: doesn't seem like onDragMove runs at all in my case... am I missing something?

https://codesandbox.io/s/trusting-chihiro-bo1k7g?file=/src/main.tsx

bluskript avatar May 02 '22 12:05 bluskript

EDIT: doesn't seem like onDragMove runs at all in my case... am I missing something?

Hmmm. I think that is a bug in solid-dnd (likely a regression caused by other fixes). Added #33 to tackle that.

martinpengellyphillips avatar May 02 '22 14:05 martinpengellyphillips

Fixed #33 in 0.6.1 @Bluskript .

Regarding the x,y position in onDragEnd enhancement. I'll have a think about the best way to go there, but happy to hear ideas too.

martinpengellyphillips avatar May 02 '22 15:05 martinpengellyphillips

export const useDragEnd = (
  onEnd: (
    x: number,
    y: number,
    ev: {
      draggable: Draggable;
      droppable?: Droppable | null;
    }
  ) => void
) => {
  const [, { onDragEnd, onDragMove }] = useDragDropContext()!;

  let x = 0;
  let y = 0;

  onDragMove(({ draggable }) => {
    x = draggable.transform.x;
    y = draggable.transform.y;
  });

  onDragEnd((ev) => {
    // offset the x and y by the draggable's position on screen
    // because the onDragMove event just gives us the change from the
    // original position of the element.
    onEnd(x + ev.draggable.layout.x, y + ev.draggable.layout.y, ev);
  });
};

here's a silly hack i put together to deal with this issue, a few questions though...

  1. why is droppable never defined for me? if it gave me the layout of the element it was dropped on, I'd be able to calculate the offset of the dropped coordinates relative to the grid directly from this hook, which would be more useful...
  2. i think solid-dnd's DragEvent should be exported in the types, since currently i have to copypaste the type definition into this function...

bluskript avatar May 02 '22 15:05 bluskript

Nice.

  1. Not sure without seeing more of the context. Are you sure you are dropping on a droppable?

  2. Yeah, can do that. I almost included them in the 0.6 release, but I tend towards waiting until there is a clear need / ask.

By the way, I'm going to play around with deferring the clearing of the transform. It might work well for your use case and also solve #28

martinpengellyphillips avatar May 02 '22 18:05 martinpengellyphillips

After extensive investigation, I decided that altering behaviour to defer clearing of the transform made code overly complicated and expectations inconsistent. For #28 I'm going to pursue a standalone auto-animate type strategy in future instead.

However, I have added an example ("Arbitrary drag move") to https://solid-dnd.com that uses the technique of capturing last known position from onDragMove which I think works well.

And 0.7.0 is released now with the exported typings.

martinpengellyphillips avatar Sep 07 '22 21:09 martinpengellyphillips