UNPKG

react-table

Version:

Hooks for building lightweight, fast and extendable datagrids for React

1,529 lines (1,303 loc) 154 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) : typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) : (global = global || self, factory(global.ReactTable = {}, global.React)); }(this, (function (exports, React) { 'use strict'; React = React && Object.prototype.hasOwnProperty.call(React, 'default') ? React['default'] : React; function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function _extends() { _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; }; return _extends.apply(this, arguments); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } var renderErr = 'Renderer Error ☝️'; var actions = { init: 'init' }; var defaultRenderer = function defaultRenderer(_ref) { var _ref$value = _ref.value, value = _ref$value === void 0 ? '' : _ref$value; return value; }; var emptyRenderer = function emptyRenderer() { return React.createElement(React.Fragment, null, "\xA0"); }; var defaultColumn = { Cell: defaultRenderer, width: 150, minWidth: 0, maxWidth: Number.MAX_SAFE_INTEGER }; function mergeProps() { for (var _len = arguments.length, propList = new Array(_len), _key = 0; _key < _len; _key++) { propList[_key] = arguments[_key]; } return propList.reduce(function (props, next) { var style = next.style, className = next.className, rest = _objectWithoutPropertiesLoose(next, ["style", "className"]); props = _extends({}, props, {}, rest); if (style) { props.style = props.style ? _extends({}, props.style || {}, {}, style || {}) : style; } if (className) { props.className = props.className ? props.className + ' ' + className : className; } if (props.className === '') { delete props.className; } return props; }, {}); } function handlePropGetter(prevProps, userProps, meta) { // Handle a lambda, pass it the previous props if (typeof userProps === 'function') { return handlePropGetter({}, userProps(prevProps, meta)); } // Handle an array, merge each item as separate props if (Array.isArray(userProps)) { return mergeProps.apply(void 0, [prevProps].concat(userProps)); } // Handle an object by default, merge the two objects return mergeProps(prevProps, userProps); } var makePropGetter = function makePropGetter(hooks, meta) { if (meta === void 0) { meta = {}; } return function (userProps) { if (userProps === void 0) { userProps = {}; } return [].concat(hooks, [userProps]).reduce(function (prev, next) { return handlePropGetter(prev, next, _extends({}, meta, { userProps: userProps })); }, {}); }; }; var reduceHooks = function reduceHooks(hooks, initial, meta, allowUndefined) { if (meta === void 0) { meta = {}; } return hooks.reduce(function (prev, next) { var nextValue = next(prev, meta); { if (!allowUndefined && typeof nextValue === 'undefined') { console.info(next); throw new Error('React Table: A reducer hook ☝️ just returned undefined! This is not allowed.'); } } return nextValue; }, initial); }; var loopHooks = function loopHooks(hooks, context, meta) { if (meta === void 0) { meta = {}; } return hooks.forEach(function (hook) { var nextValue = hook(context, meta); { if (typeof nextValue !== 'undefined') { console.info(hook, nextValue); throw new Error('React Table: A loop-type hook ☝️ just returned a value! This is not allowed.'); } } }); }; function ensurePluginOrder(plugins, befores, pluginName, afters) { if ( afters) { throw new Error("Defining plugins in the \"after\" section of ensurePluginOrder is no longer supported (see plugin " + pluginName + ")"); } var pluginIndex = plugins.findIndex(function (plugin) { return plugin.pluginName === pluginName; }); if (pluginIndex === -1) { { throw new Error("The plugin \"" + pluginName + "\" was not found in the plugin list!\nThis usually means you need to need to name your plugin hook by setting the 'pluginName' property of the hook function, eg:\n\n " + pluginName + ".pluginName = '" + pluginName + "'\n"); } } befores.forEach(function (before) { var beforeIndex = plugins.findIndex(function (plugin) { return plugin.pluginName === before; }); if (beforeIndex > -1 && beforeIndex > pluginIndex) { { throw new Error("React Table: The " + pluginName + " plugin hook must be placed after the " + before + " plugin hook!"); } } }); } function functionalUpdate(updater, old) { return typeof updater === 'function' ? updater(old) : updater; } function useGetLatest(obj) { var ref = React.useRef(); ref.current = obj; return React.useCallback(function () { return ref.current; }, []); } // SSR has issues with useLayoutEffect still, so use useEffect during SSR var safeUseLayoutEffect = typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect; function useMountedLayoutEffect(fn, deps) { var mountedRef = React.useRef(false); safeUseLayoutEffect(function () { if (mountedRef.current) { fn(); } mountedRef.current = true; // eslint-disable-next-line }, deps); } function useAsyncDebounce(defaultFn, defaultWait) { if (defaultWait === void 0) { defaultWait = 0; } var debounceRef = React.useRef({}); var getDefaultFn = useGetLatest(defaultFn); var getDefaultWait = useGetLatest(defaultWait); return React.useCallback( /*#__PURE__*/ function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee2() { var _len2, args, _key2, _args2 = arguments; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: for (_len2 = _args2.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = _args2[_key2]; } if (!debounceRef.current.promise) { debounceRef.current.promise = new Promise(function (resolve, reject) { debounceRef.current.resolve = resolve; debounceRef.current.reject = reject; }); } if (debounceRef.current.timeout) { clearTimeout(debounceRef.current.timeout); } debounceRef.current.timeout = setTimeout( /*#__PURE__*/ _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee() { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: delete debounceRef.current.timeout; _context.prev = 1; _context.t0 = debounceRef.current; _context.next = 5; return getDefaultFn().apply(void 0, args); case 5: _context.t1 = _context.sent; _context.t0.resolve.call(_context.t0, _context.t1); _context.next = 12; break; case 9: _context.prev = 9; _context.t2 = _context["catch"](1); debounceRef.current.reject(_context.t2); case 12: _context.prev = 12; delete debounceRef.current.promise; return _context.finish(12); case 15: case "end": return _context.stop(); } } }, _callee, null, [[1, 9, 12, 15]]); })), getDefaultWait()); return _context2.abrupt("return", debounceRef.current.promise); case 5: case "end": return _context2.stop(); } } }, _callee2); })); return function () { return _ref2.apply(this, arguments); }; }(), [getDefaultFn, getDefaultWait]); } function makeRenderer(instance, column, meta) { if (meta === void 0) { meta = {}; } return function (type, userProps) { if (userProps === void 0) { userProps = {}; } var Comp = typeof type === 'string' ? column[type] : type; if (typeof Comp === 'undefined') { console.info(column); throw new Error(renderErr); } return flexRender(Comp, _extends({}, instance, { column: column }, meta, {}, userProps)); }; } function flexRender(Comp, props) { return isReactComponent(Comp) ? React.createElement(Comp, props) : Comp; } function isReactComponent(component) { return isClassComponent(component) || typeof component === 'function' || isExoticComponent(component); } function isClassComponent(component) { return typeof component === 'function' && function () { var proto = Object.getPrototypeOf(component); return proto.prototype && proto.prototype.isReactComponent; }(); } function isExoticComponent(component) { return typeof component === 'object' && typeof component.$$typeof === 'symbol' && ['react.memo', 'react.forward_ref'].includes(component.$$typeof.description); } function linkColumnStructure(columns, parent, depth) { if (depth === void 0) { depth = 0; } return columns.map(function (column) { column = _extends({}, column, { parent: parent, depth: depth }); assignColumnAccessor(column); if (column.columns) { column.columns = linkColumnStructure(column.columns, column, depth + 1); } return column; }); } function flattenColumns(columns) { return flattenBy(columns, 'columns'); } function assignColumnAccessor(column) { // First check for string accessor var id = column.id, accessor = column.accessor, Header = column.Header; if (typeof accessor === 'string') { id = id || accessor; var accessorPath = accessor.split('.'); accessor = function accessor(row) { return getBy(row, accessorPath); }; } if (!id && typeof Header === 'string' && Header) { id = Header; } if (!id && column.columns) { console.error(column); throw new Error('A column ID (or unique "Header" value) is required!'); } if (!id) { console.error(column); throw new Error('A column ID (or string accessor) is required!'); } Object.assign(column, { id: id, accessor: accessor }); return column; } function decorateColumn(column, userDefaultColumn) { if (!userDefaultColumn) { throw new Error(); } Object.assign(column, _extends({ // Make sure there is a fallback header, just in case Header: emptyRenderer, Footer: emptyRenderer }, defaultColumn, {}, userDefaultColumn, {}, column)); Object.assign(column, { originalWidth: column.width }); return column; } // Build the header groups from the bottom up function makeHeaderGroups(allColumns, defaultColumn, additionalHeaderProperties) { if (additionalHeaderProperties === void 0) { additionalHeaderProperties = function additionalHeaderProperties() { return {}; }; } var headerGroups = []; var scanColumns = allColumns; var uid = 0; var getUID = function getUID() { return uid++; }; var _loop = function _loop() { // The header group we are creating var headerGroup = { headers: [] }; // The parent columns we're going to scan next var parentColumns = []; var hasParents = scanColumns.some(function (d) { return d.parent; }); // Scan each column for parents scanColumns.forEach(function (column) { // What is the latest (last) parent column? var latestParentColumn = [].concat(parentColumns).reverse()[0]; var newParent; if (hasParents) { // If the column has a parent, add it if necessary if (column.parent) { newParent = _extends({}, column.parent, { originalId: column.parent.id, id: column.parent.id + "_" + getUID(), headers: [column] }, additionalHeaderProperties(column)); } else { // If other columns have parents, we'll need to add a place holder if necessary var originalId = column.id + "_placeholder"; newParent = decorateColumn(_extends({ originalId: originalId, id: column.id + "_placeholder_" + getUID(), placeholderOf: column, headers: [column] }, additionalHeaderProperties(column)), defaultColumn); } // If the resulting parent columns are the same, just add // the column and increment the header span if (latestParentColumn && latestParentColumn.originalId === newParent.originalId) { latestParentColumn.headers.push(column); } else { parentColumns.push(newParent); } } headerGroup.headers.push(column); }); headerGroups.push(headerGroup); // Start scanning the parent columns scanColumns = parentColumns; }; while (scanColumns.length) { _loop(); } return headerGroups.reverse(); } var pathObjCache = new Map(); function getBy(obj, path, def) { if (!path) { return obj; } var cacheKey = typeof path === 'function' ? path : JSON.stringify(path); var pathObj = pathObjCache.get(cacheKey) || function () { var pathObj = makePathArray(path); pathObjCache.set(cacheKey, pathObj); return pathObj; }(); var val; try { val = pathObj.reduce(function (cursor, pathPart) { return cursor[pathPart]; }, obj); } catch (e) {// continue regardless of error } return typeof val !== 'undefined' ? val : def; } function getFirstDefined() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } for (var i = 0; i < args.length; i += 1) { if (typeof args[i] !== 'undefined') { return args[i]; } } } function isFunction(a) { if (typeof a === 'function') { return a; } } function flattenBy(arr, key) { var flat = []; var recurse = function recurse(arr) { arr.forEach(function (d) { if (!d[key]) { flat.push(d); } else { recurse(d[key]); } }); }; recurse(arr); return flat; } function expandRows(rows, _ref) { var manualExpandedKey = _ref.manualExpandedKey, expanded = _ref.expanded, _ref$expandSubRows = _ref.expandSubRows, expandSubRows = _ref$expandSubRows === void 0 ? true : _ref$expandSubRows; var expandedRows = []; var handleRow = function handleRow(row, addToExpandedRows) { if (addToExpandedRows === void 0) { addToExpandedRows = true; } row.isExpanded = row.original && row.original[manualExpandedKey] || expanded[row.id]; row.canExpand = row.subRows && !!row.subRows.length; if (addToExpandedRows) { expandedRows.push(row); } if (row.subRows && row.subRows.length && row.isExpanded) { row.subRows.forEach(function (row) { return handleRow(row, expandSubRows); }); } }; rows.forEach(function (row) { return handleRow(row); }); return expandedRows; } function getFilterMethod(filter, userFilterTypes, filterTypes) { return isFunction(filter) || userFilterTypes[filter] || filterTypes[filter] || filterTypes.text; } function shouldAutoRemoveFilter(autoRemove, value, column) { return autoRemove ? autoRemove(value, column) : typeof value === 'undefined'; } function unpreparedAccessWarning() { throw new Error('React-Table: You have not called prepareRow(row) one or more rows you are attempting to render.'); } var passiveSupported = null; function passiveEventSupported() { // memoize support to avoid adding multiple test events if (typeof passiveSupported === 'boolean') return passiveSupported; var supported = false; try { var options = { get passive() { supported = true; return false; } }; window.addEventListener('test', null, options); window.removeEventListener('test', null, options); } catch (err) { supported = false; } passiveSupported = supported; return passiveSupported; } // var reOpenBracket = /\[/g; var reCloseBracket = /\]/g; function makePathArray(obj) { return flattenDeep(obj) // remove all periods in parts .map(function (d) { return String(d).replace('.', '_'); }) // join parts using period .join('.') // replace brackets with periods .replace(reOpenBracket, '.').replace(reCloseBracket, '') // split it back out on periods .split('.'); } function flattenDeep(arr, newArr) { if (newArr === void 0) { newArr = []; } if (!Array.isArray(arr)) { newArr.push(arr); } else { for (var i = 0; i < arr.length; i += 1) { flattenDeep(arr[i], newArr); } } return newArr; } var defaultGetTableProps = function defaultGetTableProps(props) { return _extends({ role: 'table' }, props); }; var defaultGetTableBodyProps = function defaultGetTableBodyProps(props) { return _extends({ role: 'rowgroup' }, props); }; var defaultGetHeaderProps = function defaultGetHeaderProps(props, _ref) { var column = _ref.column; return _extends({ key: "header_" + column.id, colSpan: column.totalVisibleHeaderCount, role: 'columnheader' }, props); }; var defaultGetFooterProps = function defaultGetFooterProps(props, _ref2) { var column = _ref2.column; return _extends({ key: "footer_" + column.id, colSpan: column.totalVisibleHeaderCount }, props); }; var defaultGetHeaderGroupProps = function defaultGetHeaderGroupProps(props, _ref3) { var index = _ref3.index; return _extends({ key: "headerGroup_" + index, role: 'row' }, props); }; var defaultGetFooterGroupProps = function defaultGetFooterGroupProps(props, _ref4) { var index = _ref4.index; return _extends({ key: "footerGroup_" + index }, props); }; var defaultGetRowProps = function defaultGetRowProps(props, _ref5) { var row = _ref5.row; return _extends({ key: "row_" + row.id, role: 'row' }, props); }; var defaultGetCellProps = function defaultGetCellProps(props, _ref6) { var cell = _ref6.cell; return _extends({ key: "cell_" + cell.row.id + "_" + cell.column.id, role: 'cell' }, props); }; function makeDefaultPluginHooks() { return { useOptions: [], stateReducers: [], useControlledState: [], columns: [], columnsDeps: [], allColumns: [], allColumnsDeps: [], accessValue: [], materializedColumns: [], materializedColumnsDeps: [], useInstanceAfterData: [], visibleColumns: [], visibleColumnsDeps: [], headerGroups: [], headerGroupsDeps: [], useInstanceBeforeDimensions: [], useInstance: [], prepareRow: [], getTableProps: [defaultGetTableProps], getTableBodyProps: [defaultGetTableBodyProps], getHeaderGroupProps: [defaultGetHeaderGroupProps], getFooterGroupProps: [defaultGetFooterGroupProps], getHeaderProps: [defaultGetHeaderProps], getFooterProps: [defaultGetFooterProps], getRowProps: [defaultGetRowProps], getCellProps: [defaultGetCellProps], useFinalInstance: [] }; } actions.resetHiddenColumns = 'resetHiddenColumns'; actions.toggleHideColumn = 'toggleHideColumn'; actions.setHiddenColumns = 'setHiddenColumns'; actions.toggleHideAllColumns = 'toggleHideAllColumns'; var useColumnVisibility = function useColumnVisibility(hooks) { hooks.getToggleHiddenProps = [defaultGetToggleHiddenProps]; hooks.getToggleHideAllColumnsProps = [defaultGetToggleHideAllColumnsProps]; hooks.stateReducers.push(reducer); hooks.useInstanceBeforeDimensions.push(useInstanceBeforeDimensions); hooks.headerGroupsDeps.push(function (deps, _ref) { var instance = _ref.instance; return [].concat(deps, [instance.state.hiddenColumns]); }); hooks.useInstance.push(useInstance); }; useColumnVisibility.pluginName = 'useColumnVisibility'; var defaultGetToggleHiddenProps = function defaultGetToggleHiddenProps(props, _ref2) { var column = _ref2.column; return [props, { onChange: function onChange(e) { column.toggleHidden(!e.target.checked); }, style: { cursor: 'pointer' }, checked: column.isVisible, title: 'Toggle Column Visible' }]; }; var defaultGetToggleHideAllColumnsProps = function defaultGetToggleHideAllColumnsProps(props, _ref3) { var instance = _ref3.instance; return [props, { onChange: function onChange(e) { instance.toggleHideAllColumns(!e.target.checked); }, style: { cursor: 'pointer' }, checked: !instance.allColumnsHidden && !instance.state.hiddenColumns.length, title: 'Toggle All Columns Hidden', indeterminate: !instance.allColumnsHidden && instance.state.hiddenColumns.length }]; }; function reducer(state, action, previousState, instance) { if (action.type === actions.init) { return _extends({ hiddenColumns: [] }, state); } if (action.type === actions.resetHiddenColumns) { return _extends({}, state, { hiddenColumns: instance.initialState.hiddenColumns || [] }); } if (action.type === actions.toggleHideColumn) { var should = typeof action.value !== 'undefined' ? action.value : !state.hiddenColumns.includes(action.columnId); var hiddenColumns = should ? [].concat(state.hiddenColumns, [action.columnId]) : state.hiddenColumns.filter(function (d) { return d !== action.columnId; }); return _extends({}, state, { hiddenColumns: hiddenColumns }); } if (action.type === actions.setHiddenColumns) { return _extends({}, state, { hiddenColumns: functionalUpdate(action.value, state.hiddenColumns) }); } if (action.type === actions.toggleHideAllColumns) { var shouldAll = typeof action.value !== 'undefined' ? action.value : !state.hiddenColumns.length; return _extends({}, state, { hiddenColumns: shouldAll ? instance.allColumns.map(function (d) { return d.id; }) : [] }); } } function useInstanceBeforeDimensions(instance) { var headers = instance.headers, hiddenColumns = instance.state.hiddenColumns; var isMountedRef = React.useRef(false); if (!isMountedRef.current) ; var handleColumn = function handleColumn(column, parentVisible) { column.isVisible = parentVisible && !hiddenColumns.includes(column.id); var totalVisibleHeaderCount = 0; if (column.headers && column.headers.length) { column.headers.forEach(function (subColumn) { return totalVisibleHeaderCount += handleColumn(subColumn, column.isVisible); }); } else { totalVisibleHeaderCount = column.isVisible ? 1 : 0; } column.totalVisibleHeaderCount = totalVisibleHeaderCount; return totalVisibleHeaderCount; }; var totalVisibleHeaderCount = 0; headers.forEach(function (subHeader) { return totalVisibleHeaderCount += handleColumn(subHeader, true); }); } function useInstance(instance) { var columns = instance.columns, flatHeaders = instance.flatHeaders, dispatch = instance.dispatch, allColumns = instance.allColumns, getHooks = instance.getHooks, hiddenColumns = instance.state.hiddenColumns, _instance$autoResetHi = instance.autoResetHiddenColumns, autoResetHiddenColumns = _instance$autoResetHi === void 0 ? true : _instance$autoResetHi; var getInstance = useGetLatest(instance); var allColumnsHidden = allColumns.length === hiddenColumns.length; var toggleHideColumn = React.useCallback(function (columnId, value) { return dispatch({ type: actions.toggleHideColumn, columnId: columnId, value: value }); }, [dispatch]); var setHiddenColumns = React.useCallback(function (value) { return dispatch({ type: actions.setHiddenColumns, value: value }); }, [dispatch]); var toggleHideAllColumns = React.useCallback(function (value) { return dispatch({ type: actions.toggleHideAllColumns, value: value }); }, [dispatch]); var getToggleHideAllColumnsProps = makePropGetter(getHooks().getToggleHideAllColumnsProps, { instance: getInstance() }); flatHeaders.forEach(function (column) { column.toggleHidden = function (value) { dispatch({ type: actions.toggleHideColumn, columnId: column.id, value: value }); }; column.getToggleHiddenProps = makePropGetter(getHooks().getToggleHiddenProps, { instance: getInstance(), column: column }); }); var getAutoResetHiddenColumns = useGetLatest(autoResetHiddenColumns); useMountedLayoutEffect(function () { if (getAutoResetHiddenColumns()) { dispatch({ type: actions.resetHiddenColumns }); } }, [dispatch, columns]); Object.assign(instance, { allColumnsHidden: allColumnsHidden, toggleHideColumn: toggleHideColumn, setHiddenColumns: setHiddenColumns, toggleHideAllColumns: toggleHideAllColumns, getToggleHideAllColumnsProps: getToggleHideAllColumnsProps }); } var defaultInitialState = {}; var defaultColumnInstance = {}; var defaultReducer = function defaultReducer(state, action, prevState) { return state; }; var defaultGetSubRows = function defaultGetSubRows(row, index) { return row.subRows || []; }; var defaultGetRowId = function defaultGetRowId(row, index, parent) { return "" + (parent ? [parent.id, index].join('.') : index); }; var defaultUseControlledState = function defaultUseControlledState(d) { return d; }; function applyDefaults(props) { var _props$initialState = props.initialState, initialState = _props$initialState === void 0 ? defaultInitialState : _props$initialState, _props$defaultColumn = props.defaultColumn, defaultColumn = _props$defaultColumn === void 0 ? defaultColumnInstance : _props$defaultColumn, _props$getSubRows = props.getSubRows, getSubRows = _props$getSubRows === void 0 ? defaultGetSubRows : _props$getSubRows, _props$getRowId = props.getRowId, getRowId = _props$getRowId === void 0 ? defaultGetRowId : _props$getRowId, _props$stateReducer = props.stateReducer, stateReducer = _props$stateReducer === void 0 ? defaultReducer : _props$stateReducer, _props$useControlledS = props.useControlledState, useControlledState = _props$useControlledS === void 0 ? defaultUseControlledState : _props$useControlledS, rest = _objectWithoutPropertiesLoose(props, ["initialState", "defaultColumn", "getSubRows", "getRowId", "stateReducer", "useControlledState"]); return _extends({}, rest, { initialState: initialState, defaultColumn: defaultColumn, getSubRows: getSubRows, getRowId: getRowId, stateReducer: stateReducer, useControlledState: useControlledState }); } var useTable = function useTable(props) { for (var _len = arguments.length, plugins = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { plugins[_key - 1] = arguments[_key]; } // Apply default props props = applyDefaults(props); // Add core plugins plugins = [useColumnVisibility].concat(plugins); // Create the table instance var instanceRef = React.useRef({}); // Create a getter for the instance (helps avoid a lot of potential memory leaks) var getInstance = useGetLatest(instanceRef.current); // Assign the props, plugins and hooks to the instance Object.assign(getInstance(), _extends({}, props, { plugins: plugins, hooks: makeDefaultPluginHooks() })); // Allow plugins to register hooks as early as possible plugins.filter(Boolean).forEach(function (plugin) { plugin(getInstance().hooks); }); // Consume all hooks and make a getter for them var getHooks = useGetLatest(getInstance().hooks); getInstance().getHooks = getHooks; delete getInstance().hooks; // Allow useOptions hooks to modify the options coming into the table Object.assign(getInstance(), reduceHooks(getHooks().useOptions, applyDefaults(props))); var _getInstance = getInstance(), data = _getInstance.data, userColumns = _getInstance.columns, initialState = _getInstance.initialState, defaultColumn = _getInstance.defaultColumn, getSubRows = _getInstance.getSubRows, getRowId = _getInstance.getRowId, stateReducer = _getInstance.stateReducer, useControlledState = _getInstance.useControlledState; // Setup user reducer ref var getStateReducer = useGetLatest(stateReducer); // Build the reducer var reducer = React.useCallback(function (state, action) { // Detect invalid actions if (!action.type) { console.info({ action: action }); throw new Error('Unknown Action 👆'); } // Reduce the state from all plugin reducers return [].concat(getHooks().stateReducers, Array.isArray(getStateReducer()) ? getStateReducer() : [getStateReducer()]).reduce(function (s, handler) { return handler(s, action, state, getInstance()) || s; }, state); }, [getHooks, getStateReducer, getInstance]); // Start the reducer var _React$useReducer = React.useReducer(reducer, undefined, function () { return reducer(initialState, { type: actions.init }); }), reducerState = _React$useReducer[0], dispatch = _React$useReducer[1]; // Allow the user to control the final state with hooks var state = reduceHooks([].concat(getHooks().useControlledState, [useControlledState]), reducerState, { instance: getInstance() }); Object.assign(getInstance(), { state: state, dispatch: dispatch }); // Decorate All the columns var columns = React.useMemo(function () { return linkColumnStructure(reduceHooks(getHooks().columns, userColumns, { instance: getInstance() })); }, [getHooks, getInstance, userColumns].concat(reduceHooks(getHooks().columnsDeps, [], { instance: getInstance() }))); getInstance().columns = columns; // Get the flat list of all columns and allow hooks to decorate // those columns (and trigger this memoization via deps) var allColumns = React.useMemo(function () { return reduceHooks(getHooks().allColumns, flattenColumns(columns), { instance: getInstance() }).map(assignColumnAccessor); }, [columns, getHooks, getInstance].concat(reduceHooks(getHooks().allColumnsDeps, [], { instance: getInstance() }))); getInstance().allColumns = allColumns; // Access the row model using initial columns var _React$useMemo = React.useMemo(function () { var rows = []; var flatRows = []; var rowsById = {}; var allColumnsQueue = [].concat(allColumns); while (allColumnsQueue.length) { var column = allColumnsQueue.shift(); accessRowsForColumn({ data: data, rows: rows, flatRows: flatRows, rowsById: rowsById, column: column, getRowId: getRowId, getSubRows: getSubRows, accessValueHooks: getHooks().accessValue, getInstance: getInstance }); } return [rows, flatRows, rowsById]; }, [allColumns, data, getRowId, getSubRows, getHooks, getInstance]), rows = _React$useMemo[0], flatRows = _React$useMemo[1], rowsById = _React$useMemo[2]; Object.assign(getInstance(), { rows: rows, initialRows: [].concat(rows), flatRows: flatRows, rowsById: rowsById // materializedColumns, }); loopHooks(getHooks().useInstanceAfterData, getInstance()); // Get the flat list of all columns AFTER the rows // have been access, and allow hooks to decorate // those columns (and trigger this memoization via deps) var visibleColumns = React.useMemo(function () { return reduceHooks(getHooks().visibleColumns, allColumns, { instance: getInstance() }).map(function (d) { return decorateColumn(d, defaultColumn); }); }, [getHooks, allColumns, getInstance, defaultColumn].concat(reduceHooks(getHooks().visibleColumnsDeps, [], { instance: getInstance() }))); // Combine new visible columns with all columns allColumns = React.useMemo(function () { var columns = [].concat(visibleColumns); allColumns.forEach(function (column) { if (!columns.find(function (d) { return d.id === column.id; })) { columns.push(column); } }); return columns; }, [allColumns, visibleColumns]); getInstance().allColumns = allColumns; { var duplicateColumns = allColumns.filter(function (column, i) { return allColumns.findIndex(function (d) { return d.id === column.id; }) !== i; }); if (duplicateColumns.length) { console.info(allColumns); throw new Error("Duplicate columns were found with ids: \"" + duplicateColumns.map(function (d) { return d.id; }).join(', ') + "\" in the columns array above"); } } // Make the headerGroups var headerGroups = React.useMemo(function () { return reduceHooks(getHooks().headerGroups, makeHeaderGroups(visibleColumns, defaultColumn), getInstance()); }, [getHooks, visibleColumns, defaultColumn, getInstance].concat(reduceHooks(getHooks().headerGroupsDeps, [], { instance: getInstance() }))); getInstance().headerGroups = headerGroups; // Get the first level of headers var headers = React.useMemo(function () { return headerGroups.length ? headerGroups[0].headers : []; }, [headerGroups]); getInstance().headers = headers; // Provide a flat header list for utilities getInstance().flatHeaders = headerGroups.reduce(function (all, headerGroup) { return [].concat(all, headerGroup.headers); }, []); loopHooks(getHooks().useInstanceBeforeDimensions, getInstance()); // Filter columns down to visible ones var visibleColumnsDep = visibleColumns.filter(function (d) { return d.isVisible; }).map(function (d) { return d.id; }).sort().join('_'); visibleColumns = React.useMemo(function () { return visibleColumns.filter(function (d) { return d.isVisible; }); }, // eslint-disable-next-line react-hooks/exhaustive-deps [visibleColumns, visibleColumnsDep]); getInstance().visibleColumns = visibleColumns; // Header Visibility is needed by this point var _calculateHeaderWidth = calculateHeaderWidths(headers), totalColumnsMinWidth = _calculateHeaderWidth[0], totalColumnsWidth = _calculateHeaderWidth[1], totalColumnsMaxWidth = _calculateHeaderWidth[2]; getInstance().totalColumnsMinWidth = totalColumnsMinWidth; getInstance().totalColumnsWidth = totalColumnsWidth; getInstance().totalColumnsMaxWidth = totalColumnsMaxWidth; loopHooks(getHooks().useInstance, getInstance()) // Each materialized header needs to be assigned a render function and other // prop getter properties here. ; [].concat(getInstance().flatHeaders, getInstance().allColumns).forEach(function (column) { // Give columns/headers rendering power column.render = makeRenderer(getInstance(), column); // Give columns/headers a default getHeaderProps column.getHeaderProps = makePropGetter(getHooks().getHeaderProps, { instance: getInstance(), column: column }); // Give columns/headers a default getFooterProps column.getFooterProps = makePropGetter(getHooks().getFooterProps, { instance: getInstance(), column: column }); }); getInstance().headerGroups = React.useMemo(function () { return headerGroups.filter(function (headerGroup, i) { // Filter out any headers and headerGroups that don't have visible columns headerGroup.headers = headerGroup.headers.filter(function (column) { var recurse = function recurse(headers) { return headers.filter(function (column) { if (column.headers) { return recurse(column.headers); } return column.isVisible; }).length; }; if (column.headers) { return recurse(column.headers); } return column.isVisible; }); // Give headerGroups getRowProps if (headerGroup.headers.length) { headerGroup.getHeaderGroupProps = makePropGetter(getHooks().getHeaderGroupProps, { instance: getInstance(), headerGroup: headerGroup, index: i }); headerGroup.getFooterGroupProps = makePropGetter(getHooks().getFooterGroupProps, { instance: getInstance(), headerGroup: headerGroup, index: i }); return true; } return false; }); }, [headerGroups, getInstance, getHooks]); getInstance().footerGroups = [].concat(getInstance().headerGroups).reverse(); // The prepareRow function is absolutely necessary and MUST be called on // any rows the user wishes to be displayed. getInstance().prepareRow = React.useCallback(function (row) { row.getRowProps = makePropGetter(getHooks().getRowProps, { instance: getInstance(), row: row }); // Build the visible cells for each row row.allCells = allColumns.map(function (column) { var value = row.values[column.id]; var cell = { column: column, row: row, value: value }; // Give each cell a getCellProps base cell.getCellProps = makePropGetter(getHooks().getCellProps, { instance: getInstance(), cell: cell }); // Give each cell a renderer function (supports multiple renderers) cell.render = makeRenderer(getInstance(), column, { row: row, cell: cell, value: value }); return cell; }); row.cells = visibleColumns.map(function (column) { return row.allCells.find(function (cell) { return cell.column.id === column.id; }); }); // need to apply any row specific hooks (useExpanded requires this) loopHooks(getHooks().prepareRow, row, { instance: getInstance() }); }, [getHooks, getInstance, allColumns, visibleColumns]); getInstance().getTableProps = makePropGetter(getHooks().getTableProps, { instance: getInstance() }); getInstance().getTableBodyProps = makePropGetter(getHooks().getTableBodyProps, { instance: getInstance() }); loopHooks(getHooks().useFinalInstance, getInstance()); return getInstance(); }; function calculateHeaderWidths(headers, left) { if (left === void 0) { left = 0; } var sumTotalMinWidth = 0; var sumTotalWidth = 0; var sumTotalMaxWidth = 0; var sumTotalFlexWidth = 0; headers.forEach(function (header) { var subHeaders = header.headers; header.totalLeft = left; if (subHeaders && subHeaders.length) { var _calculateHeaderWidth2 = calculateHeaderWidths(subHeaders, left), totalMinWidth = _calculateHeaderWidth2[0], totalWidth = _calculateHeaderWidth2[1], totalMaxWidth = _calculateHeaderWidth2[2], totalFlexWidth = _calculateHeaderWidth2[3]; header.totalMinWidth = totalMinWidth; header.totalWidth = totalWidth; header.totalMaxWidth = totalMaxWidth; header.totalFlexWidth = totalFlexWidth; } else { header.totalMinWidth = header.minWidth; header.totalWidth = Math.min(Math.max(header.minWidth, header.width), header.maxWidth); header.totalMaxWidth = header.maxWidth; header.totalFlexWidth = header.canResize ? header.totalWidth : 0; } if (header.isVisible) { left += header.totalWidth; sumTotalMinWidth += header.totalMinWidth; sumTotalWidth += header.totalWidth; sumTotalMaxWidth += header.totalMaxWidth; sumTotalFlexWidth += header.totalFlexWidth; } }); return [sumTotalMinWidth, sumTotalWidth, sumTotalMaxWidth, sumTotalFlexWidth]; } function accessRowsForColumn(_ref) { var data = _ref.data, rows = _ref.rows, flatRows = _ref.flatRows, rowsById = _ref.rowsById, column = _ref.column, getRowId = _ref.getRowId, getSubRows = _ref.getSubRows, accessValueHooks = _ref.accessValueHooks, getInstance = _ref.getInstance; // Access the row's data column-by-column // We do it this way so we can incrementally add materialized // columns after the first pass and avoid excessive looping var accessRow = function accessRow(originalRow, rowIndex, depth, parent, parentRows) { if (depth === void 0) { depth = 0; } // Keep the original reference around var original = originalRow; var id = getRowId(originalRow, rowIndex, parent); var row = rowsById[id]; // If the row hasn't been created, let's make it if (!row) { row = { id: id, original: original, index: rowIndex, depth: depth, cells: [{}] // This is a dummy cell }; // Override common array functions (and the dummy cell's getCellProps function) // to show an error if it is accessed without calling prepareRow row.cells.map = unpreparedAccessWarning; row.cells.filter = unpreparedAccessWarning; row.cells.forEach = unpreparedAccessWarning; row.cells[0].getCellProps = unpreparedAccessWarning; // Create the cells and values row.values = {}; // Push this row into the parentRows array parentRows.push(row); // Keep track of every row in a flat array flatRows.push(row); // Also keep track of every row by its ID rowsById[id] = row; // Get the original subrows row.originalSubRows = getSubRows(originalRow, rowIndex); // Then recursively access them if (row.originalSubRows) { var subRows = []; row.originalSubRows.forEach(function (d, i) { return accessRow(d, i, depth + 1, row, subRows); }); // Keep the new subRows array on the row row.subRows = subRows; } } else if (row.subRows) { // If the row exists, then it's already been accessed // Keep recursing, but don't worry about passing the // accumlator array (those rows already exist) row.originalSubRows.forEach(function (d, i) { return accessRow(d, i, depth + 1, row); }); } // If the column has an accessor, use it to get a value if (column.accessor) { row.values[column.id] = column.accessor(originalRow, rowIndex, row, parentRows, data); } // Allow plugins to manipulate the column value row.values[column.id] = reduceHooks(accessValueHooks, row.values[column.id], { row: row, column: column, instance: getInstance() }, true); }; data.forEach(function (originalRow, rowIndex) { return accessRow(originalRow, rowIndex, 0, undefined, rows); }); } actions.resetExpanded = 'resetExpanded'; actions.toggleRowExpanded = 'toggleRowExpanded'; actions.toggleAllRowsExpanded = 'toggleAllRowsExpanded'; var useExpanded = function useExpanded(hooks) { hooks.getToggleAllRowsExpandedProps = [defaultGetToggleAllRowsExpandedProps]; hooks.getToggleRowExpandedProps = [defaultGetToggleRowExpandedProps]; hooks.stateReducers.push(reducer$1); hooks.useInstance.push(useInstance$1); hooks.prepareRow.push(prepareRow); }; useExpanded.pluginName = 'useExpanded'; var defaultGetToggleAllRowsExpandedProps = function defaultGetToggleAllRowsExpandedProps(props, _ref) { var instance = _ref.instance; return [props, { onClick: function onClick(e) { instance.toggleAllRowsExpanded(); }, style: { cursor: 'pointer' }, title: 'Toggle All Rows Expanded' }]; }; var defaultGetToggleRowExpandedProps = function defaultGetToggleRowExpandedProps(props, _ref2) { var row = _ref2.row; return [props, { onClick: function onClick() { row.toggleRowExpanded(); }, style: { cursor: 'pointer' }, title: 'Toggle Row Expanded' }]; }; // Reducer function reducer$1(state, action, previousState, instance) { if (action.type === actions.init) { return _extends({ expanded: {} }, state); } if (action.type === actions.resetExpanded) { return _extends({}, state, { expanded: instance.initialState.expanded || {} }); } if (action.type === actions.toggleAllRowsExpanded) { var value = action.value; var rowsById = instance.rowsById; var isAllRowsExpanded = Object.keys(rowsById).length === Object.keys(state.expanded).length; var expandAll = typeof value !== 'undefined' ? value : !isAllRowsExpanded; if (expandAll) { var expanded = {}; Object.keys(rowsById).forEach(function (rowId) { expanded[rowId] = true; }); return _extends({}, state, { expanded: expanded }); } return _extends({}, state, { expanded: {} }); } if (action.type === actions.toggleRowExpanded) { var id = action.id, setExpanded = action.value; var exists = state.expanded[id]; var shouldExist = typeof setExpanded !== 'undefined' ? setExpanded : !exists; if (!exists && shouldExist) { var _extends2; return _extends({}, state, { expanded: _extends({}, state.expanded, (_extends2 = {}, _extends2[id] = true, _extends2)) }); } else if (exists && !shouldExist) { var _state$expanded = state.expanded, _ = _state$expanded[id], rest = _objectWithoutProper