react-dnd / react-dnd-html5-backend

HTML5 backend for React DnD [Legacy Repo]
MIT License
145 stars 97 forks source link

Feature request: Support native folder drop #8

Open vgatto opened 8 years ago

vgatto commented 8 years ago

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));
koliyo commented 8 years ago

:+1: would really like this feature as well

quicksnap commented 7 years ago

@vgatto thank you for this monkey patch!

redwind commented 7 years ago

@vgatto really thank you for this path

Flex301 commented 7 years ago

Doesn't work for me :(

yoavniran commented 6 years ago

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
        };
    },
};