wix-style-react
Version:
wix-style-react
144 lines (142 loc) • 5.77 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import shallowEqual from 'shallowequal';
import DraggableSource from './components/DraggableSource';
import DraggableTarget from './components/DraggableTarget';
import DraggableManager from './components/DraggableManager';
export class Draggable extends React.Component {
constructor() {
super(...arguments);
this.state = {
delayed: false,
};
this.delayTimer = null;
this.resetDelayState = () => {
if (!!this.props.delay) {
this.setState({ delayed: false });
this.resetDelayTimer();
}
};
this.resetDelayTimer = () => {
clearTimeout(this.delayTimer);
this.delayTimer = null;
};
this.countDelay = () => {
if (!!this.props.delay) {
this.setState({ delayed: true });
this.resetDelayTimer();
this.delayTimer = setTimeout(() => this.setState({ delayed: false }), this.props.delay);
}
};
this.onDragStart = ({ id, index, containerId, groupName, item }) => {
if (this.props.onDragStart) {
this.props.onDragStart({ id, index, containerId, groupName, item });
}
this.resetDelayTimer();
};
this.onDragEnd = ({ id, index, containerId, groupName, item }) => {
if (this.props.onDragEnd) {
this.props.onDragEnd({ id, index, containerId, groupName, item });
}
this.resetDelayState();
};
this.canDrag = ({ id, index, containerId, groupName, item }) => {
const canDragByDelay = !!this.props.delay ? !this.state.delayed : true;
const propsCanDrag = this.props.canDrag
? this.props.canDrag({
id,
index,
containerId,
groupName,
item,
})
: true;
if (!canDragByDelay) {
this.resetDelayState();
}
return canDragByDelay && propsCanDrag;
};
}
shouldComponentUpdate({ listOfPropsThatAffectItems, ...nextProps }, nextState) {
const { listOfPropsThatAffectItems: prevListOfPropsThatAffectItems, ...prevProps } = this.props;
if (!shallowEqual(nextProps, prevProps) ||
!shallowEqual(listOfPropsThatAffectItems, prevListOfPropsThatAffectItems)) {
return true;
}
if (!shallowEqual(nextState, this.state)) {
return true;
}
return false;
}
componentWillUnmount() {
this.resetDelayTimer();
}
render() {
const { hasDragged, ...restProps } = this.props;
return (React.createElement(DraggableTarget, { ...restProps },
React.createElement("div", { onMouseDown: this.countDelay, onMouseUp: this.resetDelayState, "data-hook": "delay-wrapper" },
React.createElement(DraggableSource, { ...restProps, ignoreMouseEvents: hasDragged, onDragStart: this.onDragStart, onDragEnd: this.onDragEnd, canDrag: this.canDrag, delayed: !!this.props.delay && this.state.delayed }))));
}
}
Draggable.defaultProps = {
droppable: true,
};
Draggable.propTypes = {
/** indicates if element can be drop at this place */
droppable: PropTypes.bool,
/** decide whether to render a handle using `connectHandle` (see below) */
withHandle: PropTypes.bool,
/** uniq id of container that contain current draggable item */
containerId: PropTypes.string,
/* name of group between inside of each dnd is allowed */
groupName: PropTypes.string,
/* custom renderer for item */
renderItem: PropTypes.func,
/* position of item in container items array */
index: PropTypes.number,
/* uniq id of an item */
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
/* model that represent item */
item: PropTypes.object,
/** callback when item was moved out from current container to another container */
onMoveOut: PropTypes.func,
/** callback when item was dropped in a new location */
onDrop: PropTypes.func,
/** callback when item is hovered*/
onHover: PropTypes.func,
/** callback for drag start */
onDragStart: PropTypes.func,
/** callback for drag end */
onDragEnd: PropTypes.func,
/** visual positioning shifting for an element (transform: translate) without moving it from its real position at DOM (left, top) */
shift: PropTypes.arrayOf(PropTypes.number),
/** flag that indicates that there's an item being dragged */
hasDragged: PropTypes.bool,
/** sets draggable item node & additional info for animation positions calculations */
setWrapperNode: PropTypes.func,
/** animation duration in ms, default = 0 - disabled */
animationDuration: PropTypes.number,
/** animation timing function, default = linear */
animationTiming: PropTypes.string,
/** callback that could prevent item from dragging */
canDrag: PropTypes.func,
delay: PropTypes.number,
/**
In case that you are using some external props inside of renderItems method,
you need to define them here.
renderItem = ({ item }) => <div key={item.id}>{this.props.myAwesomeProp}</div>
render() {
return (
<SortableListBase
...
listOfPropsThatAffectItems={[this.props.myAwesomeProp]}
/>
)
}
*/
listOfPropsThatAffectItems: PropTypes.array,
};
Draggable.Item = Draggable;
Draggable.Manager = DraggableManager;
export default Draggable;
//# sourceMappingURL=Draggable.js.map