solid-dnd
solid-dnd copied to clipboard
`onDragEnd` doesn't give x or y coordinates
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
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).
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.
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
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.
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.
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...
- 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...
- i think
solid-dnd
'sDragEvent
should be exported in the types, since currently i have to copypaste the type definition into this function...
Nice.
-
Not sure without seeing more of the context. Are you sure you are dropping on a droppable?
-
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
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.