react-dnd-html5-backend icon indicating copy to clipboard operation
react-dnd-html5-backend copied to clipboard

Feature request: Support native folder drop

Open vgatto opened this issue 9 years ago • 5 comments

Currently, the native drag source for Files only extracts "files" from the data transfer object. In order to use Chrome's support for folders and folder traversal, it would be nice to have the "items" as well.

I've been able to monkey patch the HTML5Backend to pass along what I need.

function makeFolderAwareHTML5Backend(manager) {
  const backend = HTML5Backend(manager);
  const orig = backend.handleTopDropCapture;
  backend.handleTopDropCapture = function(event) {
    backend.currentNativeSource.item.items = event.dataTransfer.items;
    return orig(event);
  }
  return backend;
}

export default DragDropContext(makeFolderAwareHTML5Backend)(DropTarget(types, fileTarget, collect)(App));

vgatto avatar Dec 04 '15 00:12 vgatto

:+1: would really like this feature as well

koliyo avatar Mar 10 '16 14:03 koliyo

@vgatto thank you for this monkey patch!

quicksnap avatar Oct 22 '16 00:10 quicksnap

@vgatto really thank you for this path

redwind avatar Mar 13 '17 00:03 redwind

Doesn't work for me :(

Flex301 avatar Mar 29 '17 15:03 Flex301

thanks @vgatto your sample was a great help. I created html-dir-content to help with the traversing of folder structure and your code helped me tie them together.

In case someone ends up with a use case such as mine, here's what i ended up with:


//dndBackendWithFolderSupport.js

import HTML5Backend from "react-dnd-html5-backend";
import {getFilesFromDragEvent} from "html-dir-content";

export default (manager: Object) => {
    const backend = HTML5Backend(manager),
        orgTopDropCapture = backend.handleTopDropCapture;

    backend.handleTopDropCapture = (e) => {
        orgTopDropCapture.call(backend, e);
        backend.currentNativeSource.item.dirContent = getFilesFromDragEvent(e); //returns a promise
    };

    return backend;
}

//my component

const dndSpec = {
    drop(props: Props, monitor: { getItem: () => any }) {
        const dndItem = monitor.getItem();

        if (dndItem) {
            if (dndItem.urls && dndItem.urls.length) {
                //handle urls
            }
            else {
                dndItem.dirContent.then((files: Object[]) => {
                    if (files.length){
                       // handle dragged folder(s)
                    }
                    else if (dndItem.files && dndItem.files.length){
                         //handle dragged files
                    }               
                });
            }
        }

        return {
            dndFinished: true
        };
    },
};


yoavniran avatar Oct 29 '17 11:10 yoavniran