neodrag icon indicating copy to clipboard operation
neodrag copied to clipboard

Add a way to trigger the drag start programatically

Open santiagopuentep opened this issue 3 years ago • 15 comments

I'm trying to create a draggable element that's dragged after a certain delay pressing into it and inside a certain distance from the pointer down event.

There currently doesn't seem to be a way to implement this: if I disable the draggable, when enabling it after the delay is done, the draggable doesn't start dragging (because the disabled property exists the onDragStart early internally and doesn't even start tracking the state).

If I try to let the draggable enabled but set the position to the initial position on the onDrag handler, the element jumps back an forth between the internal draggable's position and the initial position I want it to be.

Is this solvable in some way? Maybe calling something to imperatively start the internal state when I want?

santiagopuentep avatar Dec 07 '22 16:12 santiagopuentep

I have plans to add a delay option. That will require some amount of touching/pressing before dragging begins. Would that satisfy your needs?

PuruVJ avatar Dec 07 '22 18:12 PuruVJ

The problem with solving it with a delay prop is that other cases like starting the drag only after the pointer moved a certain amount from the position it was press in are still not possible. The best way I can think of would be to make the drag activate when the active property is set to true even if the cursor is pressed, and starting from the spot the cursor is when the active property changes. So:

  • press on the draggable when the active property is false.
  • move the pointer -> nothing happens.
  • after some time (or some distance or whatever), we set the active property to true.
  • move the pointer -> the draggable moves as if we had just pressed the pointer in the frame the active property was set to true.

Another idea would be to have an imperative call to start the drag when we want it to.

santiagopuentep avatar Dec 07 '22 19:12 santiagopuentep

Hi @santiagopuentep now that v2.0 is very close and you have requested it, I'll be straight: I don't really understand the API design you want.

Can you suggest some rough code examples of how this would be configurable?

PuruVJ avatar Dec 29 '22 09:12 PuruVJ

Hi @santiagopuentep now that v2.0 is very close and you have requested it, I'll be straight: I don't really understand the API design you want.

Can you suggest some rough code examples of how this would be configurable?

I think that adding a new property called deadzone (an object with x and y properties) (appart from the delay property) could solve the other common use case of not starting drag after the cursor moved a certain distance from the pointerdown event. Deadzone similar to the the deadzone of controller joysticks.

It wouldn't be a general solution for all cases where we want to control when the component starts the drag (maybe some other event in the app), but at least most cases would be covered.

santiagopuentep avatar Dec 30 '22 04:12 santiagopuentep

deadzone could be a nice name.

But I find your idea of a generic solution more appealing.

I am thinking it could maybe resemble this:

start: ({ shadowOffsetX, shadowOffsetY }) => boolean

It gives you offsetX and offsetY. This is how much the component would have moved, but it didn't. Then based on it you can return true at some point, and then the dragging properly begins. The shadowOffsetX and shadowOffsetY will be reset and ignored. You won't be able to control this function once it becomes true.

Would that be a better solution to your answer?

PuruVJ avatar Dec 30 '22 07:12 PuruVJ

That sounds great! Good idea, I think that might be a complete solution 👌

santiagopuentep avatar Jan 06 '23 15:01 santiagopuentep

@PuruVJ Do you have any programmed dates on when this is going to be added? We really need to transition to this library but we can't until this feature is there because of how our app works. Maybe I can help?

santiagopuentep avatar Feb 26 '23 15:02 santiagopuentep

Hi! Sorry for the delay, I kinda got busy with life and other more pressing projects for a while. I can't promise when this would be released. If you think you can make a PR, I will be happy merging it ASAP :)

PuruVJ avatar Mar 02 '23 05:03 PuruVJ

Awesome. Tomorrow I'll try to do those changes.

santiagopuentep avatar Mar 03 '23 03:03 santiagopuentep

I'm trying to run the project. I did npm install and npm run compile but it's failing with this error: NX Could not find ".modules.yaml" at .... I couldn't find anyting in Google and this is the first time I use NX. Do you mind helping me to run the project? I'm running on Windows.

santiagopuentep avatar Mar 03 '23 20:03 santiagopuentep

I use pnpm here. Try pnpm install

PuruVJ avatar Mar 03 '23 20:03 PuruVJ

I have the changes complete. I managed to do the delay feature and the deadzone by letting the user return true from the onDrag callback to block the dragging. If the user returns nothing or false the drag works as usual. This way anyone can implement the feature they want however they want.

I also did some other improvements like the pointermove and pointerup events being added only when the pointer is down, instead of being permanently added and running, which is a big performance improvement.

I want to do a PR but I don't know how to run the project. If I run the react example it only shows two sliders. If I run the docs I get this error:

Failed to load url @astrojs/markdown-remark (resolved id: @astrojs/markdown-remark) in /home/santiagopuentep/neodrag-fork/docs/astro.config.ts

Could you please help me with that?

santiagopuentep avatar Mar 06 '23 15:03 santiagopuentep

Hey man!

I test things out by going to packages/svelte/demo folder and running pnpm dev in that, while having pnpm compile:watch in packages/svelte running at all times.

If you're not familiar with svelte, you can use demo folders of other frameworks too, every single folder has a demo folder. Just remember to run pnpm compile of that framework before you run the demo server

PuruVJ avatar Mar 20 '23 10:03 PuruVJ

I ended up completely changing the library to match what we need in our project, but I have a few changes that could help. I'll create issues for them.

This problem I solved by creating an onBeforeDrag callback that's run before every onDrag and if it returns true, the drag is blocked. This way the onBeforeDrag receives all the values necessary to calculate the deadzone or the delay of the drag start.

That was the best solution I could find in case you want to implement it.

santiagopuentep avatar Mar 21 '23 19:03 santiagopuentep