react-flexigrid
Version:
A React table component designed to allow presenting millions of rows of data.
1,218 lines (1,028 loc) • 44.5 kB
JavaScript
import _extends from 'babel-runtime/helpers/extends';
import _Number$MAX_SAFE_INTEGER from 'babel-runtime/core-js/number/max-safe-integer';
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 invariant from 'invariant';
import classNames from 'classnames';
import propTypes from './struct/propTypes';
import WheelHandler from './dom/WheelHandler';
import TouchHandler from './dom/TouchHandler';
import Scrollbar from './Scrollbar';
import VerticalScrollHelper from './FlexiGridVerticalScrollHelper';
import HorizontalScrollHelper from './FlexiGridHorizontalScrollHelper';
import FlexiGridColumnBuffer from './FlexiGridColumnBuffer';
import FlexiGridHeader from './FlexiGridHeader';
import FlexiGridBody from './FlexiGridBody';
import FlexiGridShadowTop from './FlexiGridShadowTop';
import FlexiGridShadowLeft from './FlexiGridShadowLeft';
import FlexiGridShadowRight from './FlexiGridShadowRight';
import FlexiGridShadowBottom from './FlexiGridShadowBottom';
import FlexiGridSortKnobs from './FlexiGridSortKnobs';
import FlexiGridColumnResizeKnobs from './FlexiGridColumnResizeKnobs';
import FlexiGridColumnReorderKnobs from './FlexiGridColumnReorderKnobs';
import FlexiGridColumnResizeHandler from './FlexiGridColumnResizeHandler';
import FlexiGridColumnReorderHandler from './FlexiGridColumnReorderHandler';
import { debounce, clamp, deepEqual } from './utils';
import { getColumnsWidth, parseColumns, shrinkColumnsWidth } from './FlexiGridColumnHelper';
var FlexiGrid = function (_React$Component) {
_inherits(FlexiGrid, _React$Component);
function FlexiGrid() {
var _temp, _this, _ret;
_classCallCheck(this, FlexiGrid);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.onScroll = function (deltaX, deltaY) {
if (!_this.scrolling) {
_this.didScrollStart();
}
if (Math.abs(deltaY) > Math.abs(deltaX) && _this.state.showScrollbarY) {
_this.doVerticalScroll(deltaY, true);
} else if (deltaX && _this.state.showScrollbarX) {
_this.doHorizontalScroll(deltaX, true);
}
_this.didScrollStop();
}, _this.onHorizontalScroll = function (scrollX) {
if (scrollX === _this.state.scrollX) {
return;
}
if (!_this.scrolling) {
_this.didScrollStart();
}
_this.doHorizontalScroll(scrollX, false);
_this.didScrollStop();
}, _this.onVerticalScroll = function (scrollY) {
if (scrollY === _this.state.scrollY) {
return;
}
if (!_this.scrolling) {
_this.didScrollStart();
}
_this.doVerticalScroll(scrollY, false);
_this.didScrollStop();
}, _this.shouldHandleWheelX = function (delta) {
if (!_this.state.showScrollbarX || delta === 0) {
return false;
}
delta = Math.round(delta); // eslint-disable-line
if (delta === 0) {
return false;
}
return delta < 0 && _this.state.scrollX > 0 || delta >= 0 && _this.state.scrollX < _this.state.maxScrollX;
}, _this.shouldHandleWheelY = function (delta) {
if (!_this.state.showScrollbarY || delta === 0) {
return false;
}
delta = Math.round(delta); // eslint-disable-line
if (delta === 0) {
return false;
}
return delta < 0 && _this.state.scrollY > 0 || delta >= 0 && _this.state.scrollY < _this.state.maxScrollY;
}, _this.shouldHandleTouchX = function (delta) {
return _this.props.touchScrollEnabled && _this.shouldHandleWheelX(delta);
}, _this.shouldHandleTouchY = function (delta) {
return _this.props.touchScrollEnabled && _this.shouldHandleWheelY(delta);
}, _this.onColumnResize = function (_ref, e) {
var column = _ref.column,
knobSize = _ref.knobSize,
left = _ref.left,
top = _ref.top,
rtl = _ref.rtl,
adjustKnob = _ref.adjustKnob;
// eslint-disable-line
var _this$state = _this.state,
headerHeight = _this$state.headerHeight,
bodyHeight = _this$state.bodyHeight;
_this.columnResizingData = {
prefixCls: _this.props.prefixCls,
rtl: rtl,
offsetLeft: left,
offsetTop: top,
knobSize: knobSize,
adjustKnob: adjustKnob,
initialWidth: column.width,
height: headerHeight + bodyHeight,
minWidth: column.minWidth || 0,
maxWidth: column.maxWidth || _Number$MAX_SAFE_INTEGER,
columnKey: column.key,
initialEvent: {
clientX: e.clientX,
clientY: e.clientY,
preventDefault: function preventDefault() {}
},
onColumnResizing: _this.onColumnResizing,
onColumnResized: _this.onColumnResized
};
if (_this.props.onColumnResize) {
_this.props.onColumnResize(column.key, column.width);
}
_this.setNextState({ columnResizingKey: column.key });
}, _this.onColumnResizing = function (columnWidth, columnKey) {
if (_this.props.onColumnResizing) {
_this.props.onColumnResizing(columnKey, columnWidth);
}
}, _this.onColumnResized = function (columnWidth, columnKey) {
if (_this.props.onColumnResized) {
_this.props.onColumnResized(columnKey, columnWidth);
}
if (!_this.columnWidthMap) {
_this.columnWidthMap = {};
}
_this.columnWidthMap[columnKey] = columnWidth;
_this.columnResizingData = null;
var nextState = _this.calculateState(_this.props, _this.state);
_this.setNextState(_extends({}, nextState, _this.getStateAfterHorizontalScroll(nextState.scrollX, false), {
columnResizingKey: null
}));
}, _this.onColumnReorder = function (_ref2, e) {
var column = _ref2.column;
_this.columnReorderingData = {
column: column,
initialEvent: {
clientX: e.clientX,
clientY: e.clientY,
preventDefault: function preventDefault() {}
},
onColumnReordering: _this.onColumnReordering,
onColumnReordered: _this.onColumnReordered
};
if (_this.props.onColumnReorder) {
_this.props.onColumnReorder(column.key);
}
_this.setNextState({ columnReorderingKey: column.key });
}, _this.onColumnReordering = function (_ref3) {
var targetKey = _ref3.targetKey,
movingLeft = _ref3.movingLeft,
position = _ref3.position;
var column = _this.columnReorderingData.column;
if (!column.fixed) {
var _this$props = _this.props,
dragScrollSpeed = _this$props.dragScrollSpeed,
dragScrollBuffer = _this$props.dragScrollBuffer;
var _this$state2 = _this.state,
bodyWidth = _this$state2.bodyWidth,
scrollX = _this$state2.scrollX,
maxScrollX = _this$state2.maxScrollX,
columnData = _this$state2.columnData;
var leftFixedColumns = columnData.leftFixedColumns,
rightFixedColumns = columnData.rightFixedColumns;
// auto scroll on moving
var scrollTo = scrollX;
if (movingLeft) {
if (scrollX > 0 && position < getColumnsWidth(leftFixedColumns) + dragScrollBuffer) {
scrollTo = Math.max(scrollX - dragScrollSpeed, 0);
}
} else if (scrollX < maxScrollX && position + column.width > bodyWidth - getColumnsWidth(rightFixedColumns) - dragScrollBuffer) {
scrollTo = Math.min(scrollX + dragScrollSpeed, maxScrollX);
}
if (scrollTo !== scrollX) {
_this.doHorizontalScroll(scrollTo, false);
}
}
if (_this.props.onColumnReordering) {
_this.props.onColumnReordering(column.key, targetKey);
}
}, _this.onColumnReordered = function (targetColumnKey) {
if (!_this.columnOrderMap) {
_this.columnOrderMap = {};
}
var column = _this.columnReorderingData.column;
var siblings = _this.getColumnSiblings(column);
var sourceColumnKey = column.key;
siblings.forEach(function (_ref4, index) {
var key = _ref4.key;
if (key === targetColumnKey) {
_this.columnOrderMap[sourceColumnKey] = index;
} else if (key === sourceColumnKey) {
_this.columnOrderMap[targetColumnKey] = index;
}
});
if (_this.props.onColumnReordered) {
_this.props.onColumnReordered(sourceColumnKey, targetColumnKey);
}
if (_this.props.onHorizontalScroll && _this.columnReorderingData.scrollX !== _this.state.scrollX) {
_this.props.onHorizontalScroll(_this.state.scrollX);
}
_this.setNextState(_extends({}, _this.calculateState(_this.props, _this.state), {
columnReorderingKey: null
}));
_this.columnReorderingData = null;
}, _this.onColumnSort = function (column, type) {
if (_this.props.onColumnSort) {
_this.props.onColumnSort(column, type);
}
}, _temp), _possibleConstructorReturn(_this, _ret);
}
FlexiGrid.prototype.componentWillMount = function componentWillMount() {
this.didScrollStop = debounce(this.didScrollStopSync, 200, this);
this.wheelHandler = new WheelHandler(this.onScroll, this.shouldHandleWheelX, this.shouldHandleWheelY, this.props.stopScrollPropagation);
this.touchHandler = new TouchHandler(this.onScroll, this.shouldHandleTouchX, this.shouldHandleTouchY, this.props.stopScrollPropagation);
this.setNextState(this.calculateState(this.props));
};
FlexiGrid.prototype.componentDidMount = function componentDidMount() {
this.reportContentHeight();
};
FlexiGrid.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
if (this.props.ownerHeight !== nextProps.ownerHeight || this.props.scrollTop !== nextProps.scrollTop || this.props.scrollLeft !== nextProps.scrollLeft) {
this.didScrollStart();
}
this.didScrollStop.reset();
this.didScrollStopSync();
this.setNextState(this.calculateState(nextProps, this.state));
};
FlexiGrid.prototype.componentDidUpdate = function componentDidUpdate() {
this.reportContentHeight();
};
FlexiGrid.prototype.componentWillUnmount = function componentWillUnmount() {
this.wheelHandler = null;
this.touchHandler = null;
// cancel any pending debounced scroll handling and handle immediately
this.didScrollStop.reset();
this.didScrollStopSync();
};
FlexiGrid.prototype.getStateAfterHorizontalScroll = function getStateAfterHorizontalScroll(scrollX, relative) {
var scrollState = relative ? this.horizontalScrollHelper.scrollBy(Math.round(scrollX)) : this.horizontalScrollHelper.scrollTo(Math.round(scrollX));
var onHorizontalScroll = this.props.onHorizontalScroll;
if (onHorizontalScroll) {
onHorizontalScroll(scrollState.position);
}
var columnData = this.state.columnData;
var contentWidth = columnData.leftFixedColumnsWidth + columnData.rightFixedColumnsWidth + scrollState.contentWidth;
var maxScrollX = Math.max(0, contentWidth - this.state.bodyWidth);
var scrollableColumnsToRender = this.columnBuffer.getColumns(scrollState.index, scrollState.offset);
return {
firstColumnIndex: scrollState.index,
firstColumnOffset: scrollState.offset,
scrollX: scrollState.position,
maxScrollX: maxScrollX,
scrollableColumnsToRender: scrollableColumnsToRender
};
};
FlexiGrid.prototype.doHorizontalScroll = function doHorizontalScroll(scrollX, relative) {
// eslint-disable-line
this.setNextState(this.getStateAfterHorizontalScroll(scrollX, relative));
};
FlexiGrid.prototype.doVerticalScroll = function doVerticalScroll(scrollY, relative) {
// eslint-disable-line
var scrollState = relative ? this.verticalScrollHelper.scrollBy(Math.round(scrollY)) : this.verticalScrollHelper.scrollTo(Math.round(scrollY));
var onVerticalScroll = this.props.onVerticalScroll;
if (onVerticalScroll) {
onVerticalScroll(scrollState.position);
}
var maxScrollY = Math.max(0, scrollState.contentHeight - this.state.bodyHeight);
this.setNextState({
firstRowIndex: scrollState.index,
firstRowOffset: scrollState.offset,
contentHeight: scrollState.contentHeight,
scrollY: scrollState.position,
maxScrollY: maxScrollY
});
};
FlexiGrid.prototype.didScrollStart = function didScrollStart() {
// eslint-disable-line
if (this.scrolling) {
return;
}
this.scrolling = true;
if (this.props.onScrollStart) {
this.props.onScrollStart(this.state.scrollX, this.state.scrollY, this.state.firstRowIndex);
}
};
FlexiGrid.prototype.didScrollStopSync = function didScrollStopSync() {
if (!this.scrolling) {
return;
}
this.scrolling = false;
this.setNextState({ redraw: true });
if (this.props.onScrollEnd) {
this.props.onScrollEnd(this.state.scrollX, this.state.scrollY, this.state.firstRowIndex);
}
};
FlexiGrid.prototype.reportContentHeight = function reportContentHeight() {
var requiredHeight = this.state.contentHeight + this.state.reservedHeight;
var contentHeight = void 0;
if (this.state.useMaxHeight && this.props.maxHeight > requiredHeight) {
contentHeight = requiredHeight;
} else if (this.state.height > requiredHeight && this.props.ownerHeight) {
contentHeight = Math.max(requiredHeight, this.props.ownerHeight);
} else {
contentHeight = this.state.height + this.state.maxScrollY;
}
if (contentHeight !== this.contentHeight && this.props.onContentHeightChange) {
this.props.onContentHeightChange(contentHeight);
}
this.contentHeight = contentHeight;
};
FlexiGrid.prototype.isColumnResizing = function isColumnResizing() {
return this.state.columnResizingKey != null;
};
FlexiGrid.prototype.isColumnReordering = function isColumnReordering() {
return this.state.columnReorderingKey != null;
};
FlexiGrid.prototype.setNextState = function setNextState(nextState) {
var _this2 = this;
var oldColumnData = this.state && this.state.columnData;
var scrollableColumnsToRender = nextState.scrollableColumnsToRender,
columnData = nextState.columnData;
var leftFixedColumnsUpdated = false;
var scrollableColumnsUpdated = false;
var rightFixedColumnsUpdated = false;
var scrollableColumnsToRenderUpdated = false;
if (columnData && oldColumnData) {
leftFixedColumnsUpdated = !(columnData.leftFixedColumns === oldColumnData.leftFixedColumns || deepEqual(columnData.leftFixedColumns, oldColumnData.leftFixedColumns));
scrollableColumnsUpdated = !(columnData.scrollableColumns === oldColumnData.scrollableColumns || deepEqual(columnData.scrollableColumns, oldColumnData.scrollableColumns));
rightFixedColumnsUpdated = !(columnData.rightFixedColumns === oldColumnData.rightFixedColumns || deepEqual(columnData.rightFixedColumns, oldColumnData.rightFixedColumns));
} else if (columnData && !oldColumnData) {
leftFixedColumnsUpdated = true;
scrollableColumnsUpdated = true;
rightFixedColumnsUpdated = true;
}
if (this.state) {
scrollableColumnsToRenderUpdated = !(scrollableColumnsToRender === this.state.scrollableColumnsToRender || deepEqual(scrollableColumnsToRender, this.state.scrollableColumnsToRender));
} else {
scrollableColumnsToRenderUpdated = true;
}
var state = _extends({}, nextState, {
leftFixedColumnsUpdated: leftFixedColumnsUpdated,
scrollableColumnsUpdated: scrollableColumnsUpdated,
rightFixedColumnsUpdated: rightFixedColumnsUpdated,
scrollableColumnsToRenderUpdated: scrollableColumnsToRenderUpdated
});
if (scrollableColumnsToRender) {
var scrollableLeafColumns = columnData ? columnData.scrollableLeafColumns : oldColumnData.scrollableLeafColumns;
var leafColumnsToRender = scrollableColumnsToRender.map(function (index) {
return _extends({}, scrollableLeafColumns[index], {
offsetLeft: _this2.horizontalScrollHelper.getColumnPosition(index)
});
});
var parents = leafColumnsToRender.map(function (item) {
var result = item;
var parent = item.parent;
while (parent) {
result = parent;
parent = result.parent;
}
return result;
});
var columnsToRender = [];
parents.forEach(function (item) {
if (!columnsToRender.includes(item)) {
columnsToRender.push(item);
}
});
state.scrollableColumnsToRender = columnsToRender;
state.scrollableLeafColumnsToRender = leafColumnsToRender;
}
this.setState(state);
};
FlexiGrid.prototype.calculateState = function calculateState() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
var oldState = arguments[1];
invariant(props.height !== undefined || props.maxHeight !== undefined, 'Either height or maxHeight should be specified');
var borderSize = props.bordered ? props.borderSize : 0;
var reservedBorderSize = props.bordered ? 2 * borderSize : 0;
// the width of viewport includes scrollbars
var viewportWidth = props.width - reservedBorderSize;
var columnConfig = {
widthMap: this.columnWidthMap || {},
orderMap: this.columnOrderMap || {},
viewportWidth: viewportWidth
};
if (oldState) {
columnConfig.resizingKey = oldState.columnResizingKey;
columnConfig.reorderingKey = oldState.columnReorderingKey;
}
var columnData = parseColumns(props.columns, columnConfig);
var rowCount = props.data.length;
var rowHeight = props.rowHeight;
var headerRowHeight = props.headerRowHeight;
var headerHeight = columnData.depth * headerRowHeight;
var useMaxHeight = props.height === undefined;
var realUseHeight = useMaxHeight ? props.maxHeight : props.height;
// the height of viewport includes scrollbars
var viewportHeight = realUseHeight - (headerHeight || 0) - (props.footerHeight || 0) - reservedBorderSize;
var firstRowIndex = oldState && oldState.firstRowIndex || 0;
var firstRowOffset = oldState && oldState.firstRowOffset || 0;
var firstColumnIndex = oldState && oldState.firstColumnIndex || 0;
var firstColumnOffset = oldState && oldState.firstColumnOffset || 0;
var scrollX = oldState ? oldState.scrollX : 0;
var scrollY = oldState ? oldState.scrollY : 0;
if (!this.verticalScrollHelper) {
this.verticalScrollHelper = new VerticalScrollHelper(rowCount, props.rowHeight, viewportHeight, props.getRowHeight, props.subRowHeight, props.getSubRowHeight);
}
var oldViewportHeight = this.verticalScrollHelper.viewportHeight;
if (oldState && (rowCount !== oldState.rowCount || props.rowHeight !== oldState.rowHeight || props.height !== oldState.height)) {
this.verticalScrollHelper = new VerticalScrollHelper(rowCount, props.rowHeight, viewportHeight, props.getRowHeight, props.subRowHeight, props.getSubRowHeight);
var scrollState = this.verticalScrollHelper.scrollToRow(firstRowIndex, firstRowOffset);
scrollY = scrollState.position;
firstRowIndex = scrollState.index;
firstRowOffset = scrollState.offset;
} else if (oldState) {
if (props.getRowHeight !== oldState.getRowHeight) {
this.verticalScrollHelper.setRowHeightGetter(props.getRowHeight);
}
if (props.getSubRowHeight !== oldState.getSubRowHeight) {
this.verticalScrollHelper.setSubRowHeightGetter(props.getSubRowHeight);
}
}
// scrollToRow
var oldScrollToRow = oldState ? oldState.scrollToRow : undefined;
if (props.scrollToRow !== undefined && (props.scrollToRow !== oldScrollToRow || viewportHeight !== oldViewportHeight)) {
var _scrollState = this.verticalScrollHelper.scrollRowIntoView(props.scrollToRow);
scrollY = _scrollState.position;
firstRowIndex = _scrollState.index;
firstRowOffset = _scrollState.offset;
}
// scrollTop
var oldScrollTop = oldState ? oldState.scrollTop : undefined;
if (props.scrollTop !== undefined && props.scrollTop !== oldScrollTop) {
var _scrollState2 = this.verticalScrollHelper.scrollTo(props.scrollTop);
scrollY = _scrollState2.position;
firstRowIndex = _scrollState2.index;
firstRowOffset = _scrollState2.offset;
}
// size for content
var contentWidth = getColumnsWidth(columnData.columns);
var contentHeight = this.verticalScrollHelper.getContentHeight();
var isJustFullfill = contentWidth === viewportWidth;
var showScrollbarX = contentWidth > viewportWidth + borderSize;
var showScrollbarY = contentHeight > viewportHeight;
var reservedHeight = props.footerHeight + headerHeight + reservedBorderSize + (showScrollbarX ? Scrollbar.SIZE : 0);
var requiredHeight = contentHeight + reservedHeight;
var reservedColumnWidth = columnData.leftFixedColumnsWidth + columnData.rightFixedColumnsWidth;
var height = Math.round(realUseHeight);
if (useMaxHeight && !showScrollbarY) {
height = requiredHeight;
}
if (showScrollbarY && isJustFullfill) {
shrinkColumnsWidth(columnData, Scrollbar.SIZE);
}
// body's size excludes scrollbars
var bodyWidth = viewportWidth - (showScrollbarY ? Scrollbar.SIZE : 0);
var bodyHeight = height - reservedHeight;
var maxScrollX = Math.max(0, contentWidth - bodyWidth);
var maxScrollY = Math.max(0, contentHeight - bodyHeight);
scrollX = Math.min(scrollX, maxScrollX);
scrollY = Math.min(scrollY, maxScrollY);
this.verticalScrollHelper.setViewportHeight(bodyHeight);
var getScrollableColumnWidth = function getScrollableColumnWidth(index) {
return columnData.scrollableLeafColumns[index].width;
};
var scrollableViewportWidth = bodyWidth - reservedColumnWidth;
if (!this.horizontalScrollHelper) {
this.horizontalScrollHelper = new HorizontalScrollHelper(columnData.scrollableLeafColumns.length, scrollableViewportWidth, getScrollableColumnWidth);
} else {
this.horizontalScrollHelper.setViewportWidth(scrollableViewportWidth);
this.horizontalScrollHelper.setColumnWidthGetter(getScrollableColumnWidth);
}
// scrollToColumn
var oldScrollToColumn = oldState ? oldState.scrollToColumn : undefined;
var scrollToColumn = props.scrollToColumn;
if (scrollToColumn !== undefined && scrollToColumn !== oldScrollToColumn) {
var leftFixedCount = columnData.leftFixedLeafColumns.length;
var scrollableCount = columnData.scrollableLeafColumns.length;
var columnIndex = clamp(scrollToColumn - leftFixedCount, 0, scrollableCount - 1);
var _scrollState3 = this.horizontalScrollHelper.scrollToColumn(columnIndex);
scrollX = _scrollState3.position;
firstColumnIndex = _scrollState3.index;
firstColumnOffset = _scrollState3.offset;
}
// scrollLeft
var oldScrollLeft = oldState ? oldState.scrollLeft : undefined;
if (props.scrollLeft !== undefined && props.scrollLeft !== oldScrollLeft) {
var _scrollState4 = this.horizontalScrollHelper.scrollTo(props.scrollLeft);
scrollX = _scrollState4.position;
firstColumnIndex = _scrollState4.index;
firstColumnOffset = _scrollState4.offset;
}
if (!this.columnBuffer || !oldState || !deepEqual(columnData.scrollableColumns, oldState.scrollableColumns)) {
this.columnBuffer = new FlexiGridColumnBuffer(columnData.scrollableLeafColumns.length, scrollableViewportWidth, getScrollableColumnWidth, props.bufferColumnCount);
}
var scrollableColumnsToRender = this.columnBuffer.getColumns(firstColumnIndex, firstColumnOffset);
// The order of elements in this object metters and bringing bodyHeight,
// height or useGroupHeader to the top can break various features
var newState = {
rowCount: rowCount,
columnData: columnData,
scrollableColumnsToRender: scrollableColumnsToRender,
columnResizingKey: oldState && oldState.columnResizingKey || null,
columnReorderingKey: oldState && oldState.columnReorderingKey || null,
width: props.width,
height: height,
rowHeight: rowHeight,
useMaxHeight: useMaxHeight,
headerHeight: headerHeight,
reservedHeight: reservedHeight,
viewportWidth: viewportWidth,
viewportHeight: viewportHeight,
bodyWidth: bodyWidth,
bodyHeight: bodyHeight,
contentWidth: contentWidth,
contentHeight: contentHeight,
firstRowIndex: firstRowIndex,
firstRowOffset: firstRowOffset,
firstColumnIndex: firstColumnIndex,
firstColumnOffset: firstColumnOffset,
scrollX: scrollX,
scrollY: scrollY,
maxScrollX: maxScrollX,
maxScrollY: maxScrollY,
showScrollbarX: showScrollbarX,
showScrollbarY: showScrollbarY,
isJustFullfill: isJustFullfill,
// store these props for next compare
scrollTop: props.scrollTop,
scrollLeft: props.scrollLeft,
scrollToRow: props.scrollToRow,
scrollToColumn: props.scrollToColumn,
getRowHeight: props.getRowHeight,
getSubRowHeight: props.getSubRowHeight
};
return newState;
};
FlexiGrid.prototype.getColumnReorderingData = function getColumnReorderingData() {
var raw = this.columnReorderingData;
if (raw) {
var column = raw.column;
var _props = this.props,
prefixCls = _props.prefixCls,
headerRowHeight = _props.headerRowHeight,
borderSize = _props.borderSize,
reorderFactor = _props.reorderFactor,
reorderKnobSize = _props.reorderKnobSize;
var _state = this.state,
bodyWidth = _state.bodyWidth,
headerHeight = _state.headerHeight,
bodyHeight = _state.bodyHeight,
columnData = _state.columnData,
scrollX = _state.scrollX;
var leftFixedColumnsWidth = columnData.leftFixedColumnsWidth,
rightFixedColumnsWidth = columnData.rightFixedColumnsWidth;
var maxRight = bodyWidth - rightFixedColumnsWidth;
var offsetTop = (column.depth - 1) * headerRowHeight;
var offsetLeft = column.left;
if (this.state.showScrollbarX) {
if (!column.fixed) {
offsetLeft -= scrollX;
} else if (column.fixed === 'right') {
offsetLeft += bodyWidth - rightFixedColumnsWidth;
}
}
var siblings = this.getColumnSiblings(column);
var targets = [];
var siblingLeft = offsetLeft;
siblings.some(function (item) {
if (item === column) {
return true;
}
siblingLeft -= item.width;
return false;
});
siblings.forEach(function (item) {
targets.push({
left: siblingLeft,
top: offsetTop,
height: headerHeight - offsetTop,
width: item.width,
key: item.key,
leftSideVisible: siblingLeft >= leftFixedColumnsWidth,
rightSideVisible: siblingLeft + item.width <= maxRight
});
siblingLeft += item.width;
});
return _extends({}, raw, {
prefixCls: prefixCls,
width: bodyWidth,
height: headerHeight + bodyHeight,
offsetLeft: offsetLeft,
offsetTop: offsetTop,
targets: targets,
headerRowHeight: headerRowHeight,
columnHeight: headerHeight - offsetTop,
borderSize: borderSize,
scrollX: scrollX,
factor: reorderFactor,
knobSize: reorderKnobSize
});
}
return raw;
};
FlexiGrid.prototype.getColumnSiblings = function getColumnSiblings(column) {
var siblings = column.depth > 1 ? column.parent.children : null;
if (!siblings) {
var columnData = this.state.columnData;
if (column.fixed === 'left') {
siblings = columnData.leftFixedColumns;
} else if (column.fixed === 'right') {
siblings = columnData.rightFixedColumns;
} else {
siblings = columnData.scrollableColumns;
}
}
return siblings;
};
FlexiGrid.prototype.getHeaderAndBodyCommonProps = function getHeaderAndBodyCommonProps() {
var _props2 = this.props,
prefixCls = _props2.prefixCls,
rowHeight = _props2.rowHeight,
bordered = _props2.bordered;
var _state2 = this.state,
columnData = _state2.columnData,
scrollX = _state2.scrollX,
showScrollbarX = _state2.showScrollbarX,
showScrollbarY = _state2.showScrollbarY,
isJustFullfill = _state2.isJustFullfill,
scrollableColumnsToRender = _state2.scrollableColumnsToRender,
scrollableLeafColumnsToRender = _state2.scrollableLeafColumnsToRender,
leftFixedColumnsUpdated = _state2.leftFixedColumnsUpdated,
scrollableColumnsUpdated = _state2.scrollableColumnsUpdated,
rightFixedColumnsUpdated = _state2.rightFixedColumnsUpdated,
scrollableColumnsToRenderUpdated = _state2.scrollableColumnsToRenderUpdated;
var leftFixedColumns = columnData.leftFixedColumns,
scrollableColumns = columnData.scrollableColumns,
rightFixedColumns = columnData.rightFixedColumns,
leftFixedLeafColumns = columnData.leftFixedLeafColumns,
scrollableLeafColumns = columnData.scrollableLeafColumns,
rightFixedLeafColumns = columnData.rightFixedLeafColumns,
leftFixedColumnsWidth = columnData.leftFixedColumnsWidth,
scrollableColumnsWidth = columnData.scrollableColumnsWidth,
rightFixedColumnsWidth = columnData.rightFixedColumnsWidth;
return {
prefixCls: prefixCls,
rowHeight: rowHeight,
bordered: bordered,
scrollX: scrollX,
showScrollbarX: showScrollbarX,
showScrollbarY: showScrollbarY,
isJustFullfill: isJustFullfill,
leftFixedColumns: leftFixedColumns,
scrollableColumns: scrollableColumns,
rightFixedColumns: rightFixedColumns,
leftFixedLeafColumns: leftFixedLeafColumns,
scrollableLeafColumns: scrollableLeafColumns,
rightFixedLeafColumns: rightFixedLeafColumns,
scrollableColumnsToRender: scrollableColumnsToRender,
scrollableLeafColumnsToRender: scrollableLeafColumnsToRender,
leftFixedColumnsWidth: leftFixedColumnsWidth,
scrollableColumnsWidth: scrollableColumnsWidth,
rightFixedColumnsWidth: rightFixedColumnsWidth,
leftFixedColumnsUpdated: leftFixedColumnsUpdated,
scrollableColumnsUpdated: scrollableColumnsUpdated,
rightFixedColumnsUpdated: rightFixedColumnsUpdated,
scrollableColumnsToRenderUpdated: scrollableColumnsToRenderUpdated
};
};
FlexiGrid.prototype.renderHeader = function renderHeader() {
var _state3 = this.state,
viewportWidth = _state3.viewportWidth,
headerHeight = _state3.headerHeight;
var props = _extends({}, this.getHeaderAndBodyCommonProps(), {
rowHeight: this.props.headerRowHeight,
scrollbarSize: Scrollbar.SIZE,
width: viewportWidth,
height: headerHeight
});
return React.createElement(FlexiGridHeader, props);
};
FlexiGrid.prototype.renderBody = function renderBody() {
var props = _extends({}, this.getHeaderAndBodyCommonProps(), {
width: this.state.bodyWidth,
height: this.state.bodyHeight,
firstRowIndex: this.state.firstRowIndex,
firstRowOffset: this.state.firstRowOffset,
data: this.props.data,
rowKey: this.props.rowKey,
scrolling: this.scrolling,
subRow: this.props.subRow,
bufferRowCount: this.props.bufferRowCount,
getRowPosition: this.verticalScrollHelper.getRowPosition,
getRowHeight: this.props.getRowHeight,
getSubRowHeight: this.props.getSubRowHeight,
getRowClassName: this.props.getRowClassName,
onRowClick: this.props.onRowClick,
onRowDoubleClick: this.props.onRowDoubleClick,
onRowMouseDown: this.props.onRowMouseDown,
onRowMouseUp: this.props.onRowMouseUp,
onRowMouseEnter: this.props.onRowMouseEnter,
onRowMouseLeave: this.props.onRowMouseLeave,
onRowTouchStart: this.props.onRowTouchStart,
onRowTouchEnd: this.props.onRowTouchEnd,
onRowTouchMove: this.props.onRowTouchMove
});
return React.createElement(FlexiGridBody, props);
};
FlexiGrid.prototype.renderFooter = function renderFooter() {
var _props3 = this.props,
prefixCls = _props3.prefixCls,
footerHeight = _props3.footerHeight,
footer = _props3.footer;
var viewportWidth = this.state.viewportWidth;
var style = {
width: viewportWidth,
height: footerHeight
};
return React.createElement(
'div',
{
className: prefixCls + '-footer',
style: style
},
footer
);
};
FlexiGrid.prototype.renderShadowTop = function renderShadowTop() {
var props = {
prefixCls: this.props.prefixCls,
display: this.state.showScrollbarY,
visible: this.state.scrollY > 0,
width: this.state.bodyWidth,
top: this.state.headerHeight
};
return React.createElement(FlexiGridShadowTop, props);
};
FlexiGrid.prototype.renderShadowBottom = function renderShadowBottom() {
var props = {
prefixCls: this.props.prefixCls,
display: this.state.showScrollbarY,
visible: this.state.scrollY !== this.state.maxScrollY,
width: this.state.bodyWidth,
bottom: this.props.footerHeight
};
return React.createElement(FlexiGridShadowBottom, props);
};
FlexiGrid.prototype.renderShadowLeft = function renderShadowLeft() {
var _state$columnData = this.state.columnData,
leftFixedColumns = _state$columnData.leftFixedColumns,
leftFixedColumnsWidth = _state$columnData.leftFixedColumnsWidth;
var props = {
prefixCls: this.props.prefixCls,
display: leftFixedColumns.length > 0,
visible: this.state.scrollX > 0,
height: this.state.headerHeight + this.state.bodyHeight,
left: leftFixedColumnsWidth
};
return React.createElement(FlexiGridShadowLeft, props);
};
FlexiGrid.prototype.renderShadowRight = function renderShadowRight() {
var _state$columnData2 = this.state.columnData,
rightFixedColumns = _state$columnData2.rightFixedColumns,
rightFixedColumnsWidth = _state$columnData2.rightFixedColumnsWidth;
var props = {
prefixCls: this.props.prefixCls,
display: rightFixedColumns.length > 0,
visible: this.state.scrollX !== this.state.maxScrollX,
height: this.state.headerHeight + this.state.bodyHeight,
right: rightFixedColumnsWidth + (this.state.showScrollbarY ? Scrollbar.SIZE : 0)
};
return React.createElement(FlexiGridShadowRight, props);
};
FlexiGrid.prototype.renderResizeKnobs = function renderResizeKnobs() {
var columnData = this.state.columnData;
var props = {
prefixCls: this.props.prefixCls,
knobSize: this.props.resizeKnobSize,
headerRowHeight: this.props.headerRowHeight,
headerHeight: this.state.headerHeight,
bodyHeight: this.state.bodyHeight,
bodyWidth: this.state.bodyWidth,
scrollX: this.state.scrollX,
showScrollbarX: this.state.showScrollbarX,
isJustFullfill: this.state.isJustFullfill,
leftFixedLeafColumns: columnData.leftFixedLeafColumns,
scrollableLeafColumns: columnData.scrollableLeafColumns,
rightFixedLeafColumns: columnData.rightFixedLeafColumns,
leftFixedColumnsWidth: columnData.leftFixedColumnsWidth,
scrollableColumnsWidth: columnData.scrollableColumnsWidth,
rightFixedColumnsWidth: columnData.rightFixedColumnsWidth,
onColumnResize: this.onColumnResize
};
return React.createElement(FlexiGridColumnResizeKnobs, props);
};
FlexiGrid.prototype.renderColumnResizeHandler = function renderColumnResizeHandler() {
var props = this.columnResizingData || { prefixCls: this.props.prefixCls };
return React.createElement(FlexiGridColumnResizeHandler, _extends({}, props, { visible: this.isColumnResizing() }));
};
FlexiGrid.prototype.renderReorderKnobs = function renderReorderKnobs() {
var columnData = this.state.columnData;
var props = {
prefixCls: this.props.prefixCls,
knobSize: this.props.reorderKnobSize,
headerHeight: this.state.headerHeight,
headerRowHeight: this.props.headerRowHeight,
bodyWidth: this.state.bodyWidth,
scrollX: this.state.scrollX,
showScrollbarX: this.state.showScrollbarX,
leftFixedColumns: columnData.leftFixedColumns,
scrollableColumns: columnData.scrollableColumns,
rightFixedColumns: columnData.rightFixedColumns,
leftFixedColumnsWidth: columnData.leftFixedColumnsWidth,
scrollableColumnsWidth: columnData.scrollableColumnsWidth,
rightFixedColumnsWidth: columnData.rightFixedColumnsWidth,
onColumnReorder: this.onColumnReorder
};
return React.createElement(FlexiGridColumnReorderKnobs, props);
};
FlexiGrid.prototype.renderColumnReorderHandler = function renderColumnReorderHandler() {
var props = this.getColumnReorderingData() || { prefixCls: this.props.prefixCls };
return React.createElement(FlexiGridColumnReorderHandler, _extends({}, props, {
sortable: this.props.sortable,
visible: this.isColumnReordering()
}));
};
FlexiGrid.prototype.renderColumnSortKnobs = function renderColumnSortKnobs() {
var columnData = this.state.columnData;
var props = {
prefixCls: this.props.prefixCls,
knobSize: this.props.sortKnobSize,
sortType: this.props.sortType,
sortColumnKey: this.props.sortColumnKey,
headerRowHeight: this.props.headerRowHeight,
headerHeight: this.state.headerHeight,
bodyWidth: this.state.bodyWidth,
scrollX: this.state.scrollX,
showScrollbarX: this.state.showScrollbarX,
leftFixedColumns: columnData.leftFixedColumns,
scrollableColumns: columnData.scrollableColumns,
rightFixedColumns: columnData.rightFixedColumns,
leftFixedColumnsWidth: columnData.leftFixedColumnsWidth,
scrollableColumnsWidth: columnData.scrollableColumnsWidth,
rightFixedColumnsWidth: columnData.rightFixedColumnsWidth,
onSort: this.onColumnSort
};
return React.createElement(FlexiGridSortKnobs, props);
};
FlexiGrid.prototype.renderScrollbar = function renderScrollbar() {
var state = this.state;
var props = this.props;
var result = {};
if (state.showScrollbarY) {
result.verticalScrollbar = React.createElement(Scrollbar, {
orientation: 'vertical',
top: state.headerHeight,
prefixCls: props.prefixCls,
position: state.scrollY,
size: state.bodyHeight,
contentSize: state.contentHeight,
onScroll: this.onVerticalScroll
});
}
if (state.showScrollbarX) {
result.horizontalScrollbar = React.createElement(Scrollbar, {
orientation: 'horizontal',
prefixCls: props.prefixCls,
position: state.scrollX,
size: state.bodyWidth,
contentSize: state.contentWidth,
hasVerticalScrollbar: state.showScrollbarX,
onScroll: this.onHorizontalScroll
});
}
return result;
};
FlexiGrid.prototype.render = function render() {
var state = this.state;
var props = this.props;
var prefixCls = props.prefixCls,
className = props.className,
bordered = props.bordered,
reorderable = props.reorderable,
sortable = props.sortable;
var mainClassNames = classNames(prefixCls, className, { bordered: bordered, reorderable: reorderable, sortable: sortable });
var _renderScrollbar = this.renderScrollbar(),
verticalScrollbar = _renderScrollbar.verticalScrollbar,
horizontalScrollbar = _renderScrollbar.horizontalScrollbar;
return React.createElement(
'div',
{
className: mainClassNames,
onWheel: this.wheelHandler.onWheel,
onTouchStart: this.touchHandler.onTouchStart,
onTouchEnd: this.touchHandler.onTouchEnd,
onTouchMove: this.touchHandler.onTouchMove,
onTouchCancel: this.touchHandler.onTouchCancel,
style: {
width: state.width,
height: state.height
}
},
React.createElement(
'div',
{
className: prefixCls + '-container',
style: {
width: state.viewportWidth,
height: state.headerHeight + state.bodyHeight + props.footerHeight
}
},
this.renderHeader(),
this.renderBody(),
this.renderFooter(),
this.renderShadowTop(),
this.renderShadowRight(),
this.renderShadowBottom(),
this.renderShadowLeft(),
this.props.resizable && this.renderResizeKnobs(),
this.props.reorderable && this.renderReorderKnobs(),
this.props.resizable && this.renderColumnResizeHandler(),
this.props.reorderable && this.renderColumnReorderHandler(),
this.props.sortable && this.renderColumnSortKnobs()
),
verticalScrollbar,
horizontalScrollbar
);
};
return FlexiGrid;
}(React.Component);
FlexiGrid.propTypes = {
prefixCls: PropTypes.string,
className: PropTypes.string,
columns: propTypes.columns.isRequired,
data: propTypes.data.isRequired,
rowKey: PropTypes.string.isRequired,
bufferRowCount: PropTypes.number,
bufferColumnCount: PropTypes.number,
bordered: PropTypes.bool,
borderSize: PropTypes.number,
width: PropTypes.number.isRequired,
height: PropTypes.number,
maxHeight: PropTypes.number,
ownerHeight: PropTypes.number,
footerHeight: PropTypes.number,
rowHeight: PropTypes.number,
headerRowHeight: PropTypes.number,
subRowHeight: PropTypes.number,
getRowHeight: PropTypes.func,
getSubRowHeight: PropTypes.func,
getRowClassName: PropTypes.func,
subRow: propTypes.render,
footer: propTypes.render,
scrollTop: PropTypes.number,
scrollLeft: PropTypes.number,
scrollToColumn: PropTypes.number,
scrollToRow: PropTypes.number,
showScrollbarX: PropTypes.bool,
showScrollbarY: PropTypes.bool,
touchScrollEnabled: PropTypes.bool,
onHorizontalScroll: PropTypes.func,
onVerticalScroll: PropTypes.func,
onScrollStart: PropTypes.func,
onScrollEnd: PropTypes.func,
stopScrollPropagation: PropTypes.bool,
onContentHeightChange: PropTypes.func,
onRowTouchStart: PropTypes.func,
onRowTouchEnd: PropTypes.func,
onRowTouchMove: PropTypes.func,
onRowClick: PropTypes.func,
onRowDoubleClick: PropTypes.func,
onRowMouseDown: PropTypes.func,
onRowMouseUp: PropTypes.func,
onRowMouseEnter: PropTypes.func,
onRowMouseLeave: PropTypes.func,
sortable: PropTypes.bool,
sortType: PropTypes.oneOf(['asc', 'desc']),
sortColumnKey: PropTypes.string,
sortKnobSize: PropTypes.number,
onColumnSort: PropTypes.func,
resizable: PropTypes.bool,
resizeKnobSize: PropTypes.number,
onColumnResize: PropTypes.func,
onColumnResizing: PropTypes.func,
onColumnResized: PropTypes.func,
reorderable: PropTypes.bool,
reorderKnobSize: PropTypes.number,
reorderFactor: PropTypes.number,
dragScrollBuffer: PropTypes.number,
dragScrollSpeed: PropTypes.number,
onColumnReorder: PropTypes.func,
onColumnReordering: PropTypes.func,
onColumnReordered: PropTypes.func
};
FlexiGrid.defaultProps = {
prefixCls: 'flexi-grid',
rowHeight: 32,
headerRowHeight: 32,
subRowHeight: 0,
footerHeight: 0,
bordered: true,
borderSize: 1,
showScrollbarX: true,
showScrollbarY: true,
touchScrollEnabled: false,
stopScrollPropagation: false,
sortable: false,
sortType: 'asc',
sortColumnKey: null,
sortKnobSize: 12,
resizable: false,
resizeKnobSize: 13,
reorderable: false,
reorderKnobSize: 12,
reorderFactor: 3 / 4,
dragScrollBuffer: 50,
dragScrollSpeed: 15
};
export default FlexiGrid;