npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

itsa-react-dd

v16.0.10

Published

Drag and Drop for React without a wrapper

Downloads

23

Readme

Build Status

Drag and Drop for React.js without a wrapper Component. Note: can also be used in projects without React.

Easy to use, just add a data-attribute.

How to use

Just set the attribute data-draggable to an arbitrary String and the Component becomes draggable. You need to use unique data-draggablevalues for each draggable item. This is where dd.generateId() becomes handy: it generates unique Id's. (note: generate those ids during initialization of the component, NOT inside render as you don't want new Id on every update).

View live example

Making draggable: data-draggable

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} />,
    document.getElementById("container")
);

Constrain: data-draggable-constrain

data-draggable-constrain can be a css-selector or "window".

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} data-draggable-constrain="window" />,
    document.getElementById("container")
);

Restriction directions: data-draggable-x or data-draggable-y

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} data-draggable-y={true} />,
    document.getElementById("container")
);

Drag by handle: data-draggable-handle

data-draggable-handle is a css-selector.

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} data-draggable-handle="h1" />,
    document.getElementById("container")
);

Proxy dragging: data-draggable-proxy

data-draggable-proxy is either "true", "outline", "blur" or "reverse-blur"

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} data-draggable-proxy="outline" />,
    document.getElementById("container")
);

Dragging related at the same time: data-draggable-group

All other Elements with the same data-draggable-group will be dragged whenever one item of the group is dragged.

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId1 = dd.generateId(),
    dragId2 = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId1} data-draggable-group="mygroup" />,
    document.getElementById("container1")
);

ReactDOM.render(
    <div data-draggable={dragId2} data-draggable-group="mygroup" />,
    document.getElementById("container2")
);

Drop Targets: data-draggable-droptarget

data-draggable-droptarget makes releasing (dropping) only available on Elements with a matching data-dropzone attribute.

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

// defining the draggable:
ReactDOM.render(
    <div data-draggable={dragId} data-draggable-droptarget="myDropzone" />,
    document.getElementById("container1")
);

// defining the dropzone:
ReactDOM.render(
    <div data-dropzone="myDropzone" />,
    document.getElementById("container2")
);

Event driven

itsa-react-dd is event driven. It just works out of the box, but you can use the event system to interact or listen to events. The Event system that is used is itsa-event, which has before and after listeners.

Available events:

*:dd --> dragging starts *:drag --> movement *.drop --> pointer is released

You can listen by wildcard, for example "*:dd", or by emitter name: "UI:dd" or "myEmitter:dd"

Example preventing drop

This example will prevent your drag to drop, leading into moving the Element into its original position:

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} />,
    document.getElementById("container")
);

Event.before("*:drop", function(e) {
    e.preventDefault();
});

Example get informed when dragging is started and ends

This example will inform you when dragging starts and ends, with the same subscriber. Because the default function returns e.returnValue as a Promise, we can use this as a handler to get informed when dd is ready.

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} />,
    document.getElementById("container")
);

Event.after("*:dd", function(e) {
    console.warn("Dragging is started");
    e.returnValue.then(function() {
        console.warn("Ready dragging");
    });
});

Example get informed on dropped inside a dropzone

This example will inform you whenever a drop inside a dropzone has taken place. The after-subscriber only gets invoked upon a successful drop: if dropped outside the dropzone, there won't be an after event.

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

// defining the draggable:
ReactDOM.render(
    <div data-draggable={dragId} data-draggable-droptarget="myDropzone" />,
    document.getElementById("container1")
);

// defining the dropzone:
ReactDOM.render(
    <div data-dropzone="myDropzone" />,
    document.getElementById("container2")
);

Event.after("*:drop", function(e) {
    console.warn(e.target, "got dropped inside", e.dropTarget);
});

Example disable dragging

This example will disable dragging as a whole.

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} />,
    document.getElementById("container")
);

Event.before("*:dd", function(e) {
    e.preventDefault();
});

Using a different emitter-name: data-draggable-emitter

By specifying data-draggable-emitter, the underlying event-system fires events on behalf of this emitter. Without an emitter, the events "UI:dd", "UI:drag" and "UI:drop" will be used, with emitter (say "myEmitter"), it becomes: "myEmitter:dd", "myEmitter:drag" and "myEmitter:drop".

const ReactDOM = require("react-dom"),
    dd = require("itsa-react-dd"),
    dragId = dd.generateId();

ReactDOM.render(
    <div data-draggable={dragId} data-draggable-emitter="myEmitter" />,
    document.getElementById("container")
);

Browser support

IE8+ and all modern browsers

If you want to express your appreciation

Feel free to donate to one of these addresses; my thanks will be great :)

  • Ether: 0xE096EBC2D19eaE7dA8745AA5D71d4830Ef3DF963
  • Bitcoin: 37GgB6MrvuxyqkQnGjwxcn7vkcdont1Vmg