UNPKG

optimizely-oui

Version:

Optimizely's Component Library.

128 lines (113 loc) 3.98 kB
import classNames from "classnames"; import Immutable from "immutable"; import PropTypes from "prop-types"; import React from "react"; import { DragSource } from "react-dnd"; import { getEmptyImage } from "react-dnd-html5-backend"; import SortTarget from "../SortTarget"; import types from "../draggableTypes"; /** * handleBeginDrag * @description Begins drag interaction for the current item * @param {Object} props - SortableItem props * @returns {Object} Information passed to item renderer + sort target upon drag */ function handleBeginDrag(props) { const { item, position, id } = props; return { data: item, id, position, type: "item", }; } /** * handleEndDrag * @description Ends drag interaction for the current item * @param {Object} props - SortableItem props */ function handleEndDrag(props) { props.endDrag(); } /** * isItemBeingDragged * @description Calculates whether the current item is being dragged * @param {Object} props - SortableItem props * @param {Object} monitor - Interface to interact with react-dnd state * @returns {Boolean} Whether or not the current item is being dragged */ function isItemBeingDragged(props, monitor) { return !monitor.didDrop() && monitor.getItem().id === props.id && monitor.getItem().type === "item"; } class SortableItem extends React.Component { static propTypes = { baseTestSection: PropTypes.string.isRequired, connectDragPreview: PropTypes.func.isRequired, connectDragSource: PropTypes.func.isRequired, endDrag: PropTypes.func.isRequired, id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, isDragPreview: PropTypes.bool, isDragging: PropTypes.bool.isRequired, item: PropTypes.instanceOf(Immutable.Map).isRequired, onMove: PropTypes.func.isRequired, position: PropTypes.arrayOf(PropTypes.number).isRequired, render: PropTypes.func.isRequired, }; static defaultProps = { isDragPreview: false, }; componentDidMount() { const { connectDragPreview } = this.props; connectDragPreview(getEmptyImage(), { captureDragState: true, }); } render() { const { baseTestSection, connectDragSource, isDragging, isDragPreview, item, position, onMove, render } = this.props; const targetPosition = [...position.slice(0, -1), position[position.length - 1] + 1]; const className = classNames({ "oui-sortable__drag-placeholder": !isDragPreview && isDragging, "oui-sortable__item": true, "pointer-events--none": !isDragPreview && isDragging, }); const renderedItem = render({ baseTestSection, connectDragSource, item, isDragging, isDragPreview, position, }); const testSectionName = isDragPreview ? "item-preview" : "item"; const testSectionId = position.join("-"); const testSection = `${baseTestSection}-${testSectionName}-${testSectionId}`; return ( <React.Fragment> <li className={className} data-test-section={testSection}> {renderedItem} </li> <SortTarget baseTestSection={baseTestSection} onMove={onMove} ownerId={item.get("id")} ownerType="item" position={targetPosition} /> </React.Fragment> ); } } export default DragSource( types.item, { beginDrag: handleBeginDrag, endDrag: handleEndDrag, isDragging: isItemBeingDragged, }, (connect, monitor) => ({ connectDragPreview: connect.dragPreview(), connectDragSource: connect.dragSource(), isDragging: monitor.isDragging(), }) )(SortableItem);