react-dnd
Advanced tools
Comparing version 0.7.0 to 0.8.0
{ | ||
"name": "react-dnd", | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"homepage": "https://github.com/gaearon/react-dnd", | ||
@@ -8,3 +8,3 @@ "authors": [ | ||
], | ||
"description": "HTML5 drag-and-drop mixin for React with full DOM control.", | ||
"description": "Drag and drop for React with full DOM control.", | ||
"main": "dist/ReactDND.min.js", | ||
@@ -11,0 +11,0 @@ "dependencies": { |
@@ -7,3 +7,3 @@ "use strict"; | ||
var DragDropActionCreators = { | ||
startDragging: function startDragging(itemType, item, effectsAllowed) { | ||
startDragging: function startDragging(itemType, item, effectsAllowed, offsetFromClient, offsetFromContainer) { | ||
DragDropDispatcher.handleAction({ | ||
@@ -13,6 +13,15 @@ type: DragDropActionTypes.DRAG_START, | ||
item: item, | ||
effectsAllowed: effectsAllowed | ||
effectsAllowed: effectsAllowed, | ||
offsetFromClient: offsetFromClient, | ||
offsetFromContainer: offsetFromContainer | ||
}); | ||
}, | ||
drag: function drag(offsetFromClient) { | ||
DragDropDispatcher.handleAction({ | ||
type: DragDropActionTypes.DRAG, | ||
offsetFromClient: offsetFromClient | ||
}); | ||
}, | ||
recordDrop: function recordDrop(dropEffect) { | ||
@@ -19,0 +28,0 @@ DragDropDispatcher.handleAction({ |
"use strict"; | ||
var DragDropActionCreators = require("../actions/DragDropActionCreators"), | ||
DragOperationStore = require("../stores/DragOperationStore"), | ||
NativeDragItemTypes = require("../constants/NativeDragItemTypes"), | ||
DropEffects = require("../constants/DropEffects"), | ||
EnterLeaveMonitor = require("../utils/EnterLeaveMonitor"), | ||
isFileDragDropEvent = require("../utils/isFileDragDropEvent"), | ||
configureDataTransfer = require("../utils/configureDataTransfer"), | ||
shallowEqual = require("react/lib/shallowEqual"), | ||
union = require("lodash/array/union"), | ||
without = require("lodash/array/without"), | ||
isWebkit = require("../utils/isWebkit"), | ||
isFirefox = require("../utils/isFirefox"); | ||
isWebkit = require("../utils/isWebkit"); | ||
@@ -17,4 +15,4 @@ // Store global state for browser-specific fixes and workarounds | ||
_currentDragTarget, | ||
_currentComponent, | ||
_initialDragTargetRect, | ||
_imitateCurrentDragEnd, | ||
_dragTargetRectDidChange, | ||
@@ -39,5 +37,8 @@ _currentDropEffect; | ||
function triggerDragEndIfDragSourceWasRemovedFromDOM() { | ||
if (_currentDragTarget && _imitateCurrentDragEnd && !document.body.contains(_currentDragTarget)) { | ||
_imitateCurrentDragEnd(); | ||
if (!_currentComponent || document.body.contains(_currentDragTarget)) { | ||
return; | ||
} | ||
var type = DragOperationStore.getDraggedItemType(); | ||
_currentComponent.handleDragEnd(type, null); | ||
} | ||
@@ -51,3 +52,3 @@ | ||
function handleDragEnter(e) { | ||
function handleTopDragEnter(e) { | ||
preventDefaultFileDropAction(e); | ||
@@ -61,5 +62,8 @@ | ||
function handleDragOver(e) { | ||
function handleTopDragOver(e) { | ||
preventDefaultFileDropAction(e); | ||
var offsetFromClient = HTML5.getOffsetFromClient(_currentComponent, e); | ||
DragDropActionCreators.drag(offsetFromClient); | ||
// At the top level of event bubbling, use previously set drop effect and reset it. | ||
@@ -71,7 +75,3 @@ if (_currentDropEffect) { | ||
if (!_currentDragTarget) { | ||
return; | ||
} | ||
if (isWebkit() && checkIfCurrentDragTargetRectChanged()) { | ||
if (_currentDragTarget && isWebkit() && checkIfCurrentDragTargetRectChanged()) { | ||
// Prevent animating to incorrect position | ||
@@ -82,3 +82,3 @@ e.preventDefault(); | ||
function handleDragLeave(e) { | ||
function handleTopDragLeave(e) { | ||
preventDefaultFileDropAction(e); | ||
@@ -92,3 +92,3 @@ | ||
function handleDrop(e) { | ||
function handleTopDrop(e) { | ||
preventDefaultFileDropAction(e); | ||
@@ -106,25 +106,34 @@ | ||
var HTML5 = { | ||
setup: function setup() { | ||
if (typeof window !== "undefined") { | ||
window.addEventListener("dragenter", handleDragEnter); | ||
window.addEventListener("dragover", handleDragOver); | ||
window.addEventListener("dragleave", handleDragLeave); | ||
window.addEventListener("drop", handleDrop); | ||
setup: function setup(component) { | ||
if (typeof window === "undefined") { | ||
return; | ||
} | ||
window.addEventListener("dragenter", handleTopDragEnter); | ||
window.addEventListener("dragover", handleTopDragOver); | ||
window.addEventListener("dragleave", handleTopDragLeave); | ||
window.addEventListener("drop", handleTopDrop); | ||
}, | ||
teardown: function teardown() { | ||
if (typeof window !== "undefined") { | ||
window.removeEventListener("dragenter", handleDragEnter); | ||
window.removeEventListener("dragover", handleDragOver); | ||
window.removeEventListener("dragleave", handleDragLeave); | ||
window.removeEventListener("drop", handleDrop); | ||
teardown: function teardown(component) { | ||
if (typeof window === "undefined") { | ||
return; | ||
} | ||
window.removeEventListener("dragenter", handleTopDragEnter); | ||
window.removeEventListener("dragover", handleTopDragOver); | ||
window.removeEventListener("dragleave", handleTopDragLeave); | ||
window.removeEventListener("drop", handleTopDrop); | ||
}, | ||
beginDrag: function beginDrag(dragTarget, imitateDragEnd) { | ||
_currentDragTarget = dragTarget; | ||
_initialDragTargetRect = getElementRect(dragTarget); | ||
beginDrag: function beginDrag(component, e, containerNode, dragPreview, dragAnchors, offsetFromContainer, effectsAllowed) { | ||
var _e$nativeEvent = e.nativeEvent; | ||
var dataTransfer = _e$nativeEvent.dataTransfer; | ||
var target = _e$nativeEvent.target; | ||
configureDataTransfer(dataTransfer, containerNode, dragPreview, dragAnchors, offsetFromContainer, effectsAllowed); | ||
_currentComponent = component; | ||
_currentDragTarget = target; | ||
_initialDragTargetRect = getElementRect(target); | ||
_dragTargetRectDidChange = false; | ||
_imitateCurrentDragEnd = imitateDragEnd; | ||
@@ -138,7 +147,7 @@ // Mouse event tell us that dragging has ended but `dragend` didn't fire. | ||
endDrag: function endDrag() { | ||
endDrag: function endDrag(component) { | ||
_currentDragTarget = null; | ||
_currentComponent = null; | ||
_initialDragTargetRect = null; | ||
_dragTargetRectDidChange = false; | ||
_imitateCurrentDragEnd = null; | ||
@@ -149,3 +158,3 @@ window.removeEventListener("mousemove", triggerDragEndIfDragSourceWasRemovedFromDOM); | ||
dragOver: function dragOver(e, dropEffect) { | ||
dragOver: function dragOver(component, e, dropEffect) { | ||
// As event bubbles top-down, first specified effect will be used | ||
@@ -155,2 +164,26 @@ if (!_currentDropEffect) { | ||
} | ||
}, | ||
getDragSourceProps: function getDragSourceProps(component, type) { | ||
return { | ||
draggable: true, | ||
onDragStart: component.handleDragStart.bind(component, type), | ||
onDragEnd: component.handleDragEnd.bind(component, type) | ||
}; | ||
}, | ||
getDropTargetProps: function getDropTargetProps(component, types) { | ||
return { | ||
onDragEnter: component.handleDragEnter.bind(component, types), | ||
onDragOver: component.handleDragOver.bind(component, types), | ||
onDragLeave: component.handleDragLeave.bind(component, types), | ||
onDrop: component.handleDrop.bind(component, types) | ||
}; | ||
}, | ||
getOffsetFromClient: function getOffsetFromClient(component, e) { | ||
return { | ||
x: e.clientX, | ||
y: e.clientY | ||
}; | ||
} | ||
@@ -157,0 +190,0 @@ }; |
@@ -8,2 +8,3 @@ "use strict"; | ||
DRAG_END: null, | ||
DRAG: null, | ||
DROP: null | ||
@@ -10,0 +11,0 @@ }); |
"use strict"; | ||
var _require = require("./backends"); | ||
var HTML5 = _require.HTML5; | ||
var createDragDropMixin = require("./utils/createDragDropMixin"); | ||
module.exports = { | ||
DragDropMixin: require("./mixins/DragDropMixin"), | ||
DragDropMixin: createDragDropMixin(HTML5), | ||
ImagePreloaderMixin: require("./mixins/ImagePreloaderMixin"), | ||
DragLayerMixin: require("./mixins/DragLayerMixin"), | ||
HorizontalDragAnchors: require("./constants/HorizontalDragAnchors"), | ||
@@ -7,0 +13,0 @@ VerticalDragAnchors: require("./constants/VerticalDragAnchors"), |
@@ -7,6 +7,3 @@ "use strict"; | ||
function configureDataTransfer(containerNode, nativeEvent, dragPreview, dragAnchors, effectsAllowed) { | ||
var dataTransfer = nativeEvent.dataTransfer; | ||
function configureDataTransfer(dataTransfer, containerNode, dragPreview, dragAnchors, offsetFromContainer, effectsAllowed) { | ||
try { | ||
@@ -18,3 +15,3 @@ // Firefox won't drag without setting data | ||
if (shouldUseDragPreview(dragPreview) && dataTransfer.setDragImage) { | ||
var dragOffset = getDragImageOffset(containerNode, dragPreview, dragAnchors, nativeEvent); | ||
var dragOffset = getDragImageOffset(containerNode, dragPreview, dragAnchors, offsetFromContainer); | ||
dataTransfer.setDragImage(dragPreview, dragOffset.x, dragOffset.y); | ||
@@ -21,0 +18,0 @@ } |
@@ -5,4 +5,2 @@ "use strict"; | ||
assign = require("react/lib/Object.assign"), | ||
shallowEqual = require("react/lib/shallowEqual"), | ||
bindAll = require("./bindAll"), | ||
CHANGE_EVENT = "change"; | ||
@@ -26,3 +24,2 @@ | ||
store.setMaxListeners(0); | ||
bindAll(store); | ||
@@ -29,0 +26,0 @@ return store; |
@@ -5,3 +5,2 @@ "use strict"; | ||
VerticalDragAnchors = require("../constants/VerticalDragAnchors"), | ||
isFirefox = require("./isFirefox"), | ||
isSafari = require("./isSafari"); | ||
@@ -13,3 +12,3 @@ | ||
*/ | ||
function getDragImageOffset(containerNode, dragPreview, dragAnchors, e) { | ||
function getDragImageOffset(containerNode, dragPreview, dragAnchors, offsetFromContainer) { | ||
dragAnchors = dragAnchors || {}; | ||
@@ -23,12 +22,8 @@ | ||
var horizontalAnchor = dragAnchors.horizontal || HorizontalDragAnchors.CENTER; | ||
var verticalAnchor = dragAnchors.vertical || VerticalDragAnchors.CENTER;var offsetX = e.offsetX; | ||
var offsetY = e.offsetY; | ||
var node = e.target; | ||
var verticalAnchor = dragAnchors.vertical || VerticalDragAnchors.CENTER;var x = offsetFromContainer.x; | ||
var y = offsetFromContainer.y; | ||
// Work around @2x coordinate discrepancies in browsers | ||
if (isFirefox()) { | ||
offsetX = e.layerX; | ||
offsetY = e.layerY; | ||
} else if (isSafari()) { | ||
if (isSafari()) { | ||
previewHeight /= window.devicePixelRatio; | ||
@@ -38,8 +33,2 @@ previewWidth /= window.devicePixelRatio; | ||
while (node !== containerNode && containerNode.contains(node)) { | ||
offsetX += node.offsetLeft; | ||
offsetY += node.offsetTop; | ||
node = node.offsetParent; | ||
} | ||
switch (horizontalAnchor) { | ||
@@ -49,6 +38,6 @@ case HorizontalDragAnchors.LEFT: | ||
case HorizontalDragAnchors.CENTER: | ||
offsetX *= previewWidth / containerWidth; | ||
x *= previewWidth / containerWidth; | ||
break; | ||
case HorizontalDragAnchors.RIGHT: | ||
offsetX = previewWidth - previewWidth * (1 - offsetX / containerWidth); | ||
x = previewWidth - previewWidth * (1 - x / containerWidth); | ||
break; | ||
@@ -61,6 +50,6 @@ } | ||
case VerticalDragAnchors.CENTER: | ||
offsetY *= previewHeight / containerHeight; | ||
y *= previewHeight / containerHeight; | ||
break; | ||
case VerticalDragAnchors.BOTTOM: | ||
offsetY = previewHeight - previewHeight * (1 - offsetY / containerHeight); | ||
y = previewHeight - previewHeight * (1 - y / containerHeight); | ||
break; | ||
@@ -72,8 +61,8 @@ } | ||
// We'll have to wait for @3x to see if this is entirely correct | ||
offsetY += (window.devicePixelRatio - 1) * previewHeight; | ||
y += (window.devicePixelRatio - 1) * previewHeight; | ||
} | ||
return { | ||
x: offsetX, | ||
y: offsetY | ||
x: x, | ||
y: y | ||
}; | ||
@@ -80,0 +69,0 @@ } |
"use strict"; | ||
function isFileDragDropEvent(e) { | ||
if (!e.dataTransfer) { | ||
return false; | ||
} | ||
var types = Array.prototype.slice.call(e.dataTransfer.types); | ||
@@ -5,0 +9,0 @@ return types.indexOf("Files") !== -1; |
@@ -1,1 +0,1 @@ | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.ReactDND=e():t.ReactDND=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";t.exports={DragDropMixin:n(31),ImagePreloaderMixin:n(32),HorizontalDragAnchors:n(18),VerticalDragAnchors:n(20),NativeDragItemTypes:n(19),DropEffects:n(4)}},function(t){function e(t){return"number"==typeof t&&t>-1&&t%1==0&&n>=t}var n=Math.pow(2,53)-1;t.exports=e},function(t){function e(t){var e=typeof t;return"function"==e||t&&"object"==e||!1}t.exports=e},function(t,e,n){function r(t){return null==t?!1:f.call(t)==s?h.test(u.call(t)):o(t)&&a.test(t)||!1}var i=n(66),o=n(5),s="[object Function]",a=/^\[object .+?Constructor\]$/,c=Object.prototype,u=Function.prototype.toString,f=c.toString,h=RegExp("^"+i(f).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=r},function(t){"use strict";var e={COPY:"copy",MOVE:"move",LINK:"link"};t.exports=e},function(t){function e(t){return t&&"object"==typeof t||!1}t.exports=e},function(t,e,n){var r=n(1),i=n(3),o=n(5),s="[object Array]",a=Object.prototype,c=a.toString,u=i(u=Array.isArray)&&u,f=u||function(t){return o(t)&&r(t.length)&&c.call(t)==s||!1};t.exports=f},function(t,e,n){"use strict";var r=n(15),i=function(t){var e,n={};r(t instanceof Object&&!Array.isArray(t));for(e in t)t.hasOwnProperty(e)&&(n[e]=e);return n};t.exports=i},function(t){"use strict";function e(){return/firefox/i.test(navigator.userAgent)}t.exports=e},function(t){"use strict";function e(){return!!window.safari}t.exports=e},function(t,e,n){function r(){return o(i(arguments,!1,!0))}var i=n(52),o=n(55);t.exports=r},function(t,e,n){function r(t){return i(t,o(arguments,1))}var i=n(51),o=n(53);t.exports=r},function(t){function e(t,e){return t=+t,e=null==e?n:e,t>-1&&t%1==0&&e>t}var n=Math.pow(2,53)-1;t.exports=e},function(t,e,n){function r(t){var e=o(t)?t.length:void 0;return i(e)&&c.call(t)==s||!1}var i=n(1),o=n(5),s="[object Arguments]",a=Object.prototype,c=a.toString;t.exports=r},function(t){function e(t){if(null==t)throw new TypeError("Object.assign target cannot be null or undefined");for(var e=Object(t),n=Object.prototype.hasOwnProperty,r=1;r<arguments.length;r++){var i=arguments[r];if(null!=i){var o=Object(i);for(var s in o)n.call(o,s)&&(e[s]=o[s])}}return e}t.exports=e},function(t){"use strict";var e=function(t,e,n,r,i,o,s,a){if(!t){var c;if(void 0===e)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,i,o,s,a],f=0;c=new Error("Invariant Violation: "+e.replace(/%s/g,function(){return u[f++]}))}throw c.framesToPop=1,c}};t.exports=e},function(t,e,n){"use strict";var r=n(21),i=n(17),o={startDragging:function(t,e,n){r.handleAction({type:i.DRAG_START,itemType:t,item:e,effectsAllowed:n})},recordDrop:function(t){r.handleAction({type:i.DROP,dropEffect:t})},endDragging:function(){r.handleAction({type:i.DRAG_END})}};t.exports=o},function(t,e,n){"use strict";var r=n(7),i=r({DRAG_START:null,DRAG_END:null,DROP:null});t.exports=i},function(t,e,n){"use strict";var r=n(7),i=r({LEFT:null,CENTER:null,RIGHT:null});t.exports=i},function(t,e,n){"use strict";var r=(n(7),{FILE:"__NATIVE_FILE__"});t.exports=r},function(t,e,n){"use strict";var r=n(7),i=r({TOP:null,CENTER:null,BOTTOM:null});t.exports=i},function(t,e,n){"use strict";var r=n(43).Dispatcher,i=n(14),o=i(new r,{handleAction:function(t){this.dispatch({action:t})}});t.exports=o},function(t,e,n){"use strict";var r=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},i=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},o=n(10),s=n(11),a=function(){function t(){i(this,t),this._entered=[]}return r(t,null,{enter:{value:function(t){return this._entered=o(this._entered.filter(function(e){return document.body.contains(e)&&(!e.contains||e.contains(t))}),[t]),1===this._entered.length},writable:!0,configurable:!0},leave:{value:function(t){return this._entered=s(this._entered.filter(function(t){return document.body.contains(t)}),t),0===this._entered.length},writable:!0,configurable:!0},reset:{value:function(){this._entered=[]},writable:!0,configurable:!0}}),t}();t.exports=a},function(t){"use strict";function e(t,e){e||(e=t);for(var n in t)t.hasOwnProperty(n)&&"function"==typeof t[n]&&(t[n]=t[n].bind(e));return t}t.exports=e},function(t){"use strict";function e(t){var e=Array.prototype.slice.call(t.dataTransfer.types);return-1!==e.indexOf("Files")}t.exports=e},function(t,e,n){function r(t,e,n){if(e!==e)return i(t,n);for(var r=(n||0)-1,o=t.length;++r<o;)if(t[r]===e)return r;return-1}var i=n(59);t.exports=r},function(t,e,n){function r(t,e){var n=t.data,r="string"==typeof e||i(e)?n.set.has(e):n.hash[e];return r?0:-1}var i=n(2);t.exports=r},function(t,e,n){(function(e){var r=n(46),i=n(67),o=n(3),s=o(s=e.Set)&&s,a=o(a=Object.create)&&a,c=a&&s?function(t){return new r(t)}:i(null);t.exports=c}).call(e,function(){return this}())},function(t,e,n){(function(e){var r=n(3),i=/\bthis\b/,o=Object.prototype,s=(s=e.window)&&s.document,a=o.propertyIsEnumerable,c={};!function(){c.funcDecomp=!r(e.WinRTError)&&i.test(function(){return this}),c.funcNames="string"==typeof Function.name;try{c.dom=11===s.createDocumentFragment().nodeType}catch(t){c.dom=!1}try{c.nonEnumArgs=!a.call(arguments,1)}catch(t){c.nonEnumArgs=!0}}(0,0),t.exports=c}).call(e,function(){return this}())},function(t){"use strict";function e(t,e){if(t===e)return!0;var n;for(n in t)if(t.hasOwnProperty(n)&&(!e.hasOwnProperty(n)||t[n]!==e[n]))return!1;for(n in e)if(e.hasOwnProperty(n)&&!t.hasOwnProperty(n))return!1;return!0}t.exports=e},function(t,e,n){"use strict";function r(t){var e=t.getBoundingClientRect();return{top:e.top,left:e.left,width:e.width,height:e.height}}function i(){if(!l){var t=r(h);l=!_(p,t)}return l}function o(){h&&g&&!document.body.contains(h)&&g()}function s(t){y(t)&&t.preventDefault()}function a(t){s(t);var e=x.enter(t.target);e&&y(t)&&v.startDragging(m.FILE,null)}function c(t){s(t),d&&(t.dataTransfer.dropEffect=d,d=null),h&&w()&&i()&&t.preventDefault()}function u(t){s(t);var e=x.leave(t.target);e&&y(t)&&v.endDragging()}function f(t){s(t),x.reset(),y(t)&&v.endDragging(),o()}var h,p,g,l,d,v=n(16),m=n(19),D=(n(4),n(22)),y=n(24),_=n(29),w=(n(10),n(11),n(41)),x=(n(8),new D),E={setup:function(){"undefined"!=typeof window&&(window.addEventListener("dragenter",a),window.addEventListener("dragover",c),window.addEventListener("dragleave",u),window.addEventListener("drop",f))},teardown:function(){"undefined"!=typeof window&&(window.removeEventListener("dragenter",a),window.removeEventListener("dragover",c),window.removeEventListener("dragleave",u),window.removeEventListener("drop",f))},beginDrag:function(t,e){h=t,p=r(t),l=!1,g=e,window.addEventListener("mousemove",o),window.addEventListener("mousein",o)},endDrag:function(){h=null,p=null,l=!1,g=null,window.removeEventListener("mousemove",o),window.removeEventListener("mousein",o)},dragOver:function(t,e){d||(d=e)}};t.exports=E},function(t,e,n){"use strict";function r(t,e){m(e&&"string"==typeof e,"Expected item type to be a non-empty string. See %s",t.constructor.displayName)}function i(t,e){var n=t.constructor.displayName;m(t._dragSources[e],'There is no drag source for "%s" registered in %s. Have you forgotten to register it? See configureDragDrop in %s',e,n,n)}function o(t,e){var n=t.constructor.displayName;m(t._dropTargets[e],'There is no drop target for "%s" registered in %s. Have you forgotten to register it? See configureDragDrop in %s',e,n,n)}function s(t,e){for(var n=arguments.length,r=Array(n>2?n-2:0),i=2;n>i;i++)r[i-2]=arguments[i];return e.constructor._legacyConfigureDragDrop?t.apply(e,r):t.call.apply(t,[null,e].concat(c(r)))}function a(t){return t.join(b)}var c=function(t){return Array.isArray(t)?t:Array.from(t)},u=n(16),f=n(34),h=n(30),p=n(22),g=n(33),l=n(4),d=n(35),v=n(24),m=(n(23),n(15)),D=n(71),y=n(14),_=n(63),w=(n(10),n(11),n(6)),x=n(2),E=n(69),b=String.fromCharCode(55357,56489),A=0,T={canDrag:function(){return!0},beginDrag:function(){m(!1,"Drag source must contain a method called beginDrag. See https://github.com/gaearon/react-dnd#drag-source-api")},endDrag:E},I={canDrop:function(){return!0},getDropEffect:function(t,e){return e[0]},enter:E,over:E,leave:E,acceptDrop:E},L={canDrop:function(){return!0},getDropEffect:function(t){return t[0]},enter:E,over:E,leave:E,acceptDrop:E},O={mixins:[g],getInitialState:function(){var t={ownDraggedItemType:null,currentDropEffect:null};return y(t,this.getStateFromDragDropStore())},getActiveDropTargetType:function(){var t=this.state,e=t.draggedItemType,n=t.draggedItem,r=t.ownDraggedItemType,i=this._dropTargets[e];if(!i)return null;if(e===r)return null;var o=i.canDrop;return s(o,this,n)?e:null},isAnyDropTargetActive:function(t){return t.indexOf(this.getActiveDropTargetType())>-1},getStateFromDragDropStore:function(){return{draggedItem:f.getDraggedItem(),draggedItemType:f.getDraggedItemType()}},getDragState:function(t){return r(this,t),i(this,t),{isDragging:this.state.ownDraggedItemType===t}},getDropState:function(t){r(this,t),o(this,t);var e=this.getActiveDropTargetType()===t,n=!!this.state.currentDropEffect;return{isDragging:e,isHovering:e&&n}},componentWillMount:function(){this._monitor=new p,this._dragSources={},this._dropTargets={},this.configureDragDrop?(D(this.constructor._legacyConfigureDragDrop,'%s declares configureDragDrop as an instance method, which is deprecated and will be removed in next version. Move configureDragDrop to statics and change all methods inside it to accept component as first parameter instead of using "this".',this.constructor.displayName),this.constructor._legacyConfigureDragDrop=!0,this.configureDragDrop(this.registerDragDropItemTypeHandlers)):this.constructor.configureDragDrop?this.constructor.configureDragDrop(this.registerDragDropItemTypeHandlers):m(this.constructor.configureDragDrop,"%s must implement static configureDragDrop(registerType) to use DragDropMixin",this.constructor.displayName)},componentDidMount:function(){0===A&&h.setup(),A++,f.addChangeListener(this.handleDragDropStoreChange)},componentWillUnmount:function(){A--,0===A&&h.teardown(),f.removeChangeListener(this.handleDragDropStoreChange)},registerDragDropItemTypeHandlers:function(t,e){r(this,t);var n=e.dragSource,i=e.dropTarget;n&&(m(!this._dragSources[t],"Drag source for %s specified twice. See configureDragDrop in %s",t,this.constructor.displayName),this._dragSources[t]=_(n,T)),i&&(m(!this._dropTargets[t],"Drop target for %s specified twice. See configureDragDrop in %s",t,this.constructor.displayName),this._dropTargets[t]=_(i,this.constructor._legacyConfigureDragDrop?L:I))},handleDragDropStoreChange:function(){this.isMounted()&&this.setState(this.getStateFromDragDropStore())},dragSourceFor:function(t){return r(this,t),i(this,t),{draggable:!0,onDragStart:this.memoizeBind("handleDragStart",t),onDragEnd:this.memoizeBind("handleDragEnd",t)}},handleDragStart:function(t,e){var n=this,r=this._dragSources[t],i=r.canDrag,o=r.beginDrag;if(!s(i,this,e))return void e.preventDefault();h.beginDrag(e.target,this.handleDragEnd.bind(this,t,null));var a=s(o,this,e),c=a.item,p=a.dragPreview,g=a.dragAnchors,v=a.effectsAllowed;v||(v=[l.MOVE]),m(w(v)&&v.length>0,"Expected effectsAllowed to be non-empty array"),m(x(c),'Expected return value of beginDrag to contain "item" object'),d(this.getDOMNode(),e.nativeEvent,p,g,v),u.startDragging(t,c,v),setTimeout(function(){n.isMounted()&&f.getDraggedItem()===c&&n.setState({ownDraggedItemType:t})})},handleDragEnd:function(t,e){h.endDrag();var n=this._dragSources[t].endDrag,r=f.getDropEffect();u.endDragging(),this.isMounted()&&this.setState({ownDraggedItemType:null}),s(n,this,r,e)},dropTargetFor:function(){for(var t=this,e=arguments.length,n=Array(e),i=0;e>i;i++)n[i]=arguments[i];return n.forEach(function(e){r(t,e),o(t,e)}),{onDragEnter:this.memoizeBind("handleDragEnter",n,a),onDragOver:this.memoizeBind("handleDragOver",n,a),onDragLeave:this.memoizeBind("handleDragLeave",n,a),onDrop:this.memoizeBind("handleDrop",n,a)}},handleDragEnter:function(t,e){if(this.isAnyDropTargetActive(t)&&this._monitor.enter(e.target)){var n=this._dropTargets[this.state.draggedItemType],r=n.enter,i=n.getDropEffect,o=f.getEffectsAllowed();v(e)&&(o=[l.COPY]);var a=s(i,this,o);a&&m(o.indexOf(a)>-1,"Effect %s supplied by drop target is not one of the effects allowed by drag source: %s",a,o.join(", ")),this.setState({currentDropEffect:a}),s(r,this,this.state.draggedItem,e)}},handleDragOver:function(t,e){if(this.isAnyDropTargetActive(t)){e.preventDefault();var n=this._dropTargets[this.state.draggedItemType].over;s(n,this,this.state.draggedItem,e),h.dragOver(e,this.state.currentDropEffect||"move")}},handleDragLeave:function(t,e){if(this.isAnyDropTargetActive(t)&&this._monitor.leave(e.target)){this.setState({currentDropEffect:null});var n=this._dropTargets[this.state.draggedItemType].leave;s(n,this,this.state.draggedItem,e)}},handleDrop:function(t,e){if(this.isAnyDropTargetActive(t)){e.preventDefault();var n=this.state.draggedItem,r=this._dropTargets[this.state.draggedItemType].acceptDrop,i=this.state.currentDropEffect,o=!!f.getDropEffect();v(e)&&(n={files:Array.prototype.slice.call(e.dataTransfer.files)}),this._monitor.reset(),o||u.recordDrop(i),this.setState({currentDropEffect:null}),s(r,this,n,e,o,f.getDropEffect())}}};t.exports=O},function(t,e,n){"use strict";var r=n(40),i="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",o={componentDidMount:function(){this._cachedImages={},this._readyImages={},this.preloadImages()},componentDidUpdate:function(){this.preloadImages()},componentWillUnmount:function(){for(var t in this._cachedImages)this._cachedImages[t].src=i;this._cachedImages={}},hasPreloadedImage:function(t){return!!this._readyImages[t]},getPreloadedImage:function(t){return this.hasPreloadedImage(t)?this._cachedImages[t]:void 0},preloadImages:function(){var t=this.getImageUrlsToPreload();t.forEach(this.preloadImage)},preloadImage:function(t){var e=this;if(t&&!this._cachedImages[t]){var n=new Image;n.onload=function(){e.isMounted()&&(e._readyImages[t]=!0)},n.onerror=function(){e.isMounted()&&delete e._cachedImages[t]},n.src=t,this._cachedImages[t]=n}},getDragImageScale:r};t.exports=o},function(t,e,n){"use strict";var r=n(15),i={memoizeBind:function(t,e,n){var i=n?n(e):e;return r("string"==typeof i,"Expected memoization key to be a string, got %s",e),this.__cachedBoundMethods||(this.__cachedBoundMethods={}),this.__cachedBoundMethods[t]||(this.__cachedBoundMethods[t]={}),this.__cachedBoundMethods[t][i]||(this.__cachedBoundMethods[t][i]=this[t].bind(this,e)),this.__cachedBoundMethods[t][i]},componentWillUnmount:function(){this.__cachedBoundMethods={}}};t.exports=i},function(t,e,n){"use strict";var r=n(21),i=n(17),o=n(36),s=null,a=null,c=null,u=null,f=o({isDragging:function(){return!!s},getEffectsAllowed:function(){return c},getDropEffect:function(){return u},getDraggedItem:function(){return s},getDraggedItemType:function(){return a}});r.register(function(t){var e=t.action;switch(e.type){case i.DRAG_START:u=null,s=e.item,a=e.itemType,c=e.effectsAllowed,f.emitChange();break;case i.DROP:u=e.dropEffect,f.emitChange();break;case i.DRAG_END:s=null,a=null,c=null,u=null,f.emitChange()}}),t.exports=f},function(t,e,n){"use strict";function r(t,e,n,r,a){var c=e.dataTransfer;try{c.setData("application/json",{})}catch(u){}if(i(n)&&c.setDragImage){var f=o(t,n,r,e);c.setDragImage(n,f.x,f.y)}c.effectAllowed=s(a)}var i=n(42),o=n(39),s=n(38);t.exports=r},function(t,e,n){"use strict";function r(t){var e=o({emitChange:function(){this.emit(a)},addChangeListener:function(t){this.on(a,t)},removeChangeListener:function(t){this.removeListener(a,t)}},t,i.prototype);return e.setMaxListeners(0),s(e),e}var i=n(72).EventEmitter,o=n(14),s=(n(29),n(23)),a="change";t.exports=r},function(t){"use strict";function e(t,e){return-1!==t.indexOf(e,t.length-e.length)}t.exports=e},function(t,e,n){"use strict";function r(t){var e=t.indexOf(i.COPY)>-1,n=t.indexOf(i.MOVE)>-1,r=t.indexOf(i.LINK)>-1;return e&&n&&r?"all":e&&n?"copyMove":r&&n?"linkMove":e&&r?"copyLink":e?"copy":n?"move":r?"link":"none"}var i=n(4);t.exports=r},function(t,e,n){"use strict";function r(t,e,n,r){n=n||{};var c=t.offsetWidth,u=t.offsetHeight,f=e instanceof Image,h=f?e.width:c,p=f?e.height:u,g=n.horizontal||i.CENTER,l=n.vertical||o.CENTER,d=r.offsetX,v=r.offsetY,m=r.target;for(s()?(d=r.layerX,v=r.layerY):a()&&(p/=window.devicePixelRatio,h/=window.devicePixelRatio);m!==t&&t.contains(m);)d+=m.offsetLeft,v+=m.offsetTop,m=m.offsetParent;switch(g){case i.LEFT:break;case i.CENTER:d*=h/c;break;case i.RIGHT:d=h-h*(1-d/c)}switch(l){case o.TOP:break;case o.CENTER:v*=p/u;break;case o.BOTTOM:v=p-p*(1-v/u)}return a()&&(v+=(window.devicePixelRatio-1)*p),{x:d,y:v}}var i=n(18),o=n(20),s=n(8),a=n(9);t.exports=r},function(t,e,n){"use strict";function r(){return i()||o()?window.devicePixelRatio:1}var i=n(8),o=n(9);t.exports=r},function(t){"use strict";function e(){return"WebkitAppearance"in document.documentElement.style}t.exports=e},function(t,e,n){"use strict";function r(t){return t?i()&&t instanceof Image&&o(t.src,".gif")?!1:!0:!1}var i=n(9),o=n(37);t.exports=r},function(t,e,n){t.exports.Dispatcher=n(44)},function(t,e,n){"use strict";function r(){this.$Dispatcher_callbacks={},this.$Dispatcher_isPending={},this.$Dispatcher_isHandled={},this.$Dispatcher_isDispatching=!1,this.$Dispatcher_pendingPayload=null}var i=n(45),o=1,s="ID_";r.prototype.register=function(t){var e=s+o++;return this.$Dispatcher_callbacks[e]=t,e},r.prototype.unregister=function(t){i(this.$Dispatcher_callbacks[t],"Dispatcher.unregister(...): `%s` does not map to a registered callback.",t),delete this.$Dispatcher_callbacks[t]},r.prototype.waitFor=function(t){i(this.$Dispatcher_isDispatching,"Dispatcher.waitFor(...): Must be invoked while dispatching.");for(var e=0;e<t.length;e++){var n=t[e];this.$Dispatcher_isPending[n]?i(this.$Dispatcher_isHandled[n],"Dispatcher.waitFor(...): Circular dependency detected while waiting for `%s`.",n):(i(this.$Dispatcher_callbacks[n],"Dispatcher.waitFor(...): `%s` does not map to a registered callback.",n),this.$Dispatcher_invokeCallback(n))}},r.prototype.dispatch=function(t){i(!this.$Dispatcher_isDispatching,"Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch."),this.$Dispatcher_startDispatching(t);try{for(var e in this.$Dispatcher_callbacks)this.$Dispatcher_isPending[e]||this.$Dispatcher_invokeCallback(e)}finally{this.$Dispatcher_stopDispatching()}},r.prototype.isDispatching=function(){return this.$Dispatcher_isDispatching},r.prototype.$Dispatcher_invokeCallback=function(t){this.$Dispatcher_isPending[t]=!0,this.$Dispatcher_callbacks[t](this.$Dispatcher_pendingPayload),this.$Dispatcher_isHandled[t]=!0},r.prototype.$Dispatcher_startDispatching=function(t){for(var e in this.$Dispatcher_callbacks)this.$Dispatcher_isPending[e]=!1,this.$Dispatcher_isHandled[e]=!1;this.$Dispatcher_pendingPayload=t,this.$Dispatcher_isDispatching=!0},r.prototype.$Dispatcher_stopDispatching=function(){this.$Dispatcher_pendingPayload=null,this.$Dispatcher_isDispatching=!1},t.exports=r},function(t){"use strict";var e=function(t,e,n,r,i,o,s,a){if(!t){var c;if(void 0===e)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,i,o,s,a],f=0;c=new Error("Invariant Violation: "+e.replace(/%s/g,function(){return u[f++]}))}throw c.framesToPop=1,c}};t.exports=e},function(t,e,n){(function(e){function r(t){var e=t?t.length:0;for(this.data={hash:a(null),set:new s};e--;)this.push(t[e])}var i=n(57),o=n(3),s=o(s=e.Set)&&s,a=o(a=Object.create)&&a;r.prototype.push=i,t.exports=r}).call(e,function(){return this}())},function(t){function e(t,e){var n=-1,r=t.length;for(e||(e=Array(r));++n<r;)e[n]=t[n];return e}t.exports=e},function(t){function e(t,e){return"undefined"==typeof t?e:t}t.exports=e},function(t,e,n){function r(t,e,n){var r=o(e);if(!n)return i(e,t,r);for(var s=-1,a=r.length;++s<a;){var c=r[s],u=t[c],f=n(u,e[c],c,t,e);(f===f?f===u:u!==u)&&("undefined"!=typeof u||c in t)||(t[c]=f)}return t}var i=n(50),o=n(64);t.exports=r},function(t){function e(t,e,n){n||(n=e,e={});for(var r=-1,i=n.length;++r<i;){var o=n[r];e[o]=t[o]}return e}t.exports=e},function(t,e,n){function r(t,e){var n=t?t.length:0,r=[];if(!n)return r;var a=-1,c=i,u=!0,f=u&&e.length>=200&&s(e),h=e.length;f&&(c=o,u=!1,e=f);t:for(;++a<n;){var p=t[a];if(u&&p===p){for(var g=h;g--;)if(e[g]===p)continue t;r.push(p)}else c(e,p)<0&&r.push(p)}return r}var i=n(25),o=n(26),s=n(27);t.exports=r},function(t,e,n){function r(t,e,n,c){for(var u=(c||0)-1,f=t.length,h=-1,p=[];++u<f;){var g=t[u];if(a(g)&&s(g.length)&&(o(g)||i(g))){e&&(g=r(g,e,n));var l=-1,d=g.length;for(p.length+=d;++l<d;)p[++h]=g[l]}else n||(p[++h]=g)}return p}var i=n(13),o=n(6),s=n(1),a=n(5);t.exports=r},function(t){function e(t,e,n){var r=-1,i=t.length;e=null==e?0:+e||0,0>e&&(e=-e>i?0:i+e),n="undefined"==typeof n||n>i?i:+n||0,0>n&&(n+=i),i=e>n?0:n-e>>>0,e>>>=0;for(var o=Array(i);++r<i;)o[r]=t[r+e];return o}t.exports=e},function(t){function e(t){return"string"==typeof t?t:null==t?"":t+""}t.exports=e},function(t,e,n){function r(t,e){var n=-1,r=i,a=t.length,c=!0,u=c&&a>=200,f=u&&s(),h=[];f?(r=o,c=!1):(u=!1,f=e?[]:h);t:for(;++n<a;){var p=t[n],g=e?e(p,n,t):p;if(c&&p===p){for(var l=f.length;l--;)if(f[l]===g)continue t;e&&f.push(g),h.push(p)}else r(f,g)<0&&((e||u)&&f.push(g),h.push(p))}return h}var i=n(25),o=n(26),s=n(27);t.exports=r},function(t,e,n){function r(t,e,n){if("function"!=typeof t)return i;if("undefined"==typeof e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 3:return function(n,r,i){return t.call(e,n,r,i)};case 4:return function(n,r,i,o){return t.call(e,n,r,i,o)};case 5:return function(n,r,i,o,s){return t.call(e,n,r,i,o,s)}}return function(){return t.apply(e,arguments)}}var i=n(68);t.exports=r},function(t,e,n){function r(t){var e=this.data;"string"==typeof t||i(t)?e.set.add(t):e.hash[t]=!0}var i=n(2);t.exports=r},function(t,e,n){function r(t){return function(){var e=arguments.length,n=arguments[0];if(2>e||null==n)return n;if(e>3&&o(arguments[1],arguments[2],arguments[3])&&(e=2),e>3&&"function"==typeof arguments[e-2])var r=i(arguments[--e-1],arguments[e--],5);else e>2&&"function"==typeof arguments[e-1]&&(r=arguments[--e]);for(var s=0;++s<e;){var a=arguments[s];a&&t(n,a,r)}return n}}var i=n(56),o=n(60);t.exports=r},function(t){function e(t,e,n){for(var r=t.length,i=n?e||r:(e||0)-1;n?i--:++i<r;){var o=t[i];if(o!==o)return i}return-1}t.exports=e},function(t,e,n){function r(t,e,n){if(!s(n))return!1;var r=typeof e;if("number"==r)var a=n.length,c=o(a)&&i(e,a);else c="string"==r&&e in n;return c&&n[e]===t}var i=n(12),o=n(1),s=n(2);t.exports=r},function(t,e,n){function r(t){for(var e=c(t),n=e.length,r=n&&t.length,f=r&&a(r)&&(o(t)||u.nonEnumArgs&&i(t)),p=-1,g=[];++p<n;){var l=e[p];(f&&s(l,r)||h.call(t,l))&&g.push(l)}return g}var i=n(13),o=n(6),s=n(12),a=n(1),c=n(65),u=n(28),f=Object.prototype,h=f.hasOwnProperty;t.exports=r},function(t,e,n){var r=n(49),i=n(58),o=i(r);t.exports=o},function(t,e,n){function r(t){if(null==t)return t;var e=i(arguments);return e.push(s),o.apply(void 0,e)}var i=n(47),o=n(62),s=n(48);t.exports=r},function(t,e,n){var r=n(1),i=n(3),o=n(2),s=n(61),a=i(a=Object.keys)&&a,c=a?function(t){if(t)var e=t.constructor,n=t.length;return"function"==typeof e&&e.prototype===t||"function"!=typeof t&&n&&r(n)?s(t):o(t)?a(t):[]}:s;t.exports=c},function(t,e,n){function r(t){if(null==t)return[];c(t)||(t=Object(t));var e=t.length;e=e&&a(e)&&(o(t)||u.nonEnumArgs&&i(t))&&e||0;for(var n=t.constructor,r=-1,f="function"==typeof n&&n.prototype==t,p=Array(e),g=e>0;++r<e;)p[r]=r+"";for(var l in t)g&&s(l,e)||"constructor"==l&&(f||!h.call(t,l))||p.push(l);return p}var i=n(13),o=n(6),s=n(12),a=n(1),c=n(2),u=n(28),f=Object.prototype,h=f.hasOwnProperty;t.exports=r},function(t,e,n){function r(t){return t=i(t),t&&s.test(t)?t.replace(o,"\\$&"):t}var i=n(54),o=/[.*+?^${}()|[\]\/\\]/g,s=RegExp(o.source);t.exports=r},function(t){function e(t){return function(){return t}}t.exports=e},function(t){function e(t){return t}t.exports=e},function(t){function e(){}t.exports=e},function(t){function e(t){return function(){return t}}function n(){}n.thatReturns=e,n.thatReturnsFalse=e(!1),n.thatReturnsTrue=e(!0),n.thatReturnsNull=e(null),n.thatReturnsThis=function(){return this},n.thatReturnsArgument=function(t){return t},t.exports=n},function(t,e,n){"use strict";var r=n(70),i=r;t.exports=i},function(t){function e(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function n(t){return"function"==typeof t}function r(t){return"number"==typeof t}function i(t){return"object"==typeof t&&null!==t}function o(t){return void 0===t}t.exports=e,e.EventEmitter=e,e.prototype._events=void 0,e.prototype._maxListeners=void 0,e.defaultMaxListeners=10,e.prototype.setMaxListeners=function(t){if(!r(t)||0>t||isNaN(t))throw TypeError("n must be a positive number");return this._maxListeners=t,this},e.prototype.emit=function(t){var e,r,s,a,c,u;if(this._events||(this._events={}),"error"===t&&(!this._events.error||i(this._events.error)&&!this._events.error.length)){if(e=arguments[1],e instanceof Error)throw e;throw TypeError('Uncaught, unspecified "error" event.')}if(r=this._events[t],o(r))return!1;if(n(r))switch(arguments.length){case 1:r.call(this);break;case 2:r.call(this,arguments[1]);break;case 3:r.call(this,arguments[1],arguments[2]);break;default:for(s=arguments.length,a=new Array(s-1),c=1;s>c;c++)a[c-1]=arguments[c];r.apply(this,a)}else if(i(r)){for(s=arguments.length,a=new Array(s-1),c=1;s>c;c++)a[c-1]=arguments[c];for(u=r.slice(),s=u.length,c=0;s>c;c++)u[c].apply(this,a)}return!0},e.prototype.addListener=function(t,r){var s;if(!n(r))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",t,n(r.listener)?r.listener:r),this._events[t]?i(this._events[t])?this._events[t].push(r):this._events[t]=[this._events[t],r]:this._events[t]=r,i(this._events[t])&&!this._events[t].warned){var s;s=o(this._maxListeners)?e.defaultMaxListeners:this._maxListeners,s&&s>0&&this._events[t].length>s&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),"function"==typeof console.trace&&console.trace())}return this},e.prototype.on=e.prototype.addListener,e.prototype.once=function(t,e){function r(){this.removeListener(t,r),i||(i=!0,e.apply(this,arguments))}if(!n(e))throw TypeError("listener must be a function");var i=!1;return r.listener=e,this.on(t,r),this},e.prototype.removeListener=function(t,e){var r,o,s,a;if(!n(e))throw TypeError("listener must be a function");if(!this._events||!this._events[t])return this;if(r=this._events[t],s=r.length,o=-1,r===e||n(r.listener)&&r.listener===e)delete this._events[t],this._events.removeListener&&this.emit("removeListener",t,e);else if(i(r)){for(a=s;a-->0;)if(r[a]===e||r[a].listener&&r[a].listener===e){o=a;break}if(0>o)return this;1===r.length?(r.length=0,delete this._events[t]):r.splice(o,1),this._events.removeListener&&this.emit("removeListener",t,e)}return this},e.prototype.removeAllListeners=function(t){var e,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[t]&&delete this._events[t],this;if(0===arguments.length){for(e in this._events)"removeListener"!==e&&this.removeAllListeners(e);return this.removeAllListeners("removeListener"),this._events={},this}if(r=this._events[t],n(r))this.removeListener(t,r);else for(;r.length;)this.removeListener(t,r[r.length-1]);return delete this._events[t],this},e.prototype.listeners=function(t){var e;return e=this._events&&this._events[t]?n(this._events[t])?[this._events[t]]:this._events[t].slice():[]},e.listenerCount=function(t,e){var r;return r=t._events&&t._events[e]?n(t._events[e])?1:t._events[e].length:0}}])}); | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):"object"==typeof exports?exports.ReactDND=e():t.ReactDND=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";var r=n(30),i=r.HTML5,o=n(38);t.exports={DragDropMixin:o(i),ImagePreloaderMixin:n(32),DragLayerMixin:n(31),HorizontalDragAnchors:n(19),VerticalDragAnchors:n(21),NativeDragItemTypes:n(20),DropEffects:n(9)}},function(t){function e(t){return"number"==typeof t&&t>-1&&t%1==0&&n>=t}var n=Math.pow(2,53)-1;t.exports=e},function(t){function e(t){var e=typeof t;return"function"==e||t&&"object"==e||!1}t.exports=e},function(t,e,n){function r(t){return null==t?!1:f.call(t)==s?g.test(u.call(t)):o(t)&&a.test(t)||!1}var i=n(71),o=n(4),s="[object Function]",a=/^\[object .+?Constructor\]$/,c=Object.prototype,u=Function.prototype.toString,f=c.toString,g=RegExp("^"+i(f).replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=r},function(t){function e(t){return t&&"object"==typeof t||!1}t.exports=e},function(t,e,n){var r=n(1),i=n(3),o=n(4),s="[object Array]",a=Object.prototype,c=a.toString,u=i(u=Array.isArray)&&u,f=u||function(t){return o(t)&&r(t.length)&&c.call(t)==s||!1};t.exports=f},function(t){function e(){}t.exports=e},function(t,e,n){"use strict";var r=n(17),i=function(t){var e,n={};r(t instanceof Object&&!Array.isArray(t));for(e in t)t.hasOwnProperty(e)&&(n[e]=e);return n};t.exports=i},function(t,e,n){"use strict";var r=n(7),i=r({DRAG_START:null,DRAG_END:null,DRAG:null,DROP:null});t.exports=i},function(t){"use strict";var e={COPY:"copy",MOVE:"move",LINK:"link"};t.exports=e},function(t,e,n){"use strict";var r=n(46).Dispatcher,i=n(16),o=i(new r,{handleAction:function(t){this.dispatch({action:t})}});t.exports=o},function(t,e,n){"use strict";var r=n(10),i=n(8),o=n(23),s=null,a=null,c=null,u=o({getInitialOffsetFromContainer:function(){return s},getInitialOffsetFromClient:function(){return a},getCurrentOffsetFromClient:function(){return c}});u.dispatchToken=r.register(function(t){var e=t.action;switch(e.type){case i.DRAG_START:s=e.offsetFromContainer,a=e.offsetFromClient,c=e.offsetFromClient,u.emitChange();break;case i.DRAG:c=e.offsetFromClient,u.emitChange();break;case i.DRAG_END:c=null,c=null,u.emitChange()}}),t.exports=u},function(t,e,n){"use strict";var r=n(10),i=n(8),o=n(11),s=n(23),a=null,c=null,u=null,f=null,g=s({isDragging:function(){return!!a},getEffectsAllowed:function(){return u},getDropEffect:function(){return f},getDraggedItem:function(){return a},getDraggedItemType:function(){return c}});g.dispatchToken=r.register(function(t){r.waitFor([o.dispatchToken]);var e=t.action;switch(e.type){case i.DRAG_START:f=null,a=e.item,c=e.itemType,u=e.effectsAllowed,g.emitChange();break;case i.DROP:f=e.dropEffect,g.emitChange();break;case i.DRAG_END:a=null,c=null,u=null,f=null,g.emitChange()}}),t.exports=g},function(t){"use strict";function e(){return!!window.safari}t.exports=e},function(t){function e(t,e){return t=+t,e=null==e?n:e,t>-1&&t%1==0&&e>t}var n=Math.pow(2,53)-1;t.exports=e},function(t,e,n){function r(t){var e=o(t)?t.length:void 0;return i(e)&&c.call(t)==s||!1}var i=n(1),o=n(4),s="[object Arguments]",a=Object.prototype,c=a.toString;t.exports=r},function(t){function e(t){if(null==t)throw new TypeError("Object.assign target cannot be null or undefined");for(var e=Object(t),n=Object.prototype.hasOwnProperty,r=1;r<arguments.length;r++){var i=arguments[r];if(null!=i){var o=Object(i);for(var s in o)n.call(o,s)&&(e[s]=o[s])}}return e}t.exports=e},function(t){"use strict";var e=function(t,e,n,r,i,o,s,a){if(!t){var c;if(void 0===e)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,i,o,s,a],f=0;c=new Error("Invariant Violation: "+e.replace(/%s/g,function(){return u[f++]}))}throw c.framesToPop=1,c}};t.exports=e},function(t,e,n){"use strict";var r=n(10),i=n(8),o={startDragging:function(t,e,n,o,s){r.handleAction({type:i.DRAG_START,itemType:t,item:e,effectsAllowed:n,offsetFromClient:o,offsetFromContainer:s})},drag:function(t){r.handleAction({type:i.DRAG,offsetFromClient:t})},recordDrop:function(t){r.handleAction({type:i.DROP,dropEffect:t})},endDragging:function(){r.handleAction({type:i.DRAG_END})}};t.exports=o},function(t,e,n){"use strict";var r=n(7),i=r({LEFT:null,CENTER:null,RIGHT:null});t.exports=i},function(t,e,n){"use strict";var r=(n(7),{FILE:"__NATIVE_FILE__"});t.exports=r},function(t,e,n){"use strict";var r=n(7),i=r({TOP:null,CENTER:null,BOTTOM:null});t.exports=i},function(t,e,n){"use strict";var r=function(t,e,n){e&&Object.defineProperties(t,e),n&&Object.defineProperties(t.prototype,n)},i=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},o=n(49),s=n(50),a=function(){function t(){i(this,t),this._entered=[]}return r(t,null,{enter:{value:function(t){return this._entered=o(this._entered.filter(function(e){return document.body.contains(e)&&(!e.contains||e.contains(t))}),[t]),1===this._entered.length},writable:!0,configurable:!0},leave:{value:function(t){return this._entered=s(this._entered.filter(function(t){return document.body.contains(t)}),t),0===this._entered.length},writable:!0,configurable:!0},reset:{value:function(){this._entered=[]},writable:!0,configurable:!0}}),t}();t.exports=a},function(t,e,n){"use strict";function r(t){var e=o({emitChange:function(){this.emit(s)},addChangeListener:function(t){this.on(s,t)},removeChangeListener:function(t){this.removeListener(s,t)}},t,i.prototype);return e.setMaxListeners(0),e}var i=n(77).EventEmitter,o=n(16),s="change";t.exports=r},function(t){"use strict";function e(t){if(!t.dataTransfer)return!1;var e=Array.prototype.slice.call(t.dataTransfer.types);return-1!==e.indexOf("Files")}t.exports=e},function(t,e,n){function r(t,e,n){if(e!==e)return i(t,n);for(var r=(n||0)-1,o=t.length;++r<o;)if(t[r]===e)return r;return-1}var i=n(64);t.exports=r},function(t,e,n){function r(t,e){var n=t.data,r="string"==typeof e||i(e)?n.set.has(e):n.hash[e];return r?0:-1}var i=n(2);t.exports=r},function(t,e,n){(function(e){var r=n(51),i=n(72),o=n(3),s=o(s=e.Set)&&s,a=o(a=Object.create)&&a,c=a&&s?function(t){return new r(t)}:i(null);t.exports=c}).call(e,function(){return this}())},function(t,e,n){(function(e){var r=n(3),i=/\bthis\b/,o=Object.prototype,s=(s=e.window)&&s.document,a=o.propertyIsEnumerable,c={};!function(){c.funcDecomp=!r(e.WinRTError)&&i.test(function(){return this}),c.funcNames="string"==typeof Function.name;try{c.dom=11===s.createDocumentFragment().nodeType}catch(t){c.dom=!1}try{c.nonEnumArgs=!a.call(arguments,1)}catch(t){c.nonEnumArgs=!0}}(0,0),t.exports=c}).call(e,function(){return this}())},function(t,e,n){"use strict";function r(t){var e=t.getBoundingClientRect();return{top:e.top,left:e.left,width:e.width,height:e.height}}function i(){if(!l){var t=r(g);l=!w(p,t)}return l}function o(){if(h&&!document.body.contains(g)){var t=m.getDraggedItemType();h.handleDragEnd(t,null)}}function s(t){x(t)&&t.preventDefault()}function a(t){s(t);var e=T.enter(t.target);e&&x(t)&&v.startDragging(D.FILE,null)}function c(t){s(t);var e=b.getOffsetFromClient(h,t);v.drag(e),d&&(t.dataTransfer.dropEffect=d,d=null),g&&E()&&i()&&t.preventDefault()}function u(t){s(t);var e=T.leave(t.target);e&&x(t)&&v.endDragging()}function f(t){s(t),T.reset(),x(t)&&v.endDragging(),o()}var g,h,p,l,d,v=n(18),m=n(12),D=n(20),y=n(22),x=n(24),_=n(37),w=n(75),E=n(44),T=new y,b={setup:function(){"undefined"!=typeof window&&(window.addEventListener("dragenter",a),window.addEventListener("dragover",c),window.addEventListener("dragleave",u),window.addEventListener("drop",f))},teardown:function(){"undefined"!=typeof window&&(window.removeEventListener("dragenter",a),window.removeEventListener("dragover",c),window.removeEventListener("dragleave",u),window.removeEventListener("drop",f))},beginDrag:function(t,e,n,i,s,a,c){var u=e.nativeEvent,f=u.dataTransfer,d=u.target;_(f,n,i,s,a,c),h=t,g=d,p=r(d),l=!1,window.addEventListener("mousemove",o),window.addEventListener("mousein",o)},endDrag:function(){g=null,h=null,p=null,l=!1,window.removeEventListener("mousemove",o),window.removeEventListener("mousein",o)},dragOver:function(t,e,n){d||(d=n)},getDragSourceProps:function(t,e){return{draggable:!0,onDragStart:t.handleDragStart.bind(t,e),onDragEnd:t.handleDragEnd.bind(t,e)}},getDropTargetProps:function(t,e){return{onDragEnter:t.handleDragEnter.bind(t,e),onDragOver:t.handleDragOver.bind(t,e),onDragLeave:t.handleDragLeave.bind(t,e),onDrop:t.handleDrop.bind(t,e)}},getOffsetFromClient:function(t,e){return{x:e.clientX,y:e.clientY}}};t.exports=b},function(t,e,n){"use strict";t.exports={HTML5:n(29)}},function(t,e,n){"use strict";var r=n(12),i=n(11),o={getInitialState:function(){return this.getStateForDragLayerMixin()},getDragLayerState:function(){var t=this.state,e=t.isDragging,n=t.draggedItemType,r=t.draggedItem,i=t.initialOffset,o=t.currentOffset;return{isDragging:e,draggedItemType:n,draggedItem:r,initialOffset:i,currentOffset:o}},getStateForDragLayerMixin:function(){var t=i.getInitialOffsetFromClient(),e=i.getCurrentOffsetFromClient(),n=i.getInitialOffsetFromContainer(),o=!1,s=null,a=null,c=null,u=null;return t&&e&&(o=!0,s=r.getDraggedItemType(),a=r.getDraggedItem(),c={x:t.x-n.x,y:t.y-n.y},u={x:e.x-n.x,y:e.y-n.y}),{isDragging:o,draggedItemType:s,draggedItem:a,initialOffset:c,currentOffset:u}},handleStoreChangeInDragLayerMixin:function(){this.isMounted()&&this.setState(this.getStateForDragLayerMixin())},componentDidMount:function(){i.addChangeListener(this.handleStoreChangeInDragLayerMixin),r.addChangeListener(this.handleStoreChangeInDragLayerMixin)},componentWillUnmount:function(){i.removeChangeListener(this.handleStoreChangeInDragLayerMixin),r.removeChangeListener(this.handleStoreChangeInDragLayerMixin)}};t.exports=o},function(t,e,n){"use strict";var r=n(42),i="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",o={componentDidMount:function(){this._cachedImages={},this._readyImages={},this.preloadImages()},componentDidUpdate:function(){this.preloadImages()},componentWillUnmount:function(){for(var t in this._cachedImages)this._cachedImages[t].src=i;this._cachedImages={}},hasPreloadedImage:function(t){return!!this._readyImages[t]},getPreloadedImage:function(t){return this.hasPreloadedImage(t)?this._cachedImages[t]:void 0},preloadImages:function(){var t=this.getImageUrlsToPreload();t.forEach(this.preloadImage)},preloadImage:function(t){var e=this;if(t&&!this._cachedImages[t]){var n=new Image;n.onload=function(){e.isMounted()&&(e._readyImages[t]=!0)},n.onerror=function(){e.isMounted()&&delete e._cachedImages[t]},n.src=t,this._cachedImages[t]=n}},getDragImageScale:r};t.exports=o},function(t,e,n){"use strict";var r=n(17),i=n(6),o={canDrag:function(){return!0},beginDrag:function(){r(!1,"Drag source must contain a method called beginDrag. See https://github.com/gaearon/react-dnd#drag-source-api")},endDrag:i};t.exports=o},function(t,e,n){"use strict";var r=n(6),i={canDrop:function(){return!0},getDropEffect:function(t,e){return e[0]},enter:r,over:r,leave:r,acceptDrop:r};t.exports=i},function(t,e,n){"use strict";var r=n(11),i={getCurrentOffsetDelta:function(){var t=r.getInitialOffsetFromClient(),e=r.getCurrentOffsetFromClient();return{x:e.x-t.x,y:e.y-t.y}}};t.exports=i},function(t,e,n){"use strict";var r=n(6),i={canDrop:function(){return!0},getDropEffect:function(t){return t[0]},enter:r,over:r,leave:r,acceptDrop:r};t.exports=i},function(t,e,n){"use strict";function r(t,e,n,r,a,c){try{t.setData("application/json",{})}catch(u){}if(i(n)&&t.setDragImage){var f=o(e,n,r,a);t.setDragImage(n,f.x,f.y)}t.effectAllowed=s(c)}var i=n(45),o=n(41),s=n(40);t.exports=r},function(t,e,n){"use strict";function r(t,e){m(e&&"string"==typeof e,"Expected item type to be a non-empty string. See %s",t.constructor.displayName)}function i(t,e){var n=t.constructor.displayName;m(t._dragSources[e],'There is no drag source for "%s" registered in %s. Have you forgotten to register it? See configureDragDrop in %s',e,n,n)}function o(t,e){var n=t.constructor.displayName;m(t._dropTargets[e],'There is no drop target for "%s" registered in %s. Have you forgotten to register it? See configureDragDrop in %s',e,n,n)}function s(t,e){for(var n=arguments.length,r=Array(n>2?n-2:0),i=2;n>i;i++)r[i-2]=arguments[i];return e.constructor._legacyConfigureDragDrop?t.apply(e,r):t.call.apply(t,[null,e].concat(r))}function a(t){function e(e){0===a&&t.setup(e),a++}function n(e){a--,0===a&&t.teardown(e)}var a=0;return{getInitialState:function(){var t={ownDraggedItemType:null,currentDropEffect:null};return y(t,this.getStateForDragDropMixin())},getActiveDropTargetType:function(){var t=this.state,e=t.draggedItemType,n=t.draggedItem,r=t.ownDraggedItemType,i=this._dropTargets[e];if(!i)return null;if(e===r)return null;var o=i.canDrop;return s(o,this,n)?e:null},isAnyDropTargetActive:function(t){return t.indexOf(this.getActiveDropTargetType())>-1},getStateForDragDropMixin:function(){return{draggedItem:u.getDraggedItem(),draggedItemType:u.getDraggedItemType()}},getDragState:function(t){return r(this,t),i(this,t),{isDragging:this.state.ownDraggedItemType===t}},getDropState:function(t){r(this,t),o(this,t);var e=this.getActiveDropTargetType()===t,n=!!this.state.currentDropEffect;return{isDragging:e,isHovering:e&&n}},componentWillMount:function(){this._monitor=new g,this._dragSources={},this._dropTargets={},this.configureDragDrop?(D(this.constructor._legacyConfigureDragDrop,'%s declares configureDragDrop as an instance method, which is deprecated and will be removed in next version. Move configureDragDrop to statics and change all methods inside it to accept component as first parameter instead of using "this".',this.constructor.displayName),this.constructor._legacyConfigureDragDrop=!0,this.configureDragDrop(this.registerDragDropItemTypeHandlers)):this.constructor.configureDragDrop?this.constructor.configureDragDrop(this.registerDragDropItemTypeHandlers,f):m(this.constructor.configureDragDrop,"%s must implement static configureDragDrop(register, context) to use DragDropMixin",this.constructor.displayName)},componentDidMount:function(){e(this),u.addChangeListener(this.handleStoreChangeInDragDropMixin)},componentWillUnmount:function(){n(this),u.removeChangeListener(this.handleStoreChangeInDragDropMixin)},registerDragDropItemTypeHandlers:function(t,e){r(this,t);var n=e.dragSource,i=e.dropTarget;n&&(m(!this._dragSources[t],"Drag source for %s specified twice. See configureDragDrop in %s",t,this.constructor.displayName),this._dragSources[t]=x(n,p)),i&&(m(!this._dropTargets[t],"Drop target for %s specified twice. See configureDragDrop in %s",t,this.constructor.displayName),this._dropTargets[t]=x(i,this.constructor._legacyConfigureDragDrop?d:l))},handleStoreChangeInDragDropMixin:function(){this.isMounted()&&this.setState(this.getStateForDragDropMixin())},dragSourceFor:function(e){return r(this,e),i(this,e),t.getDragSourceProps(this,e)},handleDragStart:function(e,n){var r=this,i=this._dragSources[e],o=i.canDrag,a=i.beginDrag;if(!s(o,this,n))return void n.preventDefault();var f,g=s(a,this,n),p=g.item,l=g.dragPreview,d=g.dragAnchors,v=g.effectsAllowed,D=this.getDOMNode(),y=D.getBoundingClientRect(),x=t.getOffsetFromClient(this,n);f={x:x.x-y.left,y:x.y-y.top},v||(v=[h.MOVE]),m(_(v)&&v.length>0,"Expected effectsAllowed to be non-empty array"),m(w(p),'Expected return value of beginDrag to contain "item" object'),t.beginDrag(this,n,D,l,d,f,v),c.startDragging(e,p,v,x,f),setTimeout(function(){r.isMounted()&&u.getDraggedItem()===p&&r.setState({ownDraggedItemType:e})})},handleDragEnd:function(e,n){t.endDrag(this);var r=this._dragSources[e].endDrag,i=u.getDropEffect();c.endDragging(),this.isMounted()&&this.setState({ownDraggedItemType:null}),s(r,this,i,n)},dropTargetFor:function(){for(var e=this,n=arguments.length,i=Array(n),s=0;n>s;s++)i[s]=arguments[s];return i.forEach(function(t){r(e,t),o(e,t)}),t.getDropTargetProps(this,i)},handleDragEnter:function(t,e){if(this.isAnyDropTargetActive(t)&&this._monitor.enter(e.target)){var n=this._dropTargets[this.state.draggedItemType],r=n.enter,i=n.getDropEffect,o=u.getEffectsAllowed();v(e)&&(o=[h.COPY]);var a=s(i,this,o);a&&m(o.indexOf(a)>-1,"Effect %s supplied by drop target is not one of the effects allowed by drag source: %s",a,o.join(", ")),this.setState({currentDropEffect:a}),s(r,this,this.state.draggedItem,e)}},handleDragOver:function(e,n){if(this.isAnyDropTargetActive(e)){n.preventDefault();{var r=this._dropTargets[this.state.draggedItemType],i=r.over;r.getDropEffect}s(i,this,this.state.draggedItem,n),t.dragOver(this,n,this.state.currentDropEffect||"move")}},handleDragLeave:function(t,e){if(this.isAnyDropTargetActive(t)&&this._monitor.leave(e.target)){this.setState({currentDropEffect:null});var n=this._dropTargets[this.state.draggedItemType].leave;s(n,this,this.state.draggedItem,e)}},handleDrop:function(t,e){if(this.isAnyDropTargetActive(t)){e.preventDefault();var n=this.state.draggedItem,r=this._dropTargets[this.state.draggedItemType].acceptDrop,i=this.state.currentDropEffect,o=!!u.getDropEffect();v(e)&&(n={files:Array.prototype.slice.call(e.dataTransfer.files)}),this._monitor.reset(),o||c.recordDrop(i),this.setState({currentDropEffect:null}),s(r,this,n,e,o,u.getDropEffect())}}}}{var c=n(18),u=n(12),f=n(35),g=n(22),h=n(9),p=n(33),l=n(34),d=n(36),v=n(24),m=n(17),D=n(76),y=n(16),x=n(68),_=n(5),w=n(2);n(6)}t.exports=a},function(t){"use strict";function e(t,e){return-1!==t.indexOf(e,t.length-e.length)}t.exports=e},function(t,e,n){"use strict";function r(t){var e=t.indexOf(i.COPY)>-1,n=t.indexOf(i.MOVE)>-1,r=t.indexOf(i.LINK)>-1;return e&&n&&r?"all":e&&n?"copyMove":r&&n?"linkMove":e&&r?"copyLink":e?"copy":n?"move":r?"link":"none"}var i=n(9);t.exports=r},function(t,e,n){"use strict";function r(t,e,n,r){n=n||{};var a=t.offsetWidth,c=t.offsetHeight,u=e instanceof Image,f=u?e.width:a,g=u?e.height:c,h=n.horizontal||i.CENTER,p=n.vertical||o.CENTER,l=r.x,d=r.y;switch(s()&&(g/=window.devicePixelRatio,f/=window.devicePixelRatio),h){case i.LEFT:break;case i.CENTER:l*=f/a;break;case i.RIGHT:l=f-f*(1-l/a)}switch(p){case o.TOP:break;case o.CENTER:d*=g/c;break;case o.BOTTOM:d=g-g*(1-d/c)}return s()&&(d+=(window.devicePixelRatio-1)*g),{x:l,y:d}}var i=n(19),o=n(21),s=n(13);t.exports=r},function(t,e,n){"use strict";function r(){return i()||o()?window.devicePixelRatio:1}var i=n(43),o=n(13);t.exports=r},function(t){"use strict";function e(){return/firefox/i.test(navigator.userAgent)}t.exports=e},function(t){"use strict";function e(){return"WebkitAppearance"in document.documentElement.style}t.exports=e},function(t,e,n){"use strict";function r(t){return t?i()&&t instanceof Image&&o(t.src,".gif")?!1:!0:!1}var i=n(13),o=n(39);t.exports=r},function(t,e,n){t.exports.Dispatcher=n(47)},function(t,e,n){"use strict";function r(){this.$Dispatcher_callbacks={},this.$Dispatcher_isPending={},this.$Dispatcher_isHandled={},this.$Dispatcher_isDispatching=!1,this.$Dispatcher_pendingPayload=null}var i=n(48),o=1,s="ID_";r.prototype.register=function(t){var e=s+o++;return this.$Dispatcher_callbacks[e]=t,e},r.prototype.unregister=function(t){i(this.$Dispatcher_callbacks[t],"Dispatcher.unregister(...): `%s` does not map to a registered callback.",t),delete this.$Dispatcher_callbacks[t]},r.prototype.waitFor=function(t){i(this.$Dispatcher_isDispatching,"Dispatcher.waitFor(...): Must be invoked while dispatching.");for(var e=0;e<t.length;e++){var n=t[e];this.$Dispatcher_isPending[n]?i(this.$Dispatcher_isHandled[n],"Dispatcher.waitFor(...): Circular dependency detected while waiting for `%s`.",n):(i(this.$Dispatcher_callbacks[n],"Dispatcher.waitFor(...): `%s` does not map to a registered callback.",n),this.$Dispatcher_invokeCallback(n))}},r.prototype.dispatch=function(t){i(!this.$Dispatcher_isDispatching,"Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch."),this.$Dispatcher_startDispatching(t);try{for(var e in this.$Dispatcher_callbacks)this.$Dispatcher_isPending[e]||this.$Dispatcher_invokeCallback(e)}finally{this.$Dispatcher_stopDispatching()}},r.prototype.isDispatching=function(){return this.$Dispatcher_isDispatching},r.prototype.$Dispatcher_invokeCallback=function(t){this.$Dispatcher_isPending[t]=!0,this.$Dispatcher_callbacks[t](this.$Dispatcher_pendingPayload),this.$Dispatcher_isHandled[t]=!0},r.prototype.$Dispatcher_startDispatching=function(t){for(var e in this.$Dispatcher_callbacks)this.$Dispatcher_isPending[e]=!1,this.$Dispatcher_isHandled[e]=!1;this.$Dispatcher_pendingPayload=t,this.$Dispatcher_isDispatching=!0},r.prototype.$Dispatcher_stopDispatching=function(){this.$Dispatcher_pendingPayload=null,this.$Dispatcher_isDispatching=!1},t.exports=r},function(t){"use strict";var e=function(t,e,n,r,i,o,s,a){if(!t){var c;if(void 0===e)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,i,o,s,a],f=0;c=new Error("Invariant Violation: "+e.replace(/%s/g,function(){return u[f++]}))}throw c.framesToPop=1,c}};t.exports=e},function(t,e,n){function r(){return o(i(arguments,!1,!0))}var i=n(57),o=n(60);t.exports=r},function(t,e,n){function r(t){return i(t,o(arguments,1))}var i=n(56),o=n(58);t.exports=r},function(t,e,n){(function(e){function r(t){var e=t?t.length:0;for(this.data={hash:a(null),set:new s};e--;)this.push(t[e])}var i=n(62),o=n(3),s=o(s=e.Set)&&s,a=o(a=Object.create)&&a;r.prototype.push=i,t.exports=r}).call(e,function(){return this}())},function(t){function e(t,e){var n=-1,r=t.length;for(e||(e=Array(r));++n<r;)e[n]=t[n];return e}t.exports=e},function(t){function e(t,e){return"undefined"==typeof t?e:t}t.exports=e},function(t,e,n){function r(t,e,n){var r=o(e);if(!n)return i(e,t,r);for(var s=-1,a=r.length;++s<a;){var c=r[s],u=t[c],f=n(u,e[c],c,t,e);(f===f?f===u:u!==u)&&("undefined"!=typeof u||c in t)||(t[c]=f)}return t}var i=n(55),o=n(69);t.exports=r},function(t){function e(t,e,n){n||(n=e,e={});for(var r=-1,i=n.length;++r<i;){var o=n[r];e[o]=t[o]}return e}t.exports=e},function(t,e,n){function r(t,e){var n=t?t.length:0,r=[];if(!n)return r;var a=-1,c=i,u=!0,f=u&&e.length>=200&&s(e),g=e.length;f&&(c=o,u=!1,e=f);t:for(;++a<n;){var h=t[a];if(u&&h===h){for(var p=g;p--;)if(e[p]===h)continue t;r.push(h)}else c(e,h)<0&&r.push(h)}return r}var i=n(25),o=n(26),s=n(27);t.exports=r},function(t,e,n){function r(t,e,n,c){for(var u=(c||0)-1,f=t.length,g=-1,h=[];++u<f;){var p=t[u];if(a(p)&&s(p.length)&&(o(p)||i(p))){e&&(p=r(p,e,n));var l=-1,d=p.length;for(h.length+=d;++l<d;)h[++g]=p[l]}else n||(h[++g]=p)}return h}var i=n(15),o=n(5),s=n(1),a=n(4);t.exports=r},function(t){function e(t,e,n){var r=-1,i=t.length;e=null==e?0:+e||0,0>e&&(e=-e>i?0:i+e),n="undefined"==typeof n||n>i?i:+n||0,0>n&&(n+=i),i=e>n?0:n-e>>>0,e>>>=0;for(var o=Array(i);++r<i;)o[r]=t[r+e];return o}t.exports=e},function(t){function e(t){return"string"==typeof t?t:null==t?"":t+""}t.exports=e},function(t,e,n){function r(t,e){var n=-1,r=i,a=t.length,c=!0,u=c&&a>=200,f=u&&s(),g=[];f?(r=o,c=!1):(u=!1,f=e?[]:g);t:for(;++n<a;){var h=t[n],p=e?e(h,n,t):h;if(c&&h===h){for(var l=f.length;l--;)if(f[l]===p)continue t;e&&f.push(p),g.push(h)}else r(f,p)<0&&((e||u)&&f.push(p),g.push(h))}return g}var i=n(25),o=n(26),s=n(27);t.exports=r},function(t,e,n){function r(t,e,n){if("function"!=typeof t)return i;if("undefined"==typeof e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 3:return function(n,r,i){return t.call(e,n,r,i)};case 4:return function(n,r,i,o){return t.call(e,n,r,i,o)};case 5:return function(n,r,i,o,s){return t.call(e,n,r,i,o,s)}}return function(){return t.apply(e,arguments)}}var i=n(73);t.exports=r},function(t,e,n){function r(t){var e=this.data;"string"==typeof t||i(t)?e.set.add(t):e.hash[t]=!0}var i=n(2);t.exports=r},function(t,e,n){function r(t){return function(){var e=arguments.length,n=arguments[0];if(2>e||null==n)return n;if(e>3&&o(arguments[1],arguments[2],arguments[3])&&(e=2),e>3&&"function"==typeof arguments[e-2])var r=i(arguments[--e-1],arguments[e--],5);else e>2&&"function"==typeof arguments[e-1]&&(r=arguments[--e]);for(var s=0;++s<e;){var a=arguments[s];a&&t(n,a,r)}return n}}var i=n(61),o=n(65);t.exports=r},function(t){function e(t,e,n){for(var r=t.length,i=n?e||r:(e||0)-1;n?i--:++i<r;){var o=t[i];if(o!==o)return i}return-1}t.exports=e},function(t,e,n){function r(t,e,n){if(!s(n))return!1;var r=typeof e;if("number"==r)var a=n.length,c=o(a)&&i(e,a);else c="string"==r&&e in n;return c&&n[e]===t}var i=n(14),o=n(1),s=n(2);t.exports=r},function(t,e,n){function r(t){for(var e=c(t),n=e.length,r=n&&t.length,f=r&&a(r)&&(o(t)||u.nonEnumArgs&&i(t)),h=-1,p=[];++h<n;){var l=e[h];(f&&s(l,r)||g.call(t,l))&&p.push(l)}return p}var i=n(15),o=n(5),s=n(14),a=n(1),c=n(70),u=n(28),f=Object.prototype,g=f.hasOwnProperty;t.exports=r},function(t,e,n){var r=n(54),i=n(63),o=i(r);t.exports=o},function(t,e,n){function r(t){if(null==t)return t;var e=i(arguments);return e.push(s),o.apply(void 0,e)}var i=n(52),o=n(67),s=n(53);t.exports=r},function(t,e,n){var r=n(1),i=n(3),o=n(2),s=n(66),a=i(a=Object.keys)&&a,c=a?function(t){if(t)var e=t.constructor,n=t.length;return"function"==typeof e&&e.prototype===t||"function"!=typeof t&&n&&r(n)?s(t):o(t)?a(t):[]}:s;t.exports=c},function(t,e,n){function r(t){if(null==t)return[];c(t)||(t=Object(t));var e=t.length;e=e&&a(e)&&(o(t)||u.nonEnumArgs&&i(t))&&e||0;for(var n=t.constructor,r=-1,f="function"==typeof n&&n.prototype===t,h=Array(e),p=e>0;++r<e;)h[r]=r+"";for(var l in t)p&&s(l,e)||"constructor"==l&&(f||!g.call(t,l))||h.push(l);return h}var i=n(15),o=n(5),s=n(14),a=n(1),c=n(2),u=n(28),f=Object.prototype,g=f.hasOwnProperty;t.exports=r},function(t,e,n){function r(t){return t=i(t),t&&s.test(t)?t.replace(o,"\\$&"):t}var i=n(59),o=/[.*+?^${}()|[\]\/\\]/g,s=RegExp(o.source);t.exports=r},function(t){function e(t){return function(){return t}}t.exports=e},function(t){function e(t){return t}t.exports=e},function(t){function e(t){return function(){return t}}function n(){}n.thatReturns=e,n.thatReturnsFalse=e(!1),n.thatReturnsTrue=e(!0),n.thatReturnsNull=e(null),n.thatReturnsThis=function(){return this},n.thatReturnsArgument=function(t){return t},t.exports=n},function(t){"use strict";function e(t,e){if(t===e)return!0;var n;for(n in t)if(t.hasOwnProperty(n)&&(!e.hasOwnProperty(n)||t[n]!==e[n]))return!1;for(n in e)if(e.hasOwnProperty(n)&&!t.hasOwnProperty(n))return!1;return!0}t.exports=e},function(t,e,n){"use strict";var r=n(74),i=r;t.exports=i},function(t){function e(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function n(t){return"function"==typeof t}function r(t){return"number"==typeof t}function i(t){return"object"==typeof t&&null!==t}function o(t){return void 0===t}t.exports=e,e.EventEmitter=e,e.prototype._events=void 0,e.prototype._maxListeners=void 0,e.defaultMaxListeners=10,e.prototype.setMaxListeners=function(t){if(!r(t)||0>t||isNaN(t))throw TypeError("n must be a positive number");return this._maxListeners=t,this},e.prototype.emit=function(t){var e,r,s,a,c,u;if(this._events||(this._events={}),"error"===t&&(!this._events.error||i(this._events.error)&&!this._events.error.length)){if(e=arguments[1],e instanceof Error)throw e;throw TypeError('Uncaught, unspecified "error" event.')}if(r=this._events[t],o(r))return!1;if(n(r))switch(arguments.length){case 1:r.call(this);break;case 2:r.call(this,arguments[1]);break;case 3:r.call(this,arguments[1],arguments[2]);break;default:for(s=arguments.length,a=new Array(s-1),c=1;s>c;c++)a[c-1]=arguments[c];r.apply(this,a)}else if(i(r)){for(s=arguments.length,a=new Array(s-1),c=1;s>c;c++)a[c-1]=arguments[c];for(u=r.slice(),s=u.length,c=0;s>c;c++)u[c].apply(this,a)}return!0},e.prototype.addListener=function(t,r){var s;if(!n(r))throw TypeError("listener must be a function");if(this._events||(this._events={}),this._events.newListener&&this.emit("newListener",t,n(r.listener)?r.listener:r),this._events[t]?i(this._events[t])?this._events[t].push(r):this._events[t]=[this._events[t],r]:this._events[t]=r,i(this._events[t])&&!this._events[t].warned){var s;s=o(this._maxListeners)?e.defaultMaxListeners:this._maxListeners,s&&s>0&&this._events[t].length>s&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),"function"==typeof console.trace&&console.trace())}return this},e.prototype.on=e.prototype.addListener,e.prototype.once=function(t,e){function r(){this.removeListener(t,r),i||(i=!0,e.apply(this,arguments))}if(!n(e))throw TypeError("listener must be a function");var i=!1;return r.listener=e,this.on(t,r),this},e.prototype.removeListener=function(t,e){var r,o,s,a;if(!n(e))throw TypeError("listener must be a function");if(!this._events||!this._events[t])return this;if(r=this._events[t],s=r.length,o=-1,r===e||n(r.listener)&&r.listener===e)delete this._events[t],this._events.removeListener&&this.emit("removeListener",t,e);else if(i(r)){for(a=s;a-->0;)if(r[a]===e||r[a].listener&&r[a].listener===e){o=a;break}if(0>o)return this;1===r.length?(r.length=0,delete this._events[t]):r.splice(o,1),this._events.removeListener&&this.emit("removeListener",t,e)}return this},e.prototype.removeAllListeners=function(t){var e,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[t]&&delete this._events[t],this;if(0===arguments.length){for(e in this._events)"removeListener"!==e&&this.removeAllListeners(e);return this.removeAllListeners("removeListener"),this._events={},this}if(r=this._events[t],n(r))this.removeListener(t,r);else for(;r.length;)this.removeListener(t,r[r.length-1]);return delete this._events[t],this},e.prototype.listeners=function(t){var e;return e=this._events&&this._events[t]?n(this._events[t])?[this._events[t]]:this._events[t].slice():[]},e.listenerCount=function(t,e){var r;return r=t._events&&t._events[e]?n(t._events[e])?1:t._events[e].length:0}}])}); |
'use strict'; | ||
var React = require('react'), | ||
ItemTypes = require('./ItemTypes'), | ||
getEmptyImage = require('./getEmptyImage'), | ||
{ PropTypes } = React, | ||
{ DragDropMixin, DropEffects } = require('react-dnd'); | ||
{ PropTypes } = React; | ||
var styles = { | ||
box: { | ||
border: '1px dashed gray', | ||
padding: '0.5rem', | ||
display: 'inline-block' | ||
} | ||
}; | ||
var Box = React.createClass({ | ||
mixins: [DragDropMixin], | ||
propTypes: { | ||
id: PropTypes.any.isRequired, | ||
left: PropTypes.number.isRequired, | ||
top: PropTypes.number.isRequired | ||
title: PropTypes.string.isRequired | ||
}, | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.BOX, { | ||
dragSource: { | ||
beginDrag(component, e) { | ||
return { | ||
effectAllowed: DropEffects.MOVE, | ||
dragPreview: getEmptyImage(), | ||
item: { | ||
id: component.props.id, | ||
startLeft: component.props.left, | ||
startTop: component.props.top, | ||
startPageX: e.pageX, | ||
startPageY: e.pageY | ||
} | ||
}; | ||
} | ||
} | ||
}); | ||
} | ||
}, | ||
render() { | ||
var { isDragging } = this.getDragState(ItemTypes.BOX), | ||
transform = `translate3d(${this.props.left}px, ${this.props.top}px, 0)`; | ||
return ( | ||
<div {...this.dragSourceFor(ItemTypes.BOX)} | ||
style={{ | ||
WebkitTransform: transform, | ||
transform: transform, | ||
opacity: isDragging ? 0.8 : 1, | ||
position: 'absolute', | ||
top: 0, | ||
left: 0, | ||
border: '1px dashed gray', | ||
padding: '0.5rem' | ||
}}> | ||
{this.props.children} | ||
<div style={styles.box}> | ||
{this.props.title} | ||
</div> | ||
@@ -58,0 +24,0 @@ ); |
@@ -6,6 +6,16 @@ 'use strict'; | ||
ItemTypes = require('./ItemTypes'), | ||
Box = require('./Box'), | ||
DraggableBox = require('./DraggableBox'), | ||
snapToGrid = require('./snapToGrid'), | ||
{ PropTypes } = React, | ||
{ DragDropMixin } = require('react-dnd'); | ||
{ DragDropMixin, DragLayerMixin } = require('react-dnd'); | ||
var styles = { | ||
container: { | ||
width: 300, | ||
height: 300, | ||
border: '1px solid black', | ||
position: 'relative' | ||
} | ||
}; | ||
var Container = React.createClass({ | ||
@@ -28,12 +38,12 @@ mixins: [DragDropMixin], | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.BOX, { | ||
configureDragDrop(register, context) { | ||
register(ItemTypes.BOX, { | ||
dropTarget: { | ||
over(component, item, e) { | ||
var left = Math.round(item.startLeft + (e.pageX - item.startPageX)), | ||
top = Math.round(item.startTop + (e.pageY - item.startPageY)); | ||
acceptDrop(component, item, e) { | ||
var delta = context.getCurrentOffsetDelta(), | ||
left = Math.round(item.left + delta.x), | ||
top = Math.round(item.top + delta.y); | ||
if (component.props.snapToGrid) { | ||
left = Math.round(left / 32) * 32; | ||
top = Math.round(top / 32) * 32; | ||
[left, top] = snapToGrid(left, top); | ||
} | ||
@@ -49,39 +59,32 @@ | ||
moveBox(id, left, top) { | ||
var stateUpdate = { | ||
boxes: {} | ||
}; | ||
stateUpdate.boxes[id] = { | ||
$merge: { | ||
left: left, | ||
top: top | ||
this.setState(update(this.state, { | ||
boxes: { | ||
[id]: { | ||
$merge: { | ||
left: left, | ||
top: top | ||
} | ||
} | ||
} | ||
}; | ||
})); | ||
}, | ||
this.setState(update(this.state, stateUpdate)); | ||
renderBox(item, key) { | ||
return ( | ||
<DraggableBox key={key} | ||
id={key} | ||
{...item} /> | ||
); | ||
}, | ||
render() { | ||
var { boxes } = this.state; | ||
return ( | ||
<div {...this.dropTargetFor(ItemTypes.BOX)} | ||
style={{ | ||
width: 300, | ||
height: 300, | ||
border: '1px solid black', | ||
position: 'relative' | ||
}}> | ||
{Object.keys(this.state.boxes).map(key => { | ||
var box = this.state.boxes[key]; | ||
return ( | ||
<Box key={key} | ||
id={key} | ||
left={box.left} | ||
top={box.top}> | ||
{box.title} | ||
</Box> | ||
); | ||
})} | ||
<div style={styles.container} | ||
{...this.dropTargetFor(ItemTypes.BOX)}> | ||
{Object | ||
.keys(boxes) | ||
.map(key => this.renderBox(boxes[key], key)) | ||
} | ||
</div> | ||
@@ -88,0 +91,0 @@ ); |
@@ -5,2 +5,3 @@ 'use strict'; | ||
Container = require('./Container'), | ||
DragLayer = require('./DragLayer'), | ||
LinkedStateMixin = require('react/lib/LinkedStateMixin'); | ||
@@ -13,3 +14,4 @@ | ||
return { | ||
snapToGrid: false | ||
snapToGridAfterDrop: false, | ||
snapToGridWhileDragging: false | ||
}; | ||
@@ -21,8 +23,14 @@ }, | ||
<div> | ||
<Container snapToGrid={this.state.snapToGrid} /> | ||
<Container snapToGrid={this.state.snapToGridAfterDrop} /> | ||
<DragLayer snapToGrid={this.state.snapToGridWhileDragging} /> | ||
<p> | ||
<input type='checkbox' | ||
checkedLink={this.linkState('snapToGrid')}> | ||
Snap to grid | ||
checkedLink={this.linkState('snapToGridAfterDrop')}> | ||
Snap to grid after drop | ||
</input> | ||
<br /> | ||
<input type='checkbox' | ||
checkedLink={this.linkState('snapToGridWhileDragging')}> | ||
Snap to grid while dragging | ||
</input> | ||
</p> | ||
@@ -36,6 +44,9 @@ <hr /> | ||
<p> | ||
We can, however, customize behavior a great deal if we feed the browser an empty image as drag preview, | ||
and move the dragged DOM element itself continuously in response to dragover event. | ||
We can, however, customize behavior a great deal if we feed the browser an empty image as drag preview. | ||
This library provides <code>DragLayerMixin</code> that you can use to implement a fixed layer on top of your app where you'd draw a custom drag preview component. | ||
</p> | ||
<p> | ||
Note that we can draw a completely different component on our drag layer if we wish so. It's not just a screenshot. | ||
</p> | ||
<p> | ||
With this approach, we miss out on default “return” animation when dropping outside the container. | ||
@@ -42,0 +53,0 @@ However, we get great flexibility in customizing drag feedback and zero flicker. |
@@ -19,15 +19,9 @@ 'use strict'; | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.BOX, { | ||
configureDragDrop(register) { | ||
register(ItemTypes.BOX, { | ||
dragSource: { | ||
beginDrag(component, e) { | ||
beginDrag(component) { | ||
return { | ||
effectAllowed: DropEffects.MOVE, | ||
item: { | ||
id: component.props.id, | ||
startLeft: component.props.left, | ||
startTop: component.props.top, | ||
startPageX: e.pageX, | ||
startPageY: e.pageY | ||
} | ||
item: component.props | ||
}; | ||
@@ -34,0 +28,0 @@ } |
@@ -27,8 +27,9 @@ 'use strict'; | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.BOX, { | ||
configureDragDrop(register, context) { | ||
register(ItemTypes.BOX, { | ||
dropTarget: { | ||
acceptDrop(component, item, e) { | ||
var left = Math.round(item.startLeft + (e.pageX - item.startPageX)), | ||
top = Math.round(item.startTop + (e.pageY - item.startPageY)); | ||
acceptDrop(component, item) { | ||
var delta = context.getCurrentOffsetDelta(), | ||
left = Math.round(item.left + delta.x), | ||
top = Math.round(item.top + delta.y); | ||
@@ -35,0 +36,0 @@ component.moveBox(item.id, left, top); |
'use strict'; | ||
var React = require('react'), | ||
makeDustbin = require('./Dustbin'), | ||
makeItem = require('./Item'), | ||
makeDustbin = require('./makeDustbin'), | ||
makeItem = require('./makeItem'), | ||
ItemTypes = require('./ItemTypes'), | ||
@@ -12,3 +12,3 @@ { NativeDragItemTypes } = require('react-dnd'); | ||
var Dustbin = makeDustbin(accepts); | ||
return <Dustbin/>; | ||
return <Dustbin />; | ||
}, | ||
@@ -18,3 +18,3 @@ | ||
var Item = makeItem(dropType); | ||
return <Item name={name}/>; | ||
return <Item name={name} />; | ||
}, | ||
@@ -21,0 +21,0 @@ |
@@ -11,4 +11,4 @@ 'use strict'; | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.ITEM, { | ||
configureDragDrop(register) { | ||
register(ItemTypes.ITEM, { | ||
dropTarget: { | ||
@@ -15,0 +15,0 @@ acceptDrop(component, item) { |
@@ -16,4 +16,4 @@ 'use strict'; | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.ITEM, { | ||
configureDragDrop(register) { | ||
register(ItemTypes.ITEM, { | ||
dragSource: { | ||
@@ -20,0 +20,0 @@ beginDrag(component) { |
@@ -18,4 +18,4 @@ 'use strict'; | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.CARD, { | ||
configureDragDrop(register) { | ||
register(ItemTypes.CARD, { | ||
dragSource: { | ||
@@ -22,0 +22,0 @@ beginDrag(component) { |
@@ -20,3 +20,3 @@ 'use strict'; | ||
<li>Drag Around (<Link to='drag-around-naive'>naive</Link>, <Link to='drag-around-custom'>custom</Link>)</li> | ||
<li>Sortable (<Link to='sortable-simple'>simple</Link>, more coming...)</li> | ||
<li>Sortable (<Link to='sortable-simple'>simple</Link>)</li> | ||
</ul> | ||
@@ -37,3 +37,2 @@ <hr /> | ||
<Route name='sortable-simple' path='sortable-simple' handler={SortableSimple} /> | ||
<Redirect from='/' to='dustbin-simple' /> | ||
@@ -40,0 +39,0 @@ </Route> |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var DragDropActionCreators = { | ||
startDragging(itemType, item, effectsAllowed) { | ||
startDragging(itemType, item, effectsAllowed, offsetFromClient, offsetFromContainer) { | ||
DragDropDispatcher.handleAction({ | ||
@@ -13,6 +13,15 @@ type: DragDropActionTypes.DRAG_START, | ||
item: item, | ||
effectsAllowed: effectsAllowed | ||
effectsAllowed: effectsAllowed, | ||
offsetFromClient: offsetFromClient, | ||
offsetFromContainer: offsetFromContainer | ||
}); | ||
}, | ||
drag(offsetFromClient) { | ||
DragDropDispatcher.handleAction({ | ||
type: DragDropActionTypes.DRAG, | ||
offsetFromClient: offsetFromClient | ||
}); | ||
}, | ||
recordDrop(dropEffect) { | ||
@@ -19,0 +28,0 @@ DragDropDispatcher.handleAction({ |
'use strict'; | ||
var DragDropActionCreators = require('../actions/DragDropActionCreators'), | ||
DragOperationStore = require('../stores/DragOperationStore'), | ||
NativeDragItemTypes = require('../constants/NativeDragItemTypes'), | ||
DropEffects = require('../constants/DropEffects'), | ||
EnterLeaveMonitor = require('../utils/EnterLeaveMonitor'), | ||
isFileDragDropEvent = require('../utils/isFileDragDropEvent'), | ||
configureDataTransfer = require('../utils/configureDataTransfer'), | ||
shallowEqual = require('react/lib/shallowEqual'), | ||
union = require('lodash/array/union'), | ||
without = require('lodash/array/without'), | ||
isWebkit = require('../utils/isWebkit'), | ||
isFirefox = require('../utils/isFirefox'); | ||
isWebkit = require('../utils/isWebkit'); | ||
@@ -17,4 +15,4 @@ // Store global state for browser-specific fixes and workarounds | ||
_currentDragTarget, | ||
_currentComponent, | ||
_initialDragTargetRect, | ||
_imitateCurrentDragEnd, | ||
_dragTargetRectDidChange, | ||
@@ -39,8 +37,8 @@ _currentDropEffect; | ||
function triggerDragEndIfDragSourceWasRemovedFromDOM() { | ||
if (_currentDragTarget && | ||
_imitateCurrentDragEnd && | ||
!document.body.contains(_currentDragTarget)) { | ||
if (!_currentComponent || document.body.contains(_currentDragTarget)) { | ||
return; | ||
} | ||
_imitateCurrentDragEnd(); | ||
} | ||
var type = DragOperationStore.getDraggedItemType(); | ||
_currentComponent.handleDragEnd(type, null); | ||
} | ||
@@ -54,3 +52,3 @@ | ||
function handleDragEnter(e) { | ||
function handleTopDragEnter(e) { | ||
preventDefaultFileDropAction(e); | ||
@@ -64,5 +62,8 @@ | ||
function handleDragOver(e) { | ||
function handleTopDragOver(e) { | ||
preventDefaultFileDropAction(e); | ||
var offsetFromClient = HTML5.getOffsetFromClient(_currentComponent, e); | ||
DragDropActionCreators.drag(offsetFromClient); | ||
// At the top level of event bubbling, use previously set drop effect and reset it. | ||
@@ -74,7 +75,3 @@ if (_currentDropEffect) { | ||
if (!_currentDragTarget) { | ||
return; | ||
} | ||
if (isWebkit() && checkIfCurrentDragTargetRectChanged()) { | ||
if (_currentDragTarget && isWebkit() && checkIfCurrentDragTargetRectChanged()) { | ||
// Prevent animating to incorrect position | ||
@@ -85,3 +82,3 @@ e.preventDefault(); | ||
function handleDragLeave(e) { | ||
function handleTopDragLeave(e) { | ||
preventDefaultFileDropAction(e); | ||
@@ -95,3 +92,3 @@ | ||
function handleDrop(e) { | ||
function handleTopDrop(e) { | ||
preventDefaultFileDropAction(e); | ||
@@ -109,25 +106,32 @@ | ||
var HTML5 = { | ||
setup() { | ||
if (typeof window !== 'undefined') { | ||
window.addEventListener('dragenter', handleDragEnter); | ||
window.addEventListener('dragover', handleDragOver); | ||
window.addEventListener('dragleave', handleDragLeave); | ||
window.addEventListener('drop', handleDrop); | ||
setup(component) { | ||
if (typeof window === 'undefined') { | ||
return; | ||
} | ||
window.addEventListener('dragenter', handleTopDragEnter); | ||
window.addEventListener('dragover', handleTopDragOver); | ||
window.addEventListener('dragleave', handleTopDragLeave); | ||
window.addEventListener('drop', handleTopDrop); | ||
}, | ||
teardown() { | ||
if (typeof window !== 'undefined') { | ||
window.removeEventListener('dragenter', handleDragEnter); | ||
window.removeEventListener('dragover', handleDragOver); | ||
window.removeEventListener('dragleave', handleDragLeave); | ||
window.removeEventListener('drop', handleDrop); | ||
teardown(component) { | ||
if (typeof window === 'undefined') { | ||
return; | ||
} | ||
window.removeEventListener('dragenter', handleTopDragEnter); | ||
window.removeEventListener('dragover', handleTopDragOver); | ||
window.removeEventListener('dragleave', handleTopDragLeave); | ||
window.removeEventListener('drop', handleTopDrop); | ||
}, | ||
beginDrag(dragTarget, imitateDragEnd) { | ||
_currentDragTarget = dragTarget; | ||
_initialDragTargetRect = getElementRect(dragTarget); | ||
beginDrag(component, e, containerNode, dragPreview, dragAnchors, offsetFromContainer, effectsAllowed) { | ||
var { nativeEvent: { dataTransfer, target } } = e; | ||
configureDataTransfer(dataTransfer, containerNode, dragPreview, dragAnchors, offsetFromContainer, effectsAllowed); | ||
_currentComponent = component; | ||
_currentDragTarget = target; | ||
_initialDragTargetRect = getElementRect(target); | ||
_dragTargetRectDidChange = false; | ||
_imitateCurrentDragEnd = imitateDragEnd; | ||
@@ -141,7 +145,7 @@ // Mouse event tell us that dragging has ended but `dragend` didn't fire. | ||
endDrag() { | ||
endDrag(component) { | ||
_currentDragTarget = null; | ||
_currentComponent = null; | ||
_initialDragTargetRect = null; | ||
_dragTargetRectDidChange = false; | ||
_imitateCurrentDragEnd = null; | ||
@@ -152,3 +156,3 @@ window.removeEventListener('mousemove', triggerDragEndIfDragSourceWasRemovedFromDOM); | ||
dragOver(e, dropEffect) { | ||
dragOver(component, e, dropEffect) { | ||
// As event bubbles top-down, first specified effect will be used | ||
@@ -158,2 +162,26 @@ if (!_currentDropEffect) { | ||
} | ||
}, | ||
getDragSourceProps(component, type) { | ||
return { | ||
draggable: true, | ||
onDragStart: component.handleDragStart.bind(component, type), | ||
onDragEnd: component.handleDragEnd.bind(component, type) | ||
}; | ||
}, | ||
getDropTargetProps(component, types) { | ||
return { | ||
onDragEnter: component.handleDragEnter.bind(component, types), | ||
onDragOver: component.handleDragOver.bind(component, types), | ||
onDragLeave: component.handleDragLeave.bind(component, types), | ||
onDrop: component.handleDrop.bind(component, types) | ||
}; | ||
}, | ||
getOffsetFromClient(component, e) { | ||
return { | ||
x: e.clientX, | ||
y: e.clientY | ||
}; | ||
} | ||
@@ -160,0 +188,0 @@ }; |
@@ -8,2 +8,3 @@ 'use strict'; | ||
DRAG_END: null, | ||
DRAG: null, | ||
DROP: null | ||
@@ -10,0 +11,0 @@ }); |
'use strict'; | ||
var { HTML5 } = require('./backends'), | ||
createDragDropMixin = require('./utils/createDragDropMixin'); | ||
module.exports = { | ||
DragDropMixin: require('./mixins/DragDropMixin'), | ||
DragDropMixin: createDragDropMixin(HTML5), | ||
ImagePreloaderMixin: require('./mixins/ImagePreloaderMixin'), | ||
DragLayerMixin: require('./mixins/DragLayerMixin'), | ||
HorizontalDragAnchors: require('./constants/HorizontalDragAnchors'), | ||
@@ -10,2 +14,2 @@ VerticalDragAnchors: require('./constants/VerticalDragAnchors'), | ||
DropEffects: require('./constants/DropEffects') | ||
}; | ||
}; |
@@ -7,5 +7,3 @@ 'use strict'; | ||
function configureDataTransfer(containerNode, nativeEvent, dragPreview, dragAnchors, effectsAllowed) { | ||
var { dataTransfer } = nativeEvent; | ||
function configureDataTransfer(dataTransfer, containerNode, dragPreview, dragAnchors, offsetFromContainer, effectsAllowed) { | ||
try { | ||
@@ -19,3 +17,3 @@ // Firefox won't drag without setting data | ||
if (shouldUseDragPreview(dragPreview) && dataTransfer.setDragImage) { | ||
var dragOffset = getDragImageOffset(containerNode, dragPreview, dragAnchors, nativeEvent); | ||
var dragOffset = getDragImageOffset(containerNode, dragPreview, dragAnchors, offsetFromContainer); | ||
dataTransfer.setDragImage(dragPreview, dragOffset.x, dragOffset.y); | ||
@@ -22,0 +20,0 @@ } |
@@ -5,4 +5,2 @@ 'use strict'; | ||
assign = require('react/lib/Object.assign'), | ||
shallowEqual = require('react/lib/shallowEqual'), | ||
bindAll = require('./bindAll'), | ||
CHANGE_EVENT = 'change'; | ||
@@ -26,3 +24,2 @@ | ||
store.setMaxListeners(0); | ||
bindAll(store); | ||
@@ -29,0 +26,0 @@ return store; |
@@ -5,3 +5,2 @@ 'use strict'; | ||
VerticalDragAnchors = require('../constants/VerticalDragAnchors'), | ||
isFirefox = require('./isFirefox'), | ||
isSafari = require('./isSafari'); | ||
@@ -13,3 +12,3 @@ | ||
*/ | ||
function getDragImageOffset(containerNode, dragPreview, dragAnchors, e) { | ||
function getDragImageOffset(containerNode, dragPreview, dragAnchors, offsetFromContainer) { | ||
dragAnchors = dragAnchors || {}; | ||
@@ -24,9 +23,6 @@ | ||
verticalAnchor = dragAnchors.vertical || VerticalDragAnchors.CENTER, | ||
{ offsetX, offsetY, target: node } = e; | ||
{ x, y } = offsetFromContainer; | ||
// Work around @2x coordinate discrepancies in browsers | ||
if (isFirefox()) { | ||
offsetX = e.layerX; | ||
offsetY = e.layerY; | ||
} else if (isSafari()) { | ||
if (isSafari()) { | ||
previewHeight /= window.devicePixelRatio; | ||
@@ -36,8 +32,2 @@ previewWidth /= window.devicePixelRatio; | ||
while (node !== containerNode && containerNode.contains(node)) { | ||
offsetX += node.offsetLeft; | ||
offsetY += node.offsetTop; | ||
node = node.offsetParent; | ||
} | ||
switch (horizontalAnchor) { | ||
@@ -47,6 +37,6 @@ case HorizontalDragAnchors.LEFT: | ||
case HorizontalDragAnchors.CENTER: | ||
offsetX *= (previewWidth / containerWidth); | ||
x *= (previewWidth / containerWidth); | ||
break; | ||
case HorizontalDragAnchors.RIGHT: | ||
offsetX = previewWidth - previewWidth * (1 - offsetX / containerWidth); | ||
x = previewWidth - previewWidth * (1 - x / containerWidth); | ||
break; | ||
@@ -59,6 +49,6 @@ } | ||
case VerticalDragAnchors.CENTER: | ||
offsetY *= (previewHeight / containerHeight); | ||
y *= (previewHeight / containerHeight); | ||
break; | ||
case VerticalDragAnchors.BOTTOM: | ||
offsetY = previewHeight - previewHeight * (1 - offsetY / containerHeight); | ||
y = previewHeight - previewHeight * (1 - y / containerHeight); | ||
break; | ||
@@ -70,8 +60,8 @@ } | ||
// We'll have to wait for @3x to see if this is entirely correct | ||
offsetY += (window.devicePixelRatio - 1) * previewHeight; | ||
y += (window.devicePixelRatio - 1) * previewHeight; | ||
} | ||
return { | ||
x: offsetX, | ||
y: offsetY | ||
x: x, | ||
y: y | ||
}; | ||
@@ -78,0 +68,0 @@ } |
'use strict'; | ||
function isFileDragDropEvent(e) { | ||
if (!e.dataTransfer) { | ||
return false; | ||
} | ||
var types = Array.prototype.slice.call(e.dataTransfer.types); | ||
@@ -8,2 +12,2 @@ return types.indexOf('Files') !== -1; | ||
module.exports = isFileDragDropEvent; | ||
module.exports = isFileDragDropEvent; |
{ | ||
"name": "react-dnd", | ||
"version": "0.7.0", | ||
"description": "HTML5 drag and drop mixin for React with full DOM control", | ||
"version": "0.8.0", | ||
"description": "Drag and drop for React with full DOM control", | ||
"main": "dist-modules/index.js", | ||
@@ -6,0 +6,0 @@ "scripts": { |
446
README.md
@@ -6,426 +6,90 @@ react-dnd | ||
HTML5 drag-and-drop mixin for React with full DOM control. | ||
Drag and drop for React with full DOM control. | ||
Currently works on top of HTML5 drag-and-drop API, but moves towards a swappable implementation. | ||
## Prior Work | ||
## Philosophy | ||
Check these first and see if they fit your use case. | ||
* Keep user in full control over rendering; | ||
* Don't make assumptions about consuming components and their structure; | ||
* Hide underlying implementation and its quirks; | ||
* Make 80% easy, 20% possible. | ||
* [react-draggable](https://github.com/mzabriskie/react-draggable) by [Matt Zabriskie](https://github.com/mzabriskie) | ||
* [react-sortable](https://github.com/danielstocks/react-sortable) by [Daniel Stocks](https://github.com/danielstocks) | ||
* [react-dropzone](https://github.com/paramaggarwal/react-dropzone) by [Param Aggarwal](https://github.com/paramaggarwal) | ||
## Live Demo | ||
If they don't, read on. | ||
#### [See it in action!](http://gaearon.github.io/react-dnd/) | ||
## Examples | ||
Demo contains a variety of things you can implement with this library, including: | ||
After cloning the project, run: | ||
* Reacting to hover and dropping; | ||
* Dropping files; | ||
* Dragging a box around with snapping; | ||
* Drawing a custom drag layer; | ||
* Making cards sortable. | ||
``` | ||
npm install | ||
npm start | ||
open http://localhost:8080/ | ||
``` | ||
You can do much more, but these examples will help you get started! | ||
This will run the included examples. | ||
Or you can **[view them in browser](http://gaearon.github.io/react-dnd/)** (and see their **[source code](https://github.com/gaearon/react-dnd/tree/master/examples)**). | ||
## Features | ||
* Emits zero DOM or CSS of its own; | ||
* Like original HTML5 API, emphasizes dragging data and not just “draggable views”; | ||
* Support dropping files using the same API; | ||
* Lets components register as “drag sources” or “drop targets” for different kinds of data; | ||
* Lets a single component contain several drag sources and drop targets; | ||
* Lets you provide a custom drag handle, whether DOM subnode or an image; | ||
* Takes the best from HTML5 API but [hides its many quirks](http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html): | ||
- doesn't require you to `preventDefault` anything to start working; | ||
- emits `enter` and `leave` as you'd expect instead of doing it for every child node; | ||
- lets you read drag state from `render()`; | ||
- consistently fires events even if source DOM node was removed; | ||
* Includes a helper to preload images for drag thumbnails; | ||
* Lets you render a custom drag layer if you'd rather draw your own drag preview. | ||
## Installation | ||
## Documentation | ||
The library can be used separately (`dist/ReactDND.min.js`) or with a bundler such as Webpack or Browserify. | ||
### API Reference | ||
``` | ||
npm install --save react-dnd | ||
``` | ||
Complete API reference is available **[here](https://github.com/gaearon/react-dnd/tree/master/docs/API.md)**. | ||
Dependencies: Flux and a couple of functions from lodash-node; | ||
Peer Dependencies: React >= 0.12.0. | ||
### Walkthrough | ||
It is written in ES6 but there's an ES5 version in `dist-modules` folder. | ||
The ES5 version is what you get when you `require('react-dnd')`. | ||
If you don't feel comfortable diving into examples source code just yet, you can start with **[the walkthrough](https://github.com/gaearon/react-dnd/tree/master/docs/Walkthrough.md)**. | ||
The examples use ES6. | ||
### Examples | ||
## Rationale | ||
Have you played with **[live demo](http://gaearon.github.io/react-dnd/)** yet? Here's **[the source code for it](https://github.com/gaearon/react-dnd/tree/master/examples)**. | ||
Existing drag-and-drop libraries didn't fit my use case so I wrote my own. It's similar to the code we've been running for about a year on Stampsy.com, but rewritten to take advantage of React and Flux. | ||
To try it locally, clone the project and run: | ||
Key requirements: | ||
* Emit zero DOM or CSS of its own, leaving it to the consuming components; | ||
* Impose as little structure as possible on consuming components; | ||
* Use HTML5 drag and drop as primary backend but make it possible to add different backends in the future; | ||
* Like original HTML5 API, emphasize dragging data and not just “draggable views”; | ||
* Support dropping files; | ||
* Hide [HTML5 API quirks](http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html) from the consuming code; | ||
* Different components may be “drag sources” or “drop targets” for different kinds of data; | ||
* Allow one component to contain several drag sources and drop targets when needed; | ||
* Make it easy for drop targets to change their appearance if compatible data is being dragged or hovered; | ||
* Make it easy to use images for drag thumbnails instead of element screenshots, circumventing [browser quirks](http://stackoverflow.com/questions/7340898/html5-setdragimage-only-works-sometimes). | ||
Hopefully the resulting API reflects that. | ||
## Snippets | ||
### Simple Drag Source | ||
First, declare types of data that can be dragged. This library, in vein of native drag and drop API, emphasizes dragging *data* and not specific DOM nodes themselves. Drag sources provide data to be dragged, and drag targets choose to either accept or decline data depending on its type. | ||
It is up to you to update your models in response to drop or other drag events. The library won't touch the DOM nodes. You have full control over your DOM. This makes react-dnd very flexible: you can implement [selective drop targets](http://gaearon.github.io/react-dnd/#/dustbin-interesting), [2D dragging on a plane](http://gaearon.github.io/react-dnd/#/drag-around-custom) or [a sortable](http://gaearon.github.io/react-dnd/#/sortable-simple) with the same set of tools. | ||
String “types” are used to check compatibility of drag sources and drop targets: | ||
```javascript | ||
// A sample ItemTypes.js enumeration for an app where you can drag images and blocks | ||
module.exports = { | ||
BLOCK: 'block', | ||
IMAGE: 'image' | ||
}; | ||
``` | ||
These types are just string constants that are used to match compatible drag sources and drop targets. Even if you only plan to have one draggable type of items, it's still neccessary to declare a string constant for it. This makes it trivial to later add additional draggable/droppable types without rewriting half of your drag and drop code. Also, always relying on types allows us to elegantly support file drag and drop via a “builtin” `NativeDragItemTypes.FILE` type. | ||
Let's make a very simple draggable component that, when dragged, represents `IMAGE`: | ||
```javascript | ||
/** | ||
* Don't panic! | ||
* Examples will use ES6 syntax. | ||
* | ||
* var { DragDropMixin } = require('react-dnd'); | ||
* | ||
* is equivalent to this in ES5: | ||
* | ||
* var DragDropMixin = require('react-dnd').DragDropMixin; | ||
*/ | ||
var { DragDropMixin } = require('react-dnd'), | ||
ItemTypes = require('./ItemTypes'); | ||
var Image = React.createClass({ | ||
mixins: [DragDropMixin], | ||
statics: { | ||
configureDragDrop(registerType) { | ||
// Specify all supported types by calling registerType(type, { dragSource?, dropTarget? }) | ||
registerType(ItemTypes.IMAGE, { | ||
// dragSource, when specified, is { | ||
// beginDrag(component), | ||
// canDrag(component)?, | ||
// endDrag(component, dropEffect)? | ||
// } | ||
dragSource: { | ||
// beginDrag should return { | ||
// item, | ||
// dragAnchors?, | ||
// dragPreview?, | ||
// dragEffect? | ||
// } | ||
beginDrag(component) { | ||
return { | ||
item: component.props.image | ||
}; | ||
} | ||
} | ||
}); | ||
} | ||
}, | ||
render() { | ||
// {...this.dragSourceFor(ItemTypes.IMAGE)} will expand into | ||
// { draggable: true, onDragStart: (handled by mixin), onDragEnd: (handled by mixin) }. | ||
return ( | ||
<img src={this.props.image.url} | ||
{...this.dragSourceFor(ItemTypes.IMAGE)} /> | ||
); | ||
} | ||
); | ||
npm install | ||
npm start | ||
open http://localhost:8080/ | ||
``` | ||
By specifying `configureDragDrop` in `statics`, we tell `DragDropMixin` the drag-drop behavior of this component. Both draggable and droppable components use the same mixin. | ||
Examples use [ES6 syntax](https://babeljs.io/docs/learn-es6/). | ||
Inside `configureDragDrop`, we need to call `registerType` for each of our custom `ItemTypes` that component supports. For example, there might be several representations of images in your app, and each would provide a `dragSource` for `ItemTypes.IMAGE`. | ||
## Installation | ||
A `dragSource` is just an object specifying how the drag source works. You must implement `beginDrag(component)` to return `item` that represents the data you're dragging and, optionally, a few options that adjust the dragging UI. You can optionally `canDrag(component)` to forbid dragging, or `endDrag(component, dropEffect)` to execute some logic when the drop has (or has not) occured. And you can share this logic between components by letting a shared mixins generate `dragSource` for them. | ||
The library can be used separately (`dist/ReactDND.min.js`) or with a bundler such as Webpack or Browserify. | ||
Finally, you must use `{...this.dragSourceFor(itemType)}` on some (one or more) elements in `render` to attach drag handlers. This means you can have several “drag handles” in one element, and they may even correspond to different item types. (If you're not familiar with [JSX Spread Attributes syntax](https://gist.github.com/sebmarkbage/07bbe37bc42b6d4aef81), check it out). | ||
### Simple Drop Target | ||
Let's say we want `ImageBlock` to be a drop target for `IMAGE`s. It's pretty much the same, except that we need to give `registerType` a `dropTarget` implementation: | ||
```javascript | ||
var { DragDropMixin } = require('react-dnd'), | ||
ItemTypes = require('./ItemTypes'); | ||
var ImageBlock = React.createClass({ | ||
mixins: [DragDropMixin], | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.IMAGE, { | ||
// dropTarget, when specified, is { | ||
// acceptDrop(component, item)?, | ||
// canDrop(component, item)?, | ||
// enter(component, item)?, | ||
// over(component, item)?, | ||
// leave(component, item)? | ||
// } | ||
dropTarget: { | ||
acceptDrop(component, image) { | ||
// Do something with image! For example, | ||
DocumentActionCreators.setImage(component.props.blockId, image); | ||
} | ||
} | ||
}); | ||
} | ||
}, | ||
render() { | ||
// {...this.dropTargetFor(ItemTypes.IMAGE)} will expand into | ||
// { onDragEnter: (handled by mixin), onDragOver: (handled by mixin), onDragLeave: (handled by mixin), onDrop: (handled by mixin) } | ||
return ( | ||
<div {...this.dropTargetFor(ItemTypes.IMAGE)}> | ||
{this.props.image && | ||
<img src={this.props.image.url} /> | ||
} | ||
</div> | ||
); | ||
} | ||
); | ||
``` | ||
### Drag Source + Drop Target In One Component | ||
Say we now want the user to be able to *drag out* an image out of `ImageBlock`. We just need to add appropriate `dragSource` to it and a few handlers: | ||
```javascript | ||
var { DragDropMixin } = require('react-dnd'), | ||
ItemTypes = require('./ItemTypes'); | ||
var ImageBlock = React.createClass({ | ||
mixins: [DragDropMixin], | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.IMAGE, { | ||
// Add a drag source that only works when ImageBlock has an image: | ||
dragSource: { | ||
canDrag(component) { | ||
return !!component.props.image; | ||
}, | ||
beginDrag(component) { | ||
return { | ||
item: component.props.image | ||
}; | ||
} | ||
}, | ||
dropTarget: { | ||
acceptDrop(component, image) { | ||
DocumentActionCreators.setImage(component.props.blockId, image); | ||
} | ||
} | ||
}); | ||
} | ||
}, | ||
render() { | ||
return ( | ||
<div {...this.dropTargetFor(ItemTypes.IMAGE)}> | ||
{/* Add {...this.dragSourceFor} handlers to a nested node */} | ||
{this.props.image && | ||
<img src={this.props.image.url} | ||
{...this.dragSourceFor(ItemTypes.IMAGE)} /> | ||
} | ||
</div> | ||
); | ||
} | ||
); | ||
npm install --save react-dnd | ||
``` | ||
### Dropping Files from the Hard Drive | ||
## Future Roadmap | ||
The library provides one built-in item type: `NativeDragItemTypes.FILE`. You can't set up a drag source for it, but you can set up as many drop targets as you want with the same API as normal drop targets. The only way in which file drop target differs from a normal one is that `item` parameter will always be `null` in `enter`, `over` and `leave`. In `drop`, its `files` property will contain a JS array of filenames as given by browser. | ||
* Touch support; | ||
* Support for mouse events instead of HTML5 drag-and-drop events; | ||
* Dragging multiple items at once. | ||
```javascript | ||
var { DragDropMixin, NativeDragItemTypes } = require('react-dnd'); | ||
## See Also | ||
var ImageUploader = React.createClass({ | ||
mixins: [DragDropMixin], | ||
* [react-draggable](https://github.com/mzabriskie/react-draggable) by [Matt Zabriskie](https://github.com/mzabriskie) | ||
* [react-sortable](https://github.com/danielstocks/react-sortable) by [Daniel Stocks](https://github.com/danielstocks) | ||
* [react-dropzone](https://github.com/paramaggarwal/react-dropzone) by [Param Aggarwal](https://github.com/paramaggarwal) | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(NativeDragItemTypes.FILE, { | ||
dropTarget: { | ||
acceptDrop(component, item) { | ||
// Do something with files | ||
console.log(item.files); | ||
} | ||
} | ||
}); | ||
} | ||
}, | ||
render() { | ||
var fileDropState = this.getDropState(NativeDragItemTypes.FILE); | ||
return ( | ||
<div {...this.dropTargetFor(NativeDragItemTypes.FILE)}> | ||
{fileDropState.isDragging && !fileDropState.isHovering && | ||
<p>Drag file here</p> | ||
} | ||
{fileDropState.isHovering && | ||
<p>Release to upload a file</p> | ||
} | ||
</div> | ||
); | ||
} | ||
); | ||
``` | ||
### What Else Is Possible? | ||
I have not covered everything but it's possible to use this API in a few more ways: | ||
* Use `getDragState(type)` and `getDropState(type)` to learn if dragging is active and use it to toggle CSS classes or attributes; | ||
* Specify `dragPreview` to be `Image` to use images as drag placeholders (use `ImagePreloaderMixin` to load them); | ||
* Say, we want to make `ImageBlock`s reorderable. We only need them to implement `dropTarget` and `dragSource` for `ItemTypes.BLOCK`. | ||
* Suppose we add other kinds of blocks. We can reuse their reordering logic by placing it in a mixin. | ||
* `dropTargetFor(...types)` allows to specify several types at once, so one drop zone can catch many different types. | ||
* When you need more fine-grained control, most methods are passed drag event that caused them as the last parameter. | ||
## API | ||
### `require('react-dnd').DragDropMixin` | ||
`statics.configureDragDrop(registerType)` | ||
Gives you a chance to configure drag and drop on your component. | ||
Components with `DragDropMixin` will have this method. | ||
`registerType(type, { dragSource?, dropTarget? })` | ||
Call this method to specify component behavior as drag source or drop target for given type. | ||
This method is passed as a parameter to `configureDragDrop`. | ||
`getDragState(type)` | ||
Returns `{ isDragging: bool }` describing whether a particular type is being dragged from this component's drag source. You may want to call this method from `render`, e.g. to hide an element that is being dragged. | ||
`getDropState(type)` | ||
Returns `{ isDragging: bool, isHovering: bool }` describing whether a particular type is being dragged or hovered, when it is compatible with this component's drop source. You may want to call this method from `render`, e.g. to highlight drop targets when they are comparible and when they are hovered. | ||
`dragSourceFor(type)` | ||
Returns props to be given to any DOM element you want to make a drag source. Intended to be used with JSX spread attribute syntax. | ||
`dropTargetFor(types...)` | ||
Returns props to be given to any DOM element you want to make a drop target. Intended to be used with JSX spread attribute syntax. | ||
=================== | ||
### Drag Source API | ||
Implement to specify drag behavior of a component: | ||
* `beginDrag(component: ReactComponent, e: SyntheticEvent)` — return value must contain `item: Object` representing your data and may also contain `dragPreview: (Image | HTMLElement)?`, `dragAnchors: { horizontal: HorizontalDragAnchors?, vertical: VerticalDragAnchors? }?`, `effectsAllowed: DropEffects[]?`. | ||
* `canDrag(component: ReactComponent, e: SyntheticEvent)` — optionally decide whether to allow dragging. | ||
* `endDrag(component: ReactComponent, effect: DropEffect?, e: SyntheticEvent)` — optionally handle end of dragging operation. `effect` is falsy if item was dropped outside compatible drop targets, or if drop target returned `null` from `getDropEffect()`. | ||
=================== | ||
### Drop Target API | ||
To perform side effects in response to changing drag state, use these methods: | ||
* `enter(component: ReactComponent, item: Object, e: SyntheticEvent)` | ||
* `leave(component: ReactComponent, item: Object, e: SyntheticEvent)` | ||
* `over(component: ReactComponent, item: Object, e: SyntheticEvent)` | ||
For example, you might use `over` for reordering items when they overlap. If you need to render different states when drop target is active or hovered, it is easier to use `this.getDropState(type)` in `render` method. | ||
Implement these methods to specify drop behavior of a component: | ||
* `canDrop(component: ReactComponent, item: Object): Boolean` — optionally implement this method to reject some of the items. | ||
* `getDropEffect(component: ReactComponent, effectsAllowed: DropEffect[]): DropEffect?` — optionally implement this method to specify drop effect that will be used by some browser for cursor, and will be passed to drag source's `endDrag`. Returned drop effect must be one of the `effectsAllowed` specified by drag source or `null`. Default implementation returns `effectsAllowed[0]`. | ||
* `acceptDrop(component: ReactComponent, item: Object, e: SyntheticEvent, isHandled: bool, effect: DropEffect?)` — optionally implement this method to perform some action when drop occurs. `isHandled` is `true` if some child drop target has already handled drop. `effect` is the drop effect you returned from `getDropEffect`, or if `isHandled` is `true`, drop effect of the child drop target that handled the drop. | ||
=================== | ||
### `require('react-dnd').ImagePreloaderMixin` | ||
You can optionally specify images to be used as drag thumbnails. | ||
Browsers can't do this reliably until image is loaded, so `ImagePreloaderMixin` provides an API to do just that: | ||
```javascript | ||
mixins: [DragDropMixin, ImagePreloaderMixin], | ||
// This method should return array of image urls for preloading | ||
getImageUrlsToPreload() { | ||
return ['some-img-url1', 'some-img-url2']; | ||
}, | ||
// You can now use `this.hasPreloadedImage(url)` and `this.getPreloadedImage(url)` in your `dragSource`: | ||
statics: { | ||
configureDragDrop(registerType) { | ||
registerType(ItemTypes.MY_ITEM, { | ||
dragSource: { | ||
canDrag(component) { | ||
return component.hasPreloadedImage('some-img-url1'); | ||
}, | ||
beginDrag(component) { | ||
return { | ||
item: ..., | ||
dragPreivew: component.getPreloadedImage('some-img-url1'); | ||
}; | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
``` | ||
Above code will load the images after `componentDidMount` is executed, and cache them until component unmounted. In `componentDidUpdate`, mixin will check if `getImageUrlsToPreload` has changed, and load images again if needed. | ||
Note that, for best results, you want to use `this.getDragImageScale()`. It will return correct scale to download for your images, considering browser differences in handling Retina screens (should either return `1` or `window.devicePixelRatio`). You can either use it with a custom server image resizer, or to choose between normal and `@2x` versions of predefined images. | ||
### `require('react-dnd').NativeDragItemTypes` | ||
Provides a single constant, `NativeDragItemTypes.FILE`, that you can use as an item type for file drop targets. | ||
### `require('react-dnd').DropEffects` | ||
Provides constants to be passed in `effectsAllowed` array from `beginDrag()` and returned from drop target's `getDropEffect()`. Correponds to singular native [`dataTransfer.dropEffect`](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer#dropEffect.28.29) values. | ||
## Thanks | ||
This library is a React port of an API, parts of which were originally written by [Andrew Kuznetsov](http://github.com/cavinsmith/). | ||
A lot of recent progress is due to [Nathan Hutchison](https://github.com/nelix)'s contributions and effort. |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2249768
113
4316
95