UNPKG

react-table-v6

Version:

A fast, lightweight, opinionated table and datagrid built on React

1,573 lines (1,356 loc) 126 kB
(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,