react-flexigrid
Version:
A React table component designed to allow presenting millions of rows of data.
467 lines (401 loc) • 13.7 kB
JavaScript
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import _extends from 'babel-runtime/helpers/extends';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
/* eslint-disable react/require-default-props */
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import propTypes from './struct/propTypes';
import MouseMoveTracker from './dom/MouseMoveTracker';
import { shallowEqual, clamp, cancelAnimationFrame, requestAnimationFrame } from './utils';
import FlexiGridCell from './FlexiGridCell';
var FlexiGridColumnReorderHandler = function (_React$Component) {
_inherits(FlexiGridColumnReorderHandler, _React$Component);
function FlexiGridColumnReorderHandler(props) {
_classCallCheck(this, FlexiGridColumnReorderHandler);
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));
_this.onColumnReordering = function (deltaX) {
if (deltaX !== 0) {
var state = _this.cache || _this.state;
var newLeft = state.delta + deltaX;
var newFixedLeft = clamp(newLeft, _this.state.minLeft, _this.state.maxLeft);
_this.cache = {
movingLeft: deltaX < 0,
left: newFixedLeft,
delta: newLeft
};
}
};
_this.onColumnReordered = function () {
var targetKey = _this.cache && _this.cache.targetKey;
cancelAnimationFrame(_this.frameId);
_this.cache = null;
_this.frameId = null;
_this.animating = false;
_this.mouseMoveTracker.release();
if (_this.props.onColumnReordered) {
_this.props.onColumnReordered(targetKey);
}
};
_this.updateState = function () {
if (_this.animating) {
_this.frameId = requestAnimationFrame(_this.updateState);
}
if (_this.cache) {
var _this$props = _this.props,
column = _this$props.column,
targets = _this$props.targets,
factor = _this$props.factor;
var _this$cache = _this.cache,
left = _this$cache.left,
movingLeft = _this$cache.movingLeft;
var right = left + column.width;
var currentTarget = null;
var tryLeftSide = function tryLeftSide() {
targets.some(function (target) {
if (target.key !== column.key && left > target.left && left < target.left + target.width * factor) {
currentTarget = {
targetKey: target.key,
targetSortable: _this.sortable !== false,
targetPosition: target.left,
isLeftTarget: true,
visible: target.leftSideVisible
};
return true;
}
return false;
});
};
var tryRightSide = function tryRightSide() {
for (var i = targets.length - 1; i >= 0; i -= 1) {
var target = targets[i];
if (target.key !== column.key && right < target.left + target.width && right > target.left + target.width * (1 - factor)) {
currentTarget = {
targetKey: target.key,
targetSortable: _this.sortable !== false,
targetPosition: target.left + target.width,
isLeftTarget: false,
visible: target.rightSideVisible
};
break;
}
}
};
if (movingLeft) {
tryLeftSide();
} else {
tryRightSide();
}
if (!currentTarget) {
if (movingLeft) {
tryRightSide();
} else {
tryLeftSide();
}
}
if (!currentTarget) {
currentTarget = {
targetKey: null,
targetPosition: 0,
isLeftTarget: true
};
}
if (!currentTarget.visible) {
currentTarget.targetKey = null;
}
_this.cache = _extends({}, _this.cache, currentTarget);
_this.setState(_this.cache);
if (_this.props.onColumnReordering) {
_this.props.onColumnReordering({
targetKey: currentTarget.targetKey,
position: left,
movingLeft: movingLeft
});
}
}
};
_this.state = {
minLeft: 0,
maxLeft: 0,
left: 0
};
_this.cache = null;
_this.animating = false;
return _this;
}
FlexiGridColumnReorderHandler.prototype.componentDidMount = function componentDidMount() {
this.mouseMoveTracker = new MouseMoveTracker(document.body, this.onColumnReordering, this.onColumnReordered);
};
FlexiGridColumnReorderHandler.prototype.componentWillReceiveProps = function componentWillReceiveProps(props) {
if (props.initialEvent && !this.mouseMoveTracker.isDragging()) {
this.mouseMoveTracker.capture(props.initialEvent);
var column = props.column,
targets = props.targets,
offsetLeft = props.offsetLeft;
var minLeft = targets.length ? targets[0].left : offsetLeft;
var maxLeft = targets.length ? targets[targets.length - 1].left + targets[targets.length - 1].width - column.width : offsetLeft;
this.setState({
minLeft: minLeft,
maxLeft: maxLeft,
left: offsetLeft,
delta: offsetLeft,
targetKey: null,
targetPosition: 0
});
this.cache = null;
this.animating = true;
this.frameId = requestAnimationFrame(this.updateState);
}
};
FlexiGridColumnReorderHandler.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) {
return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
};
FlexiGridColumnReorderHandler.prototype.componentWillUnmount = function componentWillUnmount() {
this.mouseMoveTracker.release();
this.mouseMoveTracker = null;
};
FlexiGridColumnReorderHandler.prototype.renderDropTargets = function renderDropTargets() {
var targets = this.props.targets;
return (targets || []).map(function (_ref) {
var key = _ref.key,
style = _objectWithoutProperties(_ref, ['key']);
return React.createElement('div', {
key: key,
style: style,
className: 'drop-target'
});
});
};
FlexiGridColumnReorderHandler.prototype.renderSourceMask = function renderSourceMask() {
var _props = this.props,
column = _props.column,
columnHeight = _props.columnHeight,
borderSize = _props.borderSize,
offsetLeft = _props.offsetLeft,
offsetTop = _props.offsetTop;
return column ? React.createElement('div', {
className: 'source-mask',
style: {
left: offsetLeft,
top: offsetTop,
height: columnHeight - borderSize,
width: column.width - borderSize
}
}) : null;
};
FlexiGridColumnReorderHandler.prototype.renderHeaderMergedCells = function renderHeaderMergedCells(height, left, column) {
var _props2 = this.props,
prefixCls = _props2.prefixCls,
headerRowHeight = _props2.headerRowHeight;
var children = column.children,
width = column.width,
title = column.title,
key = column.key,
align = column.align;
var cellProps = {
prefixCls: prefixCls,
width: width,
height: headerRowHeight,
left: 0,
render: title,
align: align || 'center'
};
return React.createElement(
'div',
{
key: key + '-merged-cells-wrap',
className: prefixCls + '-header-merged-cells-wrap',
style: { width: width, height: height, left: left }
},
React.createElement(FlexiGridCell, cellProps),
React.createElement(
'div',
{
key: key + '-merged-cells',
className: prefixCls + '-header-merged-cells',
style: {
width: width,
height: height - headerRowHeight,
top: headerRowHeight
}
},
this.renderHeaderCells(children, height - headerRowHeight)
)
);
};
FlexiGridColumnReorderHandler.prototype.renderHeaderCells = function renderHeaderCells(columns, height) {
var _this2 = this;
var prefixCls = this.props.prefixCls;
var left = 0;
return columns.map(function (column) {
var children = column.children,
width = column.width,
title = column.title,
key = column.key,
align = column.align;
var ret = void 0;
if (children) {
ret = _this2.renderHeaderMergedCells(height, left, column);
} else {
var cellProps = {
key: key,
prefixCls: prefixCls,
width: width,
height: height,
left: left,
align: align,
render: title
};
ret = React.createElement(FlexiGridCell, cellProps);
}
left += width;
return ret;
});
};
FlexiGridColumnReorderHandler.prototype.renderDragKnob = function renderDragKnob(column, height, offsetLeft, offsetTop) {
var _props3 = this.props,
prefixCls = _props3.prefixCls,
knobSize = _props3.knobSize;
var style = {
top: offsetTop,
left: offsetLeft,
width: knobSize,
height: height
};
var className = classNames(prefixCls + '-reorder-knob', {
active: column === this.props.column
});
return React.createElement('div', {
key: column.key,
style: style,
className: className
});
};
FlexiGridColumnReorderHandler.prototype.renderDragKnobs = function renderDragKnobs(columns, height, offsetLeft, offsetTop) {
var _this3 = this;
var headerRowHeight = this.props.headerRowHeight;
var knobs = [];
var left = offsetLeft;
columns.forEach(function (column) {
if (column.children) {
knobs.push.apply(knobs, [_this3.renderDragKnob(column, headerRowHeight, left, offsetTop)].concat(_this3.renderDragKnobs(column.children, height - headerRowHeight, left, offsetTop + headerRowHeight)));
} else {
knobs.push(_this3.renderDragKnob(column, height, left, offsetTop));
}
left += column.width;
});
return knobs;
};
FlexiGridColumnReorderHandler.prototype.renderDragProxy = function renderDragProxy() {
if (this.props.column) {
var left = this.state.left;
var _props4 = this.props,
column = _props4.column,
columnHeight = _props4.columnHeight,
offsetTop = _props4.offsetTop;
return React.createElement(
'div',
{
className: 'drag-proxy',
style: {
width: column.width,
height: columnHeight,
top: offsetTop,
left: left
}
},
this.renderHeaderCells([column], columnHeight),
this.renderDragKnobs([column], columnHeight, 0, 0)
);
}
return null;
};
FlexiGridColumnReorderHandler.prototype.renderDropMarker = function renderDropMarker() {
var _props5 = this.props,
columnHeight = _props5.columnHeight,
offsetTop = _props5.offsetTop,
width = _props5.width;
var _state = this.state,
targetKey = _state.targetKey,
targetPosition = _state.targetPosition,
isLeftTarget = _state.isLeftTarget,
targetSortable = _state.targetSortable;
if (targetKey) {
var className = classNames('target-marker', {
'is-left': isLeftTarget,
'is-right': !isLeftTarget,
'fix-position-sortable': !isLeftTarget && this.props.sortable && targetSortable
});
var style = {
height: columnHeight,
top: offsetTop
};
if (isLeftTarget) {
style.left = targetPosition;
} else {
style.right = width - targetPosition;
}
return React.createElement('div', { className: className, style: style });
}
return null;
};
FlexiGridColumnReorderHandler.prototype.render = function render() {
var _props6 = this.props,
prefixCls = _props6.prefixCls,
visible = _props6.visible,
width = _props6.width,
height = _props6.height;
var className = classNames(prefixCls + '-reorder-handler', {
visible: visible
});
var wrapStyle = {
width: width,
height: height
};
return React.createElement(
'div',
{ className: className, style: wrapStyle },
this.renderDropTargets(),
this.renderSourceMask(),
this.renderDropMarker(),
this.renderDragProxy()
);
};
return FlexiGridColumnReorderHandler;
}(React.Component);
FlexiGridColumnReorderHandler.propTypes = {
prefixCls: PropTypes.string,
column: propTypes.column,
targets: propTypes.dropTarget,
visible: PropTypes.bool,
sortable: PropTypes.bool,
factor: PropTypes.number,
width: PropTypes.number,
height: PropTypes.number,
headerRowHeight: PropTypes.number,
columnHeight: PropTypes.number,
offsetLeft: PropTypes.number,
offsetTop: PropTypes.number,
borderSize: PropTypes.number,
knobSize: PropTypes.number,
initialEvent: propTypes.domEvent,
onColumnReordering: PropTypes.func,
onColumnReordered: PropTypes.func
};
FlexiGridColumnReorderHandler.defaultProps = {
visible: false,
factor: 3 / 4,
width: 0,
height: 0,
headerRowHeight: 0,
columnHeight: 0,
offsetLeft: 0,
offsetTop: 0,
borderSize: 0,
knobSize: 0,
targets: [],
initialEvent: null
};
export default FlexiGridColumnReorderHandler;