react-table-v6
Version:
A fast, lightweight, opinionated table and datagrid built on React
1,573 lines (1,356 loc) • 126 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
(factory((global.ReactTable = {}),global.React));
}(this, (function (exports,React) { 'use strict';
var React__default = 'default' in React ? React['default'] : React;
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var classnames = createCommonjsModule(function (module) {
/*!
Copyright (c) 2016 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
/* global define */
(function () {
var hasOwn = {}.hasOwnProperty;
function classNames () {
var classes = [];
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (!arg) continue;
var argType = typeof arg;
if (argType === 'string' || argType === 'number') {
classes.push(arg);
} else if (Array.isArray(arg)) {
classes.push(classNames.apply(null, arg));
} else if (argType === 'object') {
for (var key in arg) {
if (hasOwn.call(arg, key) && arg[key]) {
classes.push(key);
}
}
}
}
return classes.join(' ');
}
if ('object' !== 'undefined' && module.exports) {
module.exports = classNames;
} else if (typeof undefined === 'function' && typeof undefined.amd === 'object' && undefined.amd) {
// register as 'classnames', consistent with npm package name
undefined('classnames', [], function () {
return classNames;
});
} else {
window.classNames = classNames;
}
}());
});
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var slicedToArray = function () {
function sliceIterator(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"]) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i);
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
}();
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
//
var _ = {
get: get$1,
set: set$1,
takeRight: takeRight,
last: last,
orderBy: orderBy,
range: range,
remove: remove,
clone: clone,
getFirstDefined: getFirstDefined,
sum: sum,
makeTemplateComponent: makeTemplateComponent,
groupBy: groupBy,
isArray: isArray,
splitProps: splitProps,
compactObject: compactObject,
isSortingDesc: isSortingDesc,
normalizeComponent: normalizeComponent,
asPx: asPx
};
function get$1(obj, path, def) {
if (!path) {
return obj;
}
var pathObj = makePathArray(path);
var val = void 0;
try {
val = pathObj.reduce(function (current, pathPart) {
return current[pathPart];
}, obj);
} catch (e) {
// continue regardless of error
}
return typeof val !== 'undefined' ? val : def;
}
function set$1() {
var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var path = arguments[1];
var value = arguments[2];
var keys = makePathArray(path);
var keyPart = void 0;
var cursor = obj;
while ((keyPart = keys.shift()) && keys.length) {
if (!cursor[keyPart]) {
cursor[keyPart] = {};
}
cursor = cursor[keyPart];
}
cursor[keyPart] = value;
return obj;
}
function takeRight(arr, n) {
var start = n > arr.length ? 0 : arr.length - n;
return arr.slice(start);
}
function last(arr) {
return arr[arr.length - 1];
}
function range(n) {
var arr = [];
for (var i = 0; i < n; i += 1) {
arr.push(n);
}
return arr;
}
function orderBy(arr, funcs, dirs, indexKey) {
return arr.sort(function (rowA, rowB) {
for (var i = 0; i < funcs.length; i += 1) {
var comp = funcs[i];
var desc = dirs[i] === false || dirs[i] === 'desc';
var sortInt = comp(rowA, rowB);
if (sortInt) {
return desc ? -sortInt : sortInt;
}
}
// Use the row index for tie breakers
return dirs[0] ? rowA[indexKey] - rowB[indexKey] : rowB[indexKey] - rowA[indexKey];
});
}
function remove(a, b) {
return a.filter(function (o, i) {
var r = b(o);
if (r) {
a.splice(i, 1);
return true;
}
return false;
});
}
function clone(a) {
try {
return JSON.parse(JSON.stringify(a, function (key, value) {
if (typeof value === 'function') {
return value.toString();
}
return value;
}));
} catch (e) {
return a;
}
}
function getFirstDefined() {
for (var i = 0; i < arguments.length; i += 1) {
if (typeof (arguments.length <= i ? undefined : arguments[i]) !== 'undefined') {
return arguments.length <= i ? undefined : arguments[i];
}
}
}
function sum(arr) {
return arr.reduce(function (a, b) {
return a + b;
}, 0);
}
function makeTemplateComponent(compClass, displayName) {
if (!displayName) {
throw new Error('No displayName found for template component:', compClass);
}
var cmp = function cmp(_ref) {
var children = _ref.children,
className = _ref.className,
rest = objectWithoutProperties(_ref, ['children', 'className']);
return React__default.createElement(
'div',
_extends({ className: classnames(compClass, className) }, rest),
children
);
};
cmp.displayName = displayName;
return cmp;
}
function groupBy(xs, key) {
return xs.reduce(function (rv, x, i) {
var resKey = typeof key === 'function' ? key(x, i) : x[key];
rv[resKey] = isArray(rv[resKey]) ? rv[resKey] : [];
rv[resKey].push(x);
return rv;
}, {});
}
function asPx(value) {
value = Number(value);
return Number.isNaN(value) ? null : value + 'px';
}
function isArray(a) {
return Array.isArray(a);
}
// ########################################################################
// Non-exported Helpers
// ########################################################################
function makePathArray(obj) {
return flattenDeep(obj).join('.').replace(/\[/g, '.').replace(/\]/g, '').split('.');
}
function flattenDeep(arr) {
var newArr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
if (!isArray(arr)) {
newArr.push(arr);
} else {
for (var i = 0; i < arr.length; i += 1) {
flattenDeep(arr[i], newArr);
}
}
return newArr;
}
function splitProps(_ref2) {
var className = _ref2.className,
style = _ref2.style,
rest = objectWithoutProperties(_ref2, ['className', 'style']);
return {
className: className,
style: style,
rest: rest || {}
};
}
function compactObject(obj) {
var newObj = {};
if (obj) {
Object.keys(obj).map(function (key) {
if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== undefined && typeof obj[key] !== 'undefined') {
newObj[key] = obj[key];
}
return true;
});
}
return newObj;
}
function isSortingDesc(d) {
return !!(d.sort === 'desc' || d.desc === true || d.asc === false);
}
function normalizeComponent(Comp) {
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var fallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Comp;
return typeof Comp === 'function' ? Object.getPrototypeOf(Comp).isReactComponent ? React__default.createElement(Comp, params) : Comp(params) : fallback;
}
var Lifecycle = (function (Base) {
return function (_Base) {
inherits(_class, _Base);
function _class() {
classCallCheck(this, _class);
return possibleConstructorReturn(this, (_class.__proto__ || Object.getPrototypeOf(_class)).apply(this, arguments));
}
createClass(_class, [{
key: 'componentWillMount',
value: function componentWillMount() {
this.setStateWithData(this.getDataModel(this.getResolvedState(), true));
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
this.fireFetchData();
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps, nextState) {
var oldState = this.getResolvedState();
var newState = this.getResolvedState(nextProps, nextState);
// Do a deep compare of new and old `defaultOption` and
// if they are different reset `option = defaultOption`
var defaultableOptions = ['sorted', 'filtered', 'resized', 'expanded'];
defaultableOptions.forEach(function (x) {
var defaultName = 'default' + (x.charAt(0).toUpperCase() + x.slice(1));
if (JSON.stringify(oldState[defaultName]) !== JSON.stringify(newState[defaultName])) {
newState[x] = newState[defaultName];
}
});
// If they change these table options, we need to reset defaults
// or else we could get into a state where the user has changed the UI
// and then disabled the ability to change it back.
// e.g. If `filterable` has changed, set `filtered = defaultFiltered`
var resettableOptions = ['sortable', 'filterable', 'resizable'];
resettableOptions.forEach(function (x) {
if (oldState[x] !== newState[x]) {
var baseName = x.replace('able', '');
var optionName = baseName + 'ed';
var defaultName = 'default' + (optionName.charAt(0).toUpperCase() + optionName.slice(1));
newState[optionName] = newState[defaultName];
}
});
// Props that trigger a data update
if (oldState.data !== newState.data || oldState.columns !== newState.columns || oldState.pivotBy !== newState.pivotBy || oldState.sorted !== newState.sorted || oldState.filtered !== newState.filtered) {
this.setStateWithData(this.getDataModel(newState, oldState.data !== newState.data));
}
}
}, {
key: 'setStateWithData',
value: function setStateWithData(newState, cb) {
var _this2 = this;
var oldState = this.getResolvedState();
var newResolvedState = this.getResolvedState({}, newState);
var freezeWhenExpanded = newResolvedState.freezeWhenExpanded;
// Default to unfrozen state
newResolvedState.frozen = false;
// If freezeWhenExpanded is set, check for frozen conditions
if (freezeWhenExpanded) {
// if any rows are expanded, freeze the existing data and sorting
var keys = Object.keys(newResolvedState.expanded);
for (var i = 0; i < keys.length; i += 1) {
if (newResolvedState.expanded[keys[i]]) {
newResolvedState.frozen = true;
break;
}
}
}
// If the data isn't frozen and either the data or
// sorting model has changed, update the data
if (oldState.frozen && !newResolvedState.frozen || oldState.sorted !== newResolvedState.sorted || oldState.filtered !== newResolvedState.filtered || oldState.showFilters !== newResolvedState.showFilters || !newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData) {
// Handle collapseOnsortedChange & collapseOnDataChange
if (oldState.sorted !== newResolvedState.sorted && this.props.collapseOnSortingChange || oldState.filtered !== newResolvedState.filtered || oldState.showFilters !== newResolvedState.showFilters || oldState.sortedData && !newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData && this.props.collapseOnDataChange) {
newResolvedState.expanded = {};
}
Object.assign(newResolvedState, this.getSortedData(newResolvedState));
}
// Set page to 0 if filters change
if (oldState.filtered !== newResolvedState.filtered) {
newResolvedState.page = 0;
}
// Calculate pageSize all the time
if (newResolvedState.sortedData) {
newResolvedState.pages = newResolvedState.manual ? newResolvedState.pages : Math.ceil(newResolvedState.sortedData.length / newResolvedState.pageSize);
newResolvedState.page = Math.max(newResolvedState.page >= newResolvedState.pages ? newResolvedState.pages - 1 : newResolvedState.page, 0);
}
return this.setState(newResolvedState, function () {
if (cb) {
cb();
}
if (oldState.page !== newResolvedState.page || oldState.pageSize !== newResolvedState.pageSize || oldState.sorted !== newResolvedState.sorted || oldState.filtered !== newResolvedState.filtered) {
_this2.fireFetchData();
}
});
}
}]);
return _class;
}(Base);
});
var Methods = (function (Base) {
return function (_Base) {
inherits(_class, _Base);
function _class() {
classCallCheck(this, _class);
return possibleConstructorReturn(this, (_class.__proto__ || Object.getPrototypeOf(_class)).apply(this, arguments));
}
createClass(_class, [{
key: 'getResolvedState',
value: function getResolvedState(props, state) {
var resolvedState = _extends({}, _.compactObject(this.state), _.compactObject(this.props), _.compactObject(state), _.compactObject(props));
return resolvedState;
}
}, {
key: 'getDataModel',
value: function getDataModel(newState, dataChanged) {
var _this2 = this;
var columns = newState.columns,
_newState$pivotBy = newState.pivotBy,
pivotBy = _newState$pivotBy === undefined ? [] : _newState$pivotBy,
data = newState.data,
resolveData = newState.resolveData,
pivotIDKey = newState.pivotIDKey,
pivotValKey = newState.pivotValKey,
subRowsKey = newState.subRowsKey,
aggregatedKey = newState.aggregatedKey,
nestingLevelKey = newState.nestingLevelKey,
originalKey = newState.originalKey,
indexKey = newState.indexKey,
groupedByPivotKey = newState.groupedByPivotKey,
SubComponent = newState.SubComponent;
// Determine Header Groups
var hasHeaderGroups = false;
columns.forEach(function (column) {
if (column.columns) {
hasHeaderGroups = true;
}
});
var columnsWithExpander = [].concat(toConsumableArray(columns));
var expanderColumn = columns.find(function (col) {
return col.expander || col.columns && col.columns.some(function (col2) {
return col2.expander;
});
});
// The actual expander might be in the columns field of a group column
if (expanderColumn && !expanderColumn.expander) {
expanderColumn = expanderColumn.columns.find(function (col) {
return col.expander;
});
}
// If we have SubComponent's we need to make sure we have an expander column
if (SubComponent && !expanderColumn) {
expanderColumn = { expander: true };
columnsWithExpander = [expanderColumn].concat(toConsumableArray(columnsWithExpander));
}
var makeDecoratedColumn = function makeDecoratedColumn(column, parentColumn) {
var dcol = void 0;
if (column.expander) {
dcol = _extends({}, _this2.props.column, _this2.props.expanderDefaults, column);
} else {
dcol = _extends({}, _this2.props.column, column);
}
// Ensure minWidth is not greater than maxWidth if set
if (dcol.maxWidth < dcol.minWidth) {
dcol.minWidth = dcol.maxWidth;
}
if (parentColumn) {
dcol.parentColumn = parentColumn;
}
// First check for string accessor
if (typeof dcol.accessor === 'string') {
dcol.id = dcol.id || dcol.accessor;
var accessorString = dcol.accessor;
dcol.accessor = function (row) {
return _.get(row, accessorString);
};
return dcol;
}
// Fall back to functional accessor (but require an ID)
if (dcol.accessor && !dcol.id) {
console.warn(dcol);
throw new Error('A column id is required if using a non-string accessor for column above.');
}
// Fall back to an undefined accessor
if (!dcol.accessor) {
dcol.accessor = function () {
return undefined;
};
}
return dcol;
};
var allDecoratedColumns = [];
// Decorate the columns
var decorateAndAddToAll = function decorateAndAddToAll(column, parentColumn) {
var decoratedColumn = makeDecoratedColumn(column, parentColumn);
allDecoratedColumns.push(decoratedColumn);
return decoratedColumn;
};
var decoratedColumns = columnsWithExpander.map(function (column) {
if (column.columns) {
return _extends({}, column, {
columns: column.columns.map(function (d) {
return decorateAndAddToAll(d, column);
})
});
}
return decorateAndAddToAll(column);
});
// Build the visible columns, headers and flat column list
var visibleColumns = decoratedColumns.slice();
var allVisibleColumns = [];
visibleColumns = visibleColumns.map(function (column) {
if (column.columns) {
var visibleSubColumns = column.columns.filter(function (d) {
return pivotBy.indexOf(d.id) > -1 ? false : _.getFirstDefined(d.show, true);
});
return _extends({}, column, {
columns: visibleSubColumns
});
}
return column;
});
visibleColumns = visibleColumns.filter(function (column) {
return column.columns ? column.columns.length : pivotBy.indexOf(column.id) > -1 ? false : _.getFirstDefined(column.show, true);
});
// Find any custom pivot location
var pivotIndex = visibleColumns.findIndex(function (col) {
return col.pivot;
});
// Handle Pivot Columns
if (pivotBy.length) {
// Retrieve the pivot columns in the correct pivot order
var pivotColumns = [];
pivotBy.forEach(function (pivotID) {
var found = allDecoratedColumns.find(function (d) {
return d.id === pivotID;
});
if (found) {
pivotColumns.push(found);
}
});
var PivotParentColumn = pivotColumns.reduce(function (prev, current) {
return prev && prev === current.parentColumn && current.parentColumn;
}, pivotColumns[0].parentColumn);
var PivotGroupHeader = hasHeaderGroups && PivotParentColumn.Header;
PivotGroupHeader = PivotGroupHeader || function () {
return React__default.createElement(
'strong',
null,
'Pivoted'
);
};
var pivotColumnGroup = {
Header: PivotGroupHeader,
columns: pivotColumns.map(function (col) {
return _extends({}, _this2.props.pivotDefaults, col, {
pivoted: true
});
})
// Place the pivotColumns back into the visibleColumns
};if (pivotIndex >= 0) {
pivotColumnGroup = _extends({}, visibleColumns[pivotIndex], pivotColumnGroup);
visibleColumns.splice(pivotIndex, 1, pivotColumnGroup);
} else {
visibleColumns.unshift(pivotColumnGroup);
}
}
// Build Header Groups
var headerGroups = [];
var currentSpan = [];
// A convenience function to add a header and reset the currentSpan
var addHeader = function addHeader(columns, column) {
headerGroups.push(_extends({}, _this2.props.column, column, {
columns: columns
}));
currentSpan = [];
};
// Build flast list of allVisibleColumns and HeaderGroups
visibleColumns.forEach(function (column) {
if (column.columns) {
allVisibleColumns = allVisibleColumns.concat(column.columns);
if (currentSpan.length > 0) {
addHeader(currentSpan);
}
addHeader(column.columns, column);
return;
}
allVisibleColumns.push(column);
currentSpan.push(column);
});
if (hasHeaderGroups && currentSpan.length > 0) {
addHeader(currentSpan);
}
// Access the data
var accessRow = function accessRow(d, i) {
var _row;
var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var row = (_row = {}, defineProperty(_row, originalKey, d), defineProperty(_row, indexKey, i), defineProperty(_row, subRowsKey, d[subRowsKey]), defineProperty(_row, nestingLevelKey, level), _row);
allDecoratedColumns.forEach(function (column) {
if (column.expander) return;
row[column.id] = column.accessor(d);
});
if (row[subRowsKey]) {
row[subRowsKey] = row[subRowsKey].map(function (d, i) {
return accessRow(d, i, level + 1);
});
}
return row;
};
// // If the data hasn't changed, just use the cached data
var resolvedData = this.resolvedData;
// If the data has changed, run the data resolver and cache the result
if (!this.resolvedData || dataChanged) {
resolvedData = resolveData(data);
this.resolvedData = resolvedData;
}
// Use the resolved data
resolvedData = resolvedData.map(function (d, i) {
return accessRow(d, i);
});
// TODO: Make it possible to fabricate nested rows without pivoting
var aggregatingColumns = allVisibleColumns.filter(function (d) {
return !d.expander && d.aggregate;
});
// If pivoting, recursively group the data
var aggregate = function aggregate(rows) {
var aggregationValues = {};
aggregatingColumns.forEach(function (column) {
var values = rows.map(function (d) {
return d[column.id];
});
aggregationValues[column.id] = column.aggregate(values, rows);
});
return aggregationValues;
};
if (pivotBy.length) {
var groupRecursively = function groupRecursively(rows, keys) {
var i = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
// This is the last level, just return the rows
if (i === keys.length) {
return rows;
}
// Group the rows together for this level
var groupedRows = Object.entries(_.groupBy(rows, keys[i])).map(function (_ref) {
var _ref3;
var _ref2 = slicedToArray(_ref, 2),
key = _ref2[0],
value = _ref2[1];
return _ref3 = {}, defineProperty(_ref3, pivotIDKey, keys[i]), defineProperty(_ref3, pivotValKey, key), defineProperty(_ref3, keys[i], key), defineProperty(_ref3, subRowsKey, value), defineProperty(_ref3, nestingLevelKey, i), defineProperty(_ref3, groupedByPivotKey, true), _ref3;
});
// Recurse into the subRows
groupedRows = groupedRows.map(function (rowGroup) {
var _babelHelpers$extends;
var subRows = groupRecursively(rowGroup[subRowsKey], keys, i + 1);
return _extends({}, rowGroup, (_babelHelpers$extends = {}, defineProperty(_babelHelpers$extends, subRowsKey, subRows), defineProperty(_babelHelpers$extends, aggregatedKey, true), _babelHelpers$extends), aggregate(subRows));
});
return groupedRows;
};
resolvedData = groupRecursively(resolvedData, pivotBy);
}
return _extends({}, newState, {
resolvedData: resolvedData,
allVisibleColumns: allVisibleColumns,
headerGroups: headerGroups,
allDecoratedColumns: allDecoratedColumns,
hasHeaderGroups: hasHeaderGroups
});
}
}, {
key: 'getSortedData',
value: function getSortedData(resolvedState) {
var manual = resolvedState.manual,
sorted = resolvedState.sorted,
filtered = resolvedState.filtered,
defaultFilterMethod = resolvedState.defaultFilterMethod,
resolvedData = resolvedState.resolvedData,
allVisibleColumns = resolvedState.allVisibleColumns,
allDecoratedColumns = resolvedState.allDecoratedColumns;
var sortMethodsByColumnID = {};
allDecoratedColumns.filter(function (col) {
return col.sortMethod;
}).forEach(function (col) {
sortMethodsByColumnID[col.id] = col.sortMethod;
});
// Resolve the data from either manual data or sorted data
return {
sortedData: manual ? resolvedData : this.sortData(this.filterData(resolvedData, filtered, defaultFilterMethod, allVisibleColumns), sorted, sortMethodsByColumnID)
};
}
}, {
key: 'fireFetchData',
value: function fireFetchData() {
this.props.onFetchData(this.getResolvedState(), this);
}
}, {
key: 'getPropOrState',
value: function getPropOrState(key) {
return _.getFirstDefined(this.props[key], this.state[key]);
}
}, {
key: 'getStateOrProp',
value: function getStateOrProp(key) {
return _.getFirstDefined(this.state[key], this.props[key]);
}
}, {
key: 'filterData',
value: function filterData(data, filtered, defaultFilterMethod, allVisibleColumns) {
var _this3 = this;
var filteredData = data;
if (filtered.length) {
filteredData = filtered.reduce(function (filteredSoFar, nextFilter) {
var column = allVisibleColumns.find(function (x) {
return x.id === nextFilter.id;
});
// Don't filter hidden columns or columns that have had their filters disabled
if (!column || column.filterable === false) {
return filteredSoFar;
}
var filterMethod = column.filterMethod || defaultFilterMethod;
// If 'filterAll' is set to true, pass the entire dataset to the filter method
if (column.filterAll) {
return filterMethod(nextFilter, filteredSoFar, column);
}
return filteredSoFar.filter(function (row) {
return filterMethod(nextFilter, row, column);
});
}, filteredData);
// Apply the filter to the subrows if we are pivoting, and then
// filter any rows without subcolumns because it would be strange to show
filteredData = filteredData.map(function (row) {
if (!row[_this3.props.subRowsKey]) {
return row;
}
return _extends({}, row, defineProperty({}, _this3.props.subRowsKey, _this3.filterData(row[_this3.props.subRowsKey], filtered, defaultFilterMethod, allVisibleColumns)));
}).filter(function (row) {
if (!row[_this3.props.subRowsKey]) {
return true;
}
return row[_this3.props.subRowsKey].length > 0;
});
}
return filteredData;
}
}, {
key: 'sortData',
value: function sortData(data, sorted) {
var _this4 = this;
var sortMethodsByColumnID = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
if (!sorted.length) {
return data;
}
var sortedData = (this.props.orderByMethod || _.orderBy)(data, sorted.map(function (sort) {
// Support custom sorting methods for each column
if (sortMethodsByColumnID[sort.id]) {
return function (a, b) {
return sortMethodsByColumnID[sort.id](a[sort.id], b[sort.id], sort.desc);
};
}
return function (a, b) {
return _this4.props.defaultSortMethod(a[sort.id], b[sort.id], sort.desc);
};
}), sorted.map(function (d) {
return !d.desc;
}), this.props.indexKey);
sortedData.forEach(function (row) {
if (!row[_this4.props.subRowsKey]) {
return;
}
row[_this4.props.subRowsKey] = _this4.sortData(row[_this4.props.subRowsKey], sorted, sortMethodsByColumnID);
});
return sortedData;
}
}, {
key: 'getMinRows',
value: function getMinRows() {
return _.getFirstDefined(this.props.minRows, this.getStateOrProp('pageSize'));
}
// User actions
}, {
key: 'onPageChange',
value: function onPageChange(page) {
var _props = this.props,
onPageChange = _props.onPageChange,
collapseOnPageChange = _props.collapseOnPageChange;
var newState = { page: page };
if (collapseOnPageChange) {
newState.expanded = {};
}
this.setStateWithData(newState, function () {
return onPageChange && onPageChange(page);
});
}
}, {
key: 'onPageSizeChange',
value: function onPageSizeChange(newPageSize) {
var onPageSizeChange = this.props.onPageSizeChange;
var _getResolvedState = this.getResolvedState(),
pageSize = _getResolvedState.pageSize,
page = _getResolvedState.page;
// Normalize the page to display
var currentRow = pageSize * page;
var newPage = Math.floor(currentRow / newPageSize);
this.setStateWithData({
pageSize: newPageSize,
page: newPage
}, function () {
return onPageSizeChange && onPageSizeChange(newPageSize, newPage);
});
}
}, {
key: 'sortColumn',
value: function sortColumn(column, additive) {
var _getResolvedState2 = this.getResolvedState(),
sorted = _getResolvedState2.sorted,
skipNextSort = _getResolvedState2.skipNextSort,
defaultSortDesc = _getResolvedState2.defaultSortDesc;
var firstSortDirection = Object.prototype.hasOwnProperty.call(column, 'defaultSortDesc') ? column.defaultSortDesc : defaultSortDesc;
var secondSortDirection = !firstSortDirection;
// we can't stop event propagation from the column resize move handlers
// attached to the document because of react's synthetic events
// so we have to prevent the sort function from actually sorting
// if we click on the column resize element within a header.
if (skipNextSort) {
this.setStateWithData({
skipNextSort: false
});
return;
}
var onSortedChange = this.props.onSortedChange;
var newSorted = _.clone(sorted || []).map(function (d) {
d.desc = _.isSortingDesc(d);
return d;
});
if (!_.isArray(column)) {
// Single-Sort
var existingIndex = newSorted.findIndex(function (d) {
return d.id === column.id;
});
if (existingIndex > -1) {
var existing = newSorted[existingIndex];
if (existing.desc === secondSortDirection) {
if (additive) {
newSorted.splice(existingIndex, 1);
} else {
existing.desc = firstSortDirection;
newSorted = [existing];
}
} else {
existing.desc = secondSortDirection;
if (!additive) {
newSorted = [existing];
}
}
} else if (additive) {
newSorted.push({
id: column.id,
desc: firstSortDirection
});
} else {
newSorted = [{
id: column.id,
desc: firstSortDirection
}];
}
} else {
// Multi-Sort
var _existingIndex = newSorted.findIndex(function (d) {
return d.id === column[0].id;
});
// Existing Sorted Column
if (_existingIndex > -1) {
var _existing = newSorted[_existingIndex];
if (_existing.desc === secondSortDirection) {
if (additive) {
newSorted.splice(_existingIndex, column.length);
} else {
column.forEach(function (d, i) {
newSorted[_existingIndex + i].desc = firstSortDirection;
});
}
} else {
column.forEach(function (d, i) {
newSorted[_existingIndex + i].desc = secondSortDirection;
});
}
if (!additive) {
newSorted = newSorted.slice(_existingIndex, column.length);
}
// New Sort Column
} else if (additive) {
newSorted = newSorted.concat(column.map(function (d) {
return {
id: d.id,
desc: firstSortDirection
};
}));
} else {
newSorted = column.map(function (d) {
return {
id: d.id,
desc: firstSortDirection
};
});
}
}
this.setStateWithData({
page: !sorted.length && newSorted.length || !additive ? 0 : this.state.page,
sorted: newSorted
}, function () {
return onSortedChange && onSortedChange(newSorted, column, additive);
});
}
}, {
key: 'filterColumn',
value: function filterColumn(column, value) {
var _getResolvedState3 = this.getResolvedState(),
filtered = _getResolvedState3.filtered;
var onFilteredChange = this.props.onFilteredChange;
// Remove old filter first if it exists
var newFiltering = (filtered || []).filter(function (x) {
return x.id !== column.id;
});
if (value !== '') {
newFiltering.push({
id: column.id,
value: value
});
}
this.setStateWithData({
filtered: newFiltering
}, function () {
return onFilteredChange && onFilteredChange(newFiltering, column, value);
});
}
}, {
key: 'resizeColumnStart',
value: function resizeColumnStart(event, column, isTouch) {
var _this5 = this;
event.stopPropagation();
var parentWidth = event.target.parentElement.getBoundingClientRect().width;
var pageX = void 0;
if (isTouch) {
pageX = event.changedTouches[0].pageX;
} else {
pageX = event.pageX;
}
this.trapEvents = true;
this.setStateWithData({
currentlyResizing: {
id: column.id,
startX: pageX,
parentWidth: parentWidth
}
}, function () {
if (isTouch) {
document.addEventListener('touchmove', _this5.resizeColumnMoving);
document.addEventListener('touchcancel', _this5.resizeColumnEnd);
document.addEventListener('touchend', _this5.resizeColumnEnd);
} else {
document.addEventListener('mousemove', _this5.resizeColumnMoving);
document.addEventListener('mouseup', _this5.resizeColumnEnd);
document.addEventListener('mouseleave', _this5.resizeColumnEnd);
}
});
}
}, {
key: 'resizeColumnMoving',
value: function resizeColumnMoving(event) {
event.stopPropagation();
var onResizedChange = this.props.onResizedChange;
var _getResolvedState4 = this.getResolvedState(),
resized = _getResolvedState4.resized,
currentlyResizing = _getResolvedState4.currentlyResizing;
// Delete old value
var newResized = resized.filter(function (x) {
return x.id !== currentlyResizing.id;
});
var pageX = void 0;
if (event.type === 'touchmove') {
pageX = event.changedTouches[0].pageX;
} else if (event.type === 'mousemove') {
pageX = event.pageX;
}
// Set the min size to 10 to account for margin and border or else the
// group headers don't line up correctly
var newWidth = Math.max(currentlyResizing.parentWidth + pageX - currentlyResizing.startX, 11);
newResized.push({
id: currentlyResizing.id,
value: newWidth
});
this.setStateWithData({
resized: newResized
}, function () {
return onResizedChange && onResizedChange(newResized, event);
});
}
}, {
key: 'resizeColumnEnd',
value: function resizeColumnEnd(event) {
event.stopPropagation();
var isTouch = event.type === 'touchend' || event.type === 'touchcancel';
if (isTouch) {
document.removeEventListener('touchmove', this.resizeColumnMoving);
document.removeEventListener('touchcancel', this.resizeColumnEnd);
document.removeEventListener('touchend', this.resizeColumnEnd);
}
// If its a touch event clear the mouse one's as well because sometimes
// the mouseDown event gets called as well, but the mouseUp event doesn't
document.removeEventListener('mousemove', this.resizeColumnMoving);
document.removeEventListener('mouseup', this.resizeColumnEnd);
document.removeEventListener('mouseleave', this.resizeColumnEnd);
// The touch events don't propagate up to the sorting's onMouseDown event so
// no need to prevent it from happening or else the first click after a touch
// event resize will not sort the column.
if (!isTouch) {
this.setStateWithData({
skipNextSort: true,
currentlyResizing: false
});
}
}
}]);
return _class;
}(Base);
});
//
// import _ from './utils'
var defaultButton = function defaultButton(props) {
return React__default.createElement(
'button',
_extends({ type: 'button' }, props, { className: '-btn' }),
props.children
);
};
var ReactTablePagination = function (_Component) {
inherits(ReactTablePagination, _Component);
function ReactTablePagination(props) {
classCallCheck(this, ReactTablePagination);
var _this = possibleConstructorReturn(this, (ReactTablePagination.__proto__ || Object.getPrototypeOf(ReactTablePagination)).call(this));
_this.getSafePage = _this.getSafePage.bind(_this);
_this.changePage = _this.changePage.bind(_this);
_this.applyPage = _this.applyPage.bind(_this);
_this.state = {
page: props.page
};
return _this;
}
createClass(ReactTablePagination, [{
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
this.setState({ page: nextProps.page });
}
}, {
key: 'getSafePage',
value: function getSafePage(page) {
if (Number.isNaN(page)) {
page = this.props.page;
}
return Math.min(Math.max(page, 0), this.props.pages - 1);
}
}, {
key: 'changePage',
value: function changePage(page) {
page = this.getSafePage(page);
this.setState({ page: page });
if (this.props.page !== page) {
this.props.onPageChange(page);
}
}
}, {
key: 'applyPage',
value: function applyPage(e) {
if (e) {
e.preventDefault();
}
var page = this.state.page;
this.changePage(page === '' ? this.props.page : page);
}
}, {
key: 'render',
value: function render() {
var _this2 = this;
var _props = this.props,
pages = _props.pages,
page = _props.page,
showPageSizeOptions = _props.showPageSizeOptions,
pageSizeOptions = _props.pageSizeOptions,
pageSize = _props.pageSize,
showPageJump = _props.showPageJump,
canPrevious = _props.canPrevious,
canNext = _props.canNext,
onPageSizeChange = _props.onPageSizeChange,
className = _props.className,
_props$PreviousCompon = _props.PreviousComponent,
PreviousComponent = _props$PreviousCompon === undefined ? defaultButton : _props$PreviousCompon,
_props$NextComponent = _props.NextComponent,
NextComponent = _props$NextComponent === undefined ? defaultButton : _props$NextComponent;
return React__default.createElement(
'div',
{ className: classnames(className, '-pagination'), style: this.props.style },
React__default.createElement(
'div',
{ className: '-previous' },
React__default.createElement(
PreviousComponent,
{
onClick: function onClick() {
if (!canPrevious) return;
_this2.changePage(page - 1);
},
disabled: !canPrevious
},
this.props.previousText
)
),
React__default.createElement(
'div',
{ className: '-center' },
React__default.createElement(
'span',
{ className: '-pageInfo' },
this.props.pageText,
' ',
showPageJump ? React__default.createElement(
'div',
{ className: '-pageJump' },
React__default.createElement('input', {
type: this.state.page === '' ? 'text' : 'number',
onChange: function onChange(e) {
var val = e.target.value;
var page = val - 1;
if (val === '') {
return _this2.setState({ page: val });
}
_this2.setState({ page: _this2.getSafePage(page) });
},
value: this.state.page === '' ? '' : this.state.page + 1,
onBlur: this.applyPage,
onKeyPress: function onKeyPress(e) {
if (e.which === 13 || e.keyCode === 13) {
_this2.applyPage();
}
}
})
) : React__default.createElement(
'span',
{ className: '-currentPage' },
page + 1
),
' ',
this.props.ofText,
' ',
React__default.createElement(
'span',
{ className: '-totalPages' },
pages || 1
)
),
showPageSizeOptions && React__default.createElement(
'span',
{ className: 'select-wrap -pageSizeOptions' },
React__default.createElement(
'select',
{ onChange: function onChange(e) {
return onPageSizeChange(Number(e.target.value));
}, value: pageSize },
pageSizeOptions.map(function (option, i) {
return (
// eslint-disable-next-line react/no-array-index-key
React__default.createElement(
'option',
{ key: i, value: option },
option,
' ',
_this2.props.rowsText
)
);
})
)
)
),
React__default.createElement(
'div',
{ className: '-next' },
React__default.createElement(
NextComponent,
{
onClick: function onClick() {
if (!canNext) return;
_this2.changePage(page + 1);
},
disabled: !canNext
},
this.props.nextText
)
)
);
}
}]);
return ReactTablePagination;
}(React.Component);
//
var emptyObj = function emptyObj() {
return {};
};
var defaultProps = {
// General
data: [],
resolveData: function resolveData(data) {
return data;
},
loading: false,
showPagination: true,
showPaginationTop: false,
showPaginationBottom: true,
showPageSizeOptions: true,
pageSizeOptions: [5, 10, 20, 25, 50, 100],
defaultPageSize: 20,
showPageJump: true,
collapseOnSortingChange: true,
collapseOnPageChange: true,
collapseOnDataChange: true,
freezeWhenExpanded: false,
sortable: true,
multiSort: true,
resizable: true,
filterable: false,
defaultSortDesc: false,
defaultSorted: [],
defaultFiltered: [],
defaultResized: [],
defaultExpanded: {},
// eslint-disable-next-line no-unused-vars
defaultFilterMethod: function defaultFilterMethod(filter, row, column) {
var id = filter.pivotId || filter.id;
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true;
},
// eslint-disable-next-line no-unused-vars
defaultSortMethod: function defaultSortMethod(a, b, desc) {
// force null and undefined to the bottom
a = a === null || a === undefined ? '' : a;
b = b === null || b === undefined ? '' : b;
// force any string values to lowercase
a = typeof a === 'string' ? a.toLowerCase() : a;
b = typeof b === 'string' ? b.toLowerCase() : b;
// Return either 1 or -1 to indicate a sort priority
if (a > b) {
return 1;
}
if (a < b) {
return -1;
}
// returning 0, undefined or any falsey value will use subsequent sorts or
// the index as a tiebreaker
return 0;
},
// Controlled State Props
// page: undefined,
// pageSize: undefined,
// sorted: [],
// filtered: [],
// resized: [],
// expanded: {},
// Controlled State Callbacks
onPageChange: undefined,
onPageSizeChange: undefined,
onSortedChange: undefined,
onFilteredChange: undefined,
onResizedChange: undefined,
onExpandedChange: undefined,
// Pivoting
pivotBy: undefined,
// Key Constants
pivotValKey: '_pivotVal',
pivotIDKey: '_pivotID',
subRowsKey: '_subRows',
aggregatedKey: '_aggregated',
nestingLevelKey: '_nestingLevel',
originalKey: '_original',
indexKey: '_index',
groupedByPivotKey: '_groupedByPivot',
// Server-side Callbacks
onFetchData: function onFetchData() {
return null;
},
// Classes
className: '',
style: {},
// Component decorators
getProps: emptyObj,
getTableProps: emptyObj,
getTheadGroupProps: emptyObj,
getTheadGroupTrProps: emptyObj,
getTheadGroupThProps: emptyObj,
getTheadProps: emptyObj,
getTheadTrProps: emptyObj,
getTheadThProps: emptyObj,
getTheadFilterProps: emptyObj,