lukasbach / react-complex-tree

Unopinionated Accessible Tree Component with Multi-Select and Drag-And-Drop
https://rct.lukasbach.com
MIT License
944 stars 74 forks source link

Support Dragging External Items #250

Open rossmeredith opened 1 year ago

rossmeredith commented 1 year ago

I attempted dragging an external item onto a controlled tree but it does not trigger the onDrop handler. I tried an external drag item both external and internal to the controlled environment but neither worked.

Can dragging items outside the controlled environment be supported? I can't think of any reason why this would be difficult to implement but then again I know nothing about the internals of this library haha. So I would expect the first parameter, to be undefined, since I'm in control of this, and the second parameter, would be based on logic already written I'm guessing.

rossmeredith commented 1 year ago

Did I ask a dumb question? Still no response after two weeks ...

lukasbach commented 1 year ago

Hey, not at all, just didn't have the time to look into this yet.

With some workarounds, this is kinda achievable already by just adding custom drop handlers to tree items, this can be done pretty quickly with a custom interaction mode: https://codesandbox.io/s/react-complex-tree-external-dragging-fkf88e?file=/src/App.tsx

It's probably not quite everything you want, since it doesn't show any drag effects, but maybe it's a good-enough workaround for you for now.

Right now, RCT internally keeps track of the drag state (list of dragging items and drag position), so to implement this feature properly, I could imagine using an empty list for dragging items for cases where custom elements are dragged in. The drop handler provided by the consumer is called in https://github.com/lukasbach/react-complex-tree/blob/450e874de20eccdc00aa93050eaae714e273ac4b/packages/core/src/controlledEnvironment/DragAndDropProvider.tsx#L170-L179

so I suppose only the onFocusItem call would have to be adjusted to not fire. However, RCT also needs to be informed that a drag has started, so it can react to the drag event. Since this starts outside of RCT, the only good way I can think of, is doing that through an imperative ref on the environment. If there are better suggestions, I'm open. Right now, this is possible through [treeEnvRef.current.dragAndDropContext.onStartDraggingItems(items, treeId). But since this would become a consumer-oriented feature, a more convenient interface should probably be pulled up from the dragAndDropContext subprop to the environment ref, maybe something like treeEnvRef.current.startCustomDrag(treeId: string).

I haven't tested this, so not completely sure if this works how I imagine it right now. I'm open for other suggestions for how the interface could look like, and also contributions if anyone is interested.

rossmeredith commented 1 year ago

Hi. Thanks for getting back to me. I'll look into what you suggest some time this week.