react-ant-dragger
Version:
Component-based drag and drop for React.js
873 lines (755 loc) • 27.4 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('prop-types'), require('react-dnd'), require('react-dom'), require('react-dnd-html5-backend')) :
typeof define === 'function' && define.amd ? define(['exports', 'react', 'prop-types', 'react-dnd', 'react-dom', 'react-dnd-html5-backend'], factory) :
(factory((global.AntDragger = {}), global.React, global.PropTypes, global.ReactDnD, global.ReactDOM, global.ReactDnDHTML5Backend));
}(this, (function (exports, React, PropTypes, reactDnd, ReactDOM, HTML5Backend) {
'use strict';
React = React && React.hasOwnProperty('default') ? React['default'] : React;
PropTypes = PropTypes && PropTypes.hasOwnProperty('default') ? PropTypes['default'] : PropTypes;
ReactDOM = ReactDOM && ReactDOM.hasOwnProperty('default') ? ReactDOM['default'] : ReactDOM;
HTML5Backend = HTML5Backend && HTML5Backend.hasOwnProperty('default') ? HTML5Backend['default'] : HTML5Backend;
function unwrapExports(x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
function createCommonjsModule(fn, module) {
return module = {
exports: {}
}, fn(module, module.exports), module.exports;
}
var shallowEqual_1 = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = shallowEqual;
function shallowEqual(objA, objB) {
if (objA === objB) {
return true;
}
var keysA = Object.keys(objA);
var keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
var hasOwn = Object.prototype.hasOwnProperty;
for (var i = 0; i < keysA.length; i += 1) {
if (!hasOwn.call(objB, keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) {
return false;
}
var valA = objA[keysA[i]];
var valB = objB[keysA[i]];
if (valA !== valB) {
return false;
}
}
return true;
}
});
var shallowEqual = unwrapExports(shallowEqual_1);
var BEGIN_DRAG = 'BEGIN_DRAG';
var END_DRAG = 'END_DRAG';
var DROP = 'DROP';
var HOVER = 'HOVER';
var ENTER = 'ENTER';
var LEAVE = 'LEAVE';
var CAN_DRAG = 'CAN_DRAG';
var CAN_DROP = 'CAN_DROP';
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var Draggable = function (_React$Component) {
inherits(Draggable, _React$Component);
function Draggable() {
classCallCheck(this, Draggable);
return possibleConstructorReturn(this, (Draggable.__proto__ || Object.getPrototypeOf(Draggable)).apply(this, arguments));
}
createClass(Draggable, [{
key: 'getChildContext',
value: function getChildContext() {
return {
dragSourceCreator: this.props.connectDragSource,
dragCursor: this.props.dragCursor,
dragHandlerType: this.props.dragHandlerType
};
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _props = this.props,
children = _props.children,
dragToken = _props.dragToken,
draggerPreview = _props.draggerPreview,
connectDragPreview = _props.connectDragPreview;
if (draggerPreview && typeof draggerPreview === 'function') {
var node = draggerPreview(dragToken(), children.props);
if (typeof node === 'function') {
node(connectDragPreview);
} else if (typeof node.then === 'function') {
node.then(connectDragPreview);
} else {
connectDragPreview(node);
}
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps, prevState) {
var _props2 = this.props,
dragToken = _props2.dragToken,
dispatcher = _props2.dispatcher,
currIsOver = _props2.isOver,
item = _props2.item;
var prevIsOver = prevProps.isOver;
if (!prevIsOver && currIsOver) {
// enter
dispatcher(ENTER, {
source: item && item.$source,
target: dragToken(),
props: this.props,
component: this
});
} else if (!currIsOver && prevIsOver) {
// leave
dispatcher(LEAVE, {
source: item && item.$source,
target: dragToken(),
props: this.props,
component: this
});
}
}
}, {
key: 'render',
value: function render() {
var _props3 = this.props,
children = _props3.children,
dispatcher = _props3.dispatcher,
dragToken = _props3.dragToken,
dragCursor = _props3.dragCursor,
draggingHint = _props3.draggingHint,
dragHandlerType = _props3.dragHandlerType,
Tag = _props3.wrapTag,
wrapStyle = _props3.wrapStyle,
wrapClassName = _props3.wrapClassName,
draggerPreview = _props3.draggerPreview,
connectDragSource = _props3.connectDragSource,
connectDropTarget = _props3.connectDropTarget,
connectDragPreview = _props3.connectDragPreview,
isDragging = _props3.isDragging,
isOver = _props3.isOver,
item = _props3.item,
itemType = _props3.itemType,
differenceFromInitialOffset = _props3.differenceFromInitialOffset,
initialClientOffset = _props3.initialClientOffset,
initialSourceClientOffset = _props3.initialSourceClientOffset,
clientOffset = _props3.clientOffset,
sourceClientOffset = _props3.sourceClientOffset,
otherProps = objectWithoutProperties(_props3, ['children', 'dispatcher', 'dragToken', 'dragCursor', 'draggingHint', 'dragHandlerType', 'wrapTag', 'wrapStyle', 'wrapClassName', 'draggerPreview', 'connectDragSource', 'connectDropTarget', 'connectDragPreview', 'isDragging', 'isOver', 'item', 'itemType', 'differenceFromInitialOffset', 'initialClientOffset', 'initialSourceClientOffset', 'clientOffset', 'sourceClientOffset']);
var className = wrapClassName;
if (typeof className !== 'string' && typeof className.join === 'function') {
className = className.join(' ');
}
var style = _extends({
cursor: dragHandlerType !== 'default' ? 'auto' : dragCursor
}, wrapStyle);
var props = _extends({
className: className,
style: style
}, otherProps);
var child = children;
if (typeof child !== 'string') {
child = React.Children.only(child);
}
if (isDragging && typeof draggingHint === 'function' && differenceFromInitialOffset !== null) {
var newProps = draggingHint(props, child);
if (newProps) {
props = newProps;
}
}
if (typeof child.type !== 'string') {
child = React.createElement(
Tag,
props,
child
);
} else {
child = React.cloneElement(child, _extends({}, child.props, props, {
style: _extends({}, child.props.style, props.style)
}));
}
if (!draggerPreview) {
child = connectDragPreview(child);
}
if (dragHandlerType === 'default') {
child = connectDragSource(child);
}
return connectDropTarget(child);
}
}]);
return Draggable;
}(React.Component);
Draggable.childContextTypes = {
dragSourceCreator: PropTypes.func,
dragCursor: PropTypes.string,
dragHandlerType: PropTypes.string
};
var DraggableWrapper = function (_React$Component2) {
inherits(DraggableWrapper, _React$Component2);
function DraggableWrapper(props, context) {
classCallCheck(this, DraggableWrapper);
var _this2 = possibleConstructorReturn(this, (DraggableWrapper.__proto__ || Object.getPrototypeOf(DraggableWrapper)).call(this, props, context));
_this2.dragSource = {
beginDrag: _this2.dispatchBeginDragEvent.bind(_this2),
endDrag: _this2.dispatchEndDragEvent.bind(_this2),
canDrag: _this2.dispatchCanDragEvent.bind(_this2)
};
_this2.dropTarget = {
hover: _this2.dispatchHoverEvent.bind(_this2),
drop: _this2.dispatchDropEvent.bind(_this2),
canDrop: _this2.dispatchCanDropEvent.bind(_this2)
};
_this2.cachedWrapped = undefined;
return _this2;
}
createClass(DraggableWrapper, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.cachedWrapped = undefined;
}
}, {
key: 'dispatchBeginDragEvent',
value: function dispatchBeginDragEvent(props, monitor, component) {
var source = this.props.dragToken();
var result = this.context.dispatcher(BEGIN_DRAG, {
source: source,
props: props,
component: component
});
if (result === undefined) {
result = {};
}
if (result.dragToken === undefined) {
result.dragToken = source;
}
result.$target = result.$source = result.dragToken;
return result;
}
}, {
key: 'dispatchEndDragEvent',
value: function dispatchEndDragEvent(props, monitor, component) {
var _monitor$getItem = monitor.getItem(),
target = _monitor$getItem.$target,
source = _monitor$getItem.$source;
this.context.dispatcher(END_DRAG, {
target: target,
source: source,
props: props,
component: component
});
}
}, {
key: 'dispatchCanDragEvent',
value: function dispatchCanDragEvent(props, monitor) {
var source = this.props.dragToken();
var result = this.context.dispatcher(CAN_DRAG, {
source: source,
props: props
});
if (result === undefined) {
result = true;
}
return result;
}
}, {
key: 'dispatchHoverEvent',
value: function dispatchHoverEvent(props, monitor, component) {
var current = component.props.dragToken();
var source = monitor.getItem().$source;
if (shallowEqual(current, source) && current === source) {
return;
}
monitor.getItem().$target = current;
var handled = this.context.dispatcher(HOVER, {
target: current,
source: source,
props: props,
component: component
});
if (handled && handled.constructor === current.constructor) {
monitor.getItem().$target = handled;
}
return handled;
}
}, {
key: 'dispatchDropEvent',
value: function dispatchDropEvent(props, monitor, component) {
var _monitor$getItem2 = monitor.getItem(),
target = _monitor$getItem2.$target,
source = _monitor$getItem2.$source;
var handled = this.context.dispatcher(DROP, {
target: target,
source: source,
props: props,
component: component
});
return handled;
}
}, {
key: 'dispatchCanDropEvent',
value: function dispatchCanDropEvent(props, monitor) {
var _monitor$getItem3 = monitor.getItem(),
target = _monitor$getItem3.$target,
source = _monitor$getItem3.$source;
var result = this.context.dispatcher(CAN_DROP, {
target: target,
source: source,
props: props
});
if (result === undefined) {
result = true;
}
return result;
}
}, {
key: 'render',
value: function render() {
var _props4 = this.props,
children = _props4.children,
dragToken = _props4.dragToken,
dragCursor = _props4.dragCursor,
draggingHint = _props4.draggingHint,
wrapTag = _props4.wrapTag,
wrapStyle = _props4.wrapStyle,
wrapClassName = _props4.wrapClassName,
otherProps = objectWithoutProperties(_props4, ['children', 'dragToken', 'dragCursor', 'draggingHint', 'wrapTag', 'wrapStyle', 'wrapClassName']);
var _context = this.context,
dispatcher = _context.dispatcher,
draggerType = _context.draggerType,
draggerPreview = _context.draggerPreview;
if (!this.cachedWrapped) {
this.cachedWrapped = reactDnd.DragSource(draggerType, this.dragSource, function (connect, monitor) {
return {
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
isDragging: monitor.isDragging(),
initialClientOffset: monitor.getInitialClientOffset(),
initialSourceClientOffset: monitor.getInitialSourceClientOffset()
};
})(reactDnd.DropTarget(draggerType, this.dropTarget, function (connect, monitor) {
return {
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver({
shallow: true
}),
item: monitor.getItem(),
itemType: monitor.getItemType(),
differenceFromInitialOffset: monitor.getDifferenceFromInitialOffset(),
clientOffset: monitor.getClientOffset(),
sourceClientOffset: monitor.getSourceClientOffset()
};
})(Draggable));
}
var Wrapped = this.cachedWrapped;
var wrappedProps = {
dragCursor: dragCursor,
draggingHint: draggingHint,
wrapTag: wrapTag,
wrapStyle: wrapStyle,
wrapClassName: wrapClassName,
draggerPreview: draggerPreview,
dragToken: dragToken,
dispatcher: dispatcher
};
return React.createElement(
Wrapped,
_extends({}, wrappedProps, otherProps),
children
);
}
}]);
return DraggableWrapper;
}(React.Component);
DraggableWrapper.contextTypes = {
dispatcher: PropTypes.func,
draggerType: PropTypes.string,
dragDropManager: PropTypes.object,
draggerPreview: PropTypes.func
};
DraggableWrapper.propTypes = {
dragToken: PropTypes.func.isRequired,
draggingHint: PropTypes.func,
dragHandlerType: PropTypes.oneOf(['default', 'handler']),
dragCursor: PropTypes.oneOf(['default', 'move', 'pointer']),
wrapTag: PropTypes.string,
wrapStyle: PropTypes.object,
wrapClassName: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.string])
};
DraggableWrapper.defaultProps = {
wrapTag: 'div',
dragCursor: 'default',
dragHandlerType: 'default',
wrapStyle: {},
wrapClassName: ''
};
var eventDispatcher = (function (fn) {
return function (type, event) {
return fn(type, event);
};
});
var eventCreator = (function (source, target) {
return function () {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var base = {
source: source,
target: target
};
var extra = {
item: options.item,
itemType: options.itemType,
isDragging: options.isDragging,
isOver: options.isOver,
differenceFromInitialOffset: options.differenceFromInitialOffset,
initialClientOffset: options.initialClientOffset,
initialSourceClientOffset: options.initialSourceClientOffset,
clientOffset: options.clientOffset,
sourceClientOffset: options.sourceClientOffset
};
return _extends({}, base, extra);
};
});
var _EVENT_FUNC;
var EVENT_FUNC = (_EVENT_FUNC = {}, defineProperty(_EVENT_FUNC, BEGIN_DRAG, 'onDragStart'), defineProperty(_EVENT_FUNC, END_DRAG, 'onDragEnd'), defineProperty(_EVENT_FUNC, HOVER, 'onDragging'), defineProperty(_EVENT_FUNC, ENTER, 'onDragEnter'), defineProperty(_EVENT_FUNC, LEAVE, 'onDragLeave'), defineProperty(_EVENT_FUNC, DROP, 'onDrop'), defineProperty(_EVENT_FUNC, CAN_DRAG, 'canDrag'), defineProperty(_EVENT_FUNC, CAN_DROP, 'canDrop'), _EVENT_FUNC);
var noop = function noop() {};
var Dragger = function (_React$Component) {
inherits(Dragger, _React$Component);
function Dragger(props, context) {
classCallCheck(this, Dragger);
var _this = possibleConstructorReturn(this, (Dragger.__proto__ || Object.getPrototypeOf(Dragger)).call(this, props, context));
_this.notifyHandler = _this.notifyHandler.bind(_this);
_this.dispatcher = eventDispatcher(_this.notifyHandler);
return _this;
}
createClass(Dragger, [{
key: 'getChildContext',
value: function getChildContext() {
return {
dispatcher: this.dispatcher,
draggerType: this.props.draggerType,
draggerPreview: this.props.draggerPreview
};
}
}, {
key: 'notifyHandler',
value: function notifyHandler(type, _ref) {
var target = _ref.target,
source = _ref.source,
props = _ref.props,
component = _ref.component;
var fn = this.props[EVENT_FUNC[type]];
if (type === CAN_DROP && !fn) {
fn = this.props.canDrag;
}
if (!fn) {
console.warn('Unknown event type', type);
}
return fn && fn(eventCreator(source, target)(props), props, component);
}
}, {
key: 'render',
value: function render() {
var connectDropTarget = this.props.connectDropTarget;
return connectDropTarget(React.Children.only(this.props.children));
}
}]);
return Dragger;
}(React.Component);
Dragger.propTypes = {
onDragStart: PropTypes.func,
onDragEnd: PropTypes.func,
onDrop: PropTypes.func,
onDragging: PropTypes.func,
onDragEnter: PropTypes.func,
onDragLeave: PropTypes.func,
canDrag: PropTypes.func,
canDrop: PropTypes.func,
draggerType: PropTypes.string,
draggerPreview: PropTypes.func
};
Dragger.defaultProps = {
onDragStart: noop,
onDragEnd: noop,
onDrop: noop,
onDragging: noop,
onDragEnter: noop,
onDragLeave: noop,
canDrag: function canDrag() {
return true;
},
canDrop: undefined,
draggerType: '__dragger__',
draggerPreview: undefined
};
Dragger.childContextTypes = {
dispatcher: PropTypes.func,
draggerType: PropTypes.string,
draggerPreview: PropTypes.func
};
Dragger.contextTypes = {
dragDropManager: PropTypes.object
};
var Wrapper = function (_React$Component2) {
inherits(Wrapper, _React$Component2);
function Wrapper(props) {
classCallCheck(this, Wrapper);
var _this2 = possibleConstructorReturn(this, (Wrapper.__proto__ || Object.getPrototypeOf(Wrapper)).call(this, props));
_this2.dropTarget = {
hover: _this2.handleContainerHover.bind(_this2)
};
_this2.edgeWidth = _this2.props.edgeWidth;
if (typeof _this2.edgeWidth === 'number') {
var v = _this2.edgeWidth;
_this2.edgeWidth = {
left: v,
top: v,
right: v,
bottom: v
};
}
_this2.cachedWrapped = undefined;
return _this2;
}
createClass(Wrapper, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.cachedWrapped = undefined;
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
this.refreshBoundingRect();
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
this.refreshBoundingRect();
}
}, {
key: 'handleContainerHover',
value: function handleContainerHover(props, monitor, component) {
var _monitor$getClientOff = monitor.getClientOffset(),
clientX = _monitor$getClientOff.x,
clientY = _monitor$getClientOff.y;
var _containerBoundingRec = this.containerBoundingRect,
left = _containerBoundingRec.left,
top = _containerBoundingRec.top,
right = _containerBoundingRec.right,
bottom = _containerBoundingRec.bottom;
var _edgeWidth = this.edgeWidth,
edgeLeft = _edgeWidth.left,
edgeTop = _edgeWidth.top,
edgeRight = _edgeWidth.right,
edgeBottom = _edgeWidth.bottom;
var containerEdge = {
left: left + edgeLeft,
top: top + edgeTop,
right: right - edgeRight,
bottom: bottom - edgeBottom
};
var strike = {
left: clientX <= containerEdge.left,
top: clientY <= containerEdge.top,
right: clientX >= containerEdge.right,
bottom: clientY >= containerEdge.bottom
};
if (strike.left || strike.top || strike.right || strike.bottom) {
this.props.onDragEdge({
strike: strike,
client: {
x: clientX,
y: clientY
},
edge: containerEdge,
itemType: monitor.getItemType(),
initialClientOffset: monitor.getInitialClientOffset(),
initialSourceClientOffset: monitor.getInitialSourceClientOffset(),
clientOffset: monitor.getClientOffset(),
sourceClientOffset: monitor.getSourceClientOffset(),
differenceFromInitialOffset: monitor.getDifferenceFromInitialOffset()
}, props, component);
}
}
}, {
key: 'refreshBoundingRect',
value: function refreshBoundingRect() {
var _this3 = this;
setTimeout(function () {
var el = ReactDOM.findDOMNode(_this3);
_this3.containerBoundingRect = el.getBoundingClientRect();
}, 0);
}
}, {
key: 'render',
value: function render() {
if (!this.cachedWrapped) {
this.cachedWrapped = reactDnd.DropTarget(this.props.draggerType, this.dropTarget, function (collect, monitor) {
return {
connectDropTarget: collect.dropTarget()
};
})(Dragger);
}
var Wrap = this.cachedWrapped;
return React.createElement(
Wrap,
this.props,
this.props.children
);
}
}]);
return Wrapper;
}(React.Component);
Wrapper.propTypes = {
onDragEdge: PropTypes.func,
edgeWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
draggerType: PropTypes.string
};
Wrapper.defaultProps = {
onDragEdge: noop,
edgeWidth: 20,
draggerType: '__dragger__'
};
var _DraggerContext = reactDnd.DragDropContext(HTML5Backend);
var DraggerHandler = function (_React$Component) {
inherits(DraggerHandler, _React$Component);
function DraggerHandler() {
classCallCheck(this, DraggerHandler);
return possibleConstructorReturn(this, (DraggerHandler.__proto__ || Object.getPrototypeOf(DraggerHandler)).apply(this, arguments));
}
createClass(DraggerHandler, [{
key: 'render',
value: function render() {
var _context = this.context,
dragSourceCreator = _context.dragSourceCreator,
dragHandlerType = _context.dragHandlerType,
dragCursor = _context.dragCursor;
var style = _extends({
cursor: dragCursor
}, this.props.style);
var className = this.props.className;
var children = this.props.children;
if (dragHandlerType === 'handler') {
var Tag = this.props.wrapTag;
children = dragSourceCreator(React.createElement(
Tag, {
className: className,
style: style
},
children
));
}
return children;
}
}]);
return DraggerHandler;
}(React.Component);
DraggerHandler.contextTypes = {
dragSourceCreator: PropTypes.func,
dragHandlerType: PropTypes.string,
dragCursor: PropTypes.string
};
DraggerHandler.propTypes = {
wrapTag: PropTypes.string
};
DraggerHandler.defaultProps = {
wrapTag: 'div'
};
var Draggable$1 = DraggableWrapper;
var Dragger$1 = Wrapper;
var DraggerContext = _DraggerContext;
var DraggerHandler$1 = DraggerHandler;
var index = {
Draggable: Draggable$1,
Dragger: Dragger$1,
DraggerContext: DraggerContext,
DraggerHandler: DraggerHandler$1
};
exports.Draggable = Draggable$1;
exports.Dragger = Dragger$1;
exports.DraggerContext = DraggerContext;
exports.DraggerHandler = DraggerHandler$1;
exports['default'] = index;
Object.defineProperty(exports, '__esModule', {
value: true
});
})));
//# sourceMappingURL=ant-dragger.js.map