@bigfishtv/cockpit
Version:
107 lines (94 loc) • 2.83 kB
JavaScript
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import classnames from 'classnames'
import { DragSource, DropTarget } from 'react-dnd'
import * as DragTypes from '../../constants/DragTypes'
import _CellControl from './CellControl'
import DefaultIcon from '../Icon'
import Spinner from '../Spinner'
// we define this because react-docgen fails when defaultProp directly references an imported component
const DefaultCellControl = props => <_CellControl {...props} />
const cellSource = {
beginDrag(props) {
return {
id: props.id,
}
},
}
const cellTarget = {
hover(props, monitor, component) {
const ownId = props.id
const draggedId = monitor.getItem().id
if (draggedId === ownId) return
const ownIndex = props.index
const draggedIndex = monitor.getItem().index
const boundingRect = ReactDOM.findDOMNode(component).getBoundingClientRect()
const clientOffset = monitor.getClientOffset()
const ownMiddleY = (boundingRect.bottom - boundingRect.top) / 2
const offsetY = clientOffset.y - boundingRect.top
if (draggedIndex < ownIndex && offsetY < ownMiddleY) return
if (draggedIndex > ownIndex && offsetY > ownMiddleY) return
props.onMove(draggedId, ownId)
},
}
/**
* Default Cell component used in things like Tree and RepeatableFieldset
*/
(DragTypes.CELL, cellTarget, connect => ({
connectDropTarget: connect.dropTarget(),
}))
(DragTypes.CELL, cellSource, (connect, monitor) => ({
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging(),
}))
export default class Cell extends Component {
static propTypes = {
title: PropTypes.node,
CellControl: PropTypes.func,
Icon: PropTypes.node,
icon: PropTypes.string,
className: PropTypes.string,
reorderable: PropTypes.bool,
}
static defaultProps = {
loading: false,
CellControl: DefaultCellControl,
}
render() {
const {
reorderable,
loading,
onEdit,
CellControl,
Icon,
icon,
connectDragSource,
connectDropTarget,
isDragging,
className,
} = this.props
const returnNode = (
<div
className={classnames('cell', className, { dragging: isDragging, reorderable: reorderable })}
onDoubleClick={onEdit}>
{Icon ? (
<div className="cell-icon">{Icon}</div>
) : (
icon && (
<div className="cell-icon">
<DefaultIcon name={icon} />
</div>
)
)}
{loading && <Spinner color="#9696A3" spinnerName="circle" />}
<div className="cell-content">{this.props.title}</div>
<div className="cell-control">
{CellControl ? <CellControl {...this.props} /> : <div style={{ height: 30, display: 'inline-block' }} />}
</div>
</div>
)
if (reorderable) return connectDragSource(connectDropTarget(returnNode))
else return returnNode
}
}