\n {renderTemplate(language.pageNumbers, { page, pages: totalPages })}\n
\n )\n }\n\n const prevButton = (\n \n
\n {pageInfo}\n {pageSizeOptions}\n
\n\n
\n {prevButton}\n {pageNumbers}\n {nextButton}\n
\n
\n )\n }\n}\n\nPagination.propTypes = {\n paginationType: PropTypes.oneOf(['numbers', 'jump', 'simple']),\n pageSizeOptions: PropTypes.arrayOf(PropTypes.number),\n showPageSizeOptions: PropTypes.bool,\n showPageInfo: PropTypes.bool,\n page: PropTypes.number.isRequired,\n pages: PropTypes.number.isRequired,\n pageSize: PropTypes.number.isRequired,\n pageRowCount: PropTypes.number.isRequired,\n canPrevious: PropTypes.bool.isRequired,\n canNext: PropTypes.bool.isRequired,\n onPageChange: PropTypes.func.isRequired,\n onPageSizeChange: PropTypes.func.isRequired,\n rowCount: PropTypes.number.isRequired,\n theme: PropTypes.shape({\n paginationStyle: PropTypes.object\n }),\n language: PropTypes.shape({\n pageNext: PropTypes.string,\n pagePrevious: PropTypes.string,\n pageNumbers: PropTypes.string,\n pageInfo: PropTypes.string,\n pageSizeOptions: PropTypes.string,\n pageNextLabel: PropTypes.string,\n pagePreviousLabel: PropTypes.string,\n pageNumberLabel: PropTypes.string,\n pageJumpLabel: PropTypes.string,\n pageSizeOptionsLabel: PropTypes.string\n })\n}\n\nPagination.defaultProps = {\n paginationType: 'numbers',\n pageSizeOptions: [10, 25, 50, 100],\n showPageInfo: true,\n language: defaultLanguage\n}\n","import React from 'react'\nimport PropTypes from 'prop-types'\n\nimport { isBrowser } from './utils'\n\nexport default class WidgetContainer extends React.Component {\n componentDidMount() {\n this.staticRender()\n }\n\n staticRender() {\n if (!window.HTMLWidgets) {\n return\n }\n if (!WidgetContainer.throttled) {\n window.HTMLWidgets.staticRender()\n // Throttle static rendering since it targets the entire document\n WidgetContainer.throttled = true\n if (typeof setTimeout !== 'undefined') {\n setTimeout(() => {\n if (WidgetContainer.lastCall) {\n window.HTMLWidgets.staticRender()\n }\n WidgetContainer.throttled = false\n WidgetContainer.lastCall = false\n })\n }\n } else {\n WidgetContainer.lastCall = true\n }\n }\n\n render() {\n // Don't serialize HTML widget HTML/scripts when server-side rendering:\n // 1. Most HTML widgets are client-side rendered and wouldn't benefit much from SSR.\n // 2. This keeps the initial HTML payload slim, as the widget script data would be\n // unnecessarily duplicated.\n // 3. Problems can occur when multiple instances of the same HTML widget type\n // are embedded in different tables, and the global HTMLWidgets.staticRender()\n // renders HTML widgets in other tables before those other tables are hydrated\n // (each table lives in its own React root). When other tables are hydrated,\n // the HTML widgets there will get wiped out, but not rerendered on the next\n // staticRender() because the root widget element is already marked as\n // html-widget-static-bound. This also helps keep the initial HTML payload slim,\n // as the widget script data would get unnecessarily duplicated.\n if (!isBrowser()) {\n return null\n }\n return this.props.children\n }\n}\n\nWidgetContainer.propTypes = {\n children: PropTypes.node\n}\n","// useFlexLayout modified to:\n// - Fix flex widths when resizing is disabled (don't use column.totalFlexWidth)\n// - Support resizing to actual min and max column widths (not flex widths)\n// - Set min width on thead/tbody/tfoot instead of table for responsive, horizontal scrolling.\n// Tables should use the new instance.getTheadProps and instance.getTfootProps for this.\n// - Include resized widths in table min width to prevent glitches with sticky headers/footers\n// - Exclude redundant styles\n\nimport { useGetLatest, makePropGetter } from 'react-table'\n\nexport default function useFlexLayout(hooks) {\n hooks.getTheadProps = [getRowGroupStyles]\n hooks.getTfootProps = [getRowGroupStyles]\n hooks.getTableBodyProps.push(getRowGroupStyles)\n hooks.getRowProps.push(getRowStyles)\n hooks.getHeaderGroupProps.push(getRowStyles)\n hooks.getFooterGroupProps.push(getRowStyles)\n hooks.getHeaderProps.push(getHeaderProps)\n hooks.getCellProps.push(getCellProps)\n hooks.getFooterProps.push(getFooterProps)\n hooks.useInstance.push(useInstance)\n}\n\nuseFlexLayout.pluginName = 'useFlexLayout'\n\n// Set min-width for thead and tfoot. Include resized widths in min width\n// (using totalColumnsWidth over totalColumnsMinWidth) so cells don't overlap\n// with sticky headers and footers when the total resized width is greater than\n// the total min width.\nconst getRowGroupStyles = (props, { instance }) => {\n return [\n props,\n {\n style: {\n minWidth: asPx(instance.totalColumnsWidth)\n }\n }\n ]\n}\n\nconst getRowStyles = (props, { instance }) => {\n return [\n props,\n {\n style: {\n flex: '1 0 auto',\n minWidth: asPx(instance.totalColumnsWidth)\n }\n }\n ]\n}\n\nconst getHeaderProps = (props, { column }) => {\n // Don't set max width if MAX_SAFE_INTEGER (the default for column.maxWidth)\n const maxWidth = column.totalMaxWidth < Number.MAX_SAFE_INTEGER ? column.totalMaxWidth : null\n return [\n props,\n {\n style: {\n flex: `${column.flexWidth} 0 auto`,\n minWidth: asPx(column.totalMinWidth),\n width: asPx(column.totalWidth),\n maxWidth: asPx(maxWidth)\n }\n }\n ]\n}\n\nconst getCellProps = (props, { cell }) => {\n const maxWidth =\n cell.column.totalMaxWidth < Number.MAX_SAFE_INTEGER ? cell.column.totalMaxWidth : null\n return [\n props,\n {\n style: {\n flex: `${cell.column.flexWidth} 0 auto`,\n minWidth: asPx(cell.column.totalMinWidth),\n width: asPx(cell.column.totalWidth),\n maxWidth: asPx(maxWidth)\n }\n }\n ]\n}\n\nconst getFooterProps = (props, { column }) => {\n const maxWidth = column.totalMaxWidth < Number.MAX_SAFE_INTEGER ? column.totalMaxWidth : null\n return [\n props,\n {\n style: {\n flex: `${column.flexWidth} 0 auto`,\n minWidth: asPx(column.totalMinWidth),\n width: asPx(column.totalWidth),\n maxWidth: asPx(maxWidth)\n }\n }\n ]\n}\n\nfunction useInstance(instance) {\n const { headers, state, getHooks } = instance\n\n const resizedWidths = state.columnResizing.columnWidths\n\n // Manually calculate flex widths instead of using column.totalFlexWidth\n function calculateFlexWidths(columns) {\n let totalFlexWidth = 0\n columns.forEach(column => {\n if (column.headers) {\n column.flexWidth = calculateFlexWidths(column.headers)\n } else {\n // If the column has been resized or has fixed width, flex width = 0.\n // Otherwise, flex width = min width.\n if (resizedWidths[column.id] != null) {\n column.flexWidth = 0\n } else {\n const isFixedWidth = column.totalMinWidth === column.totalMaxWidth\n column.flexWidth = isFixedWidth ? 0 : column.totalMinWidth\n }\n }\n if (column.isVisible) {\n totalFlexWidth += column.flexWidth\n }\n })\n return totalFlexWidth\n }\n\n calculateFlexWidths(headers)\n\n const getInstance = useGetLatest(instance)\n const getTheadProps = makePropGetter(getHooks().getTheadProps, { instance: getInstance() })\n const getTfootProps = makePropGetter(getHooks().getTfootProps, { instance: getInstance() })\n\n Object.assign(instance, {\n getTheadProps,\n getTfootProps\n })\n}\n\nfunction asPx(value) {\n return typeof value === 'number' ? `${value}px` : undefined\n}\n","import { ensurePluginOrder } from 'react-table'\n\nimport { getLeafColumns } from './utils'\n\nexport default function useStickyColumns(hooks) {\n hooks.getHeaderProps.push(getHeaderProps)\n hooks.getCellProps.push(getCellProps)\n hooks.getFooterProps.push(getFooterProps)\n hooks.useInstance.push(useInstance)\n}\n\nuseStickyColumns.pluginName = 'useStickyColumns'\n\nconst getHeaderProps = (props, { column }) => {\n if (!column.stickyProps) {\n return props\n }\n return [props, column.stickyProps]\n}\n\nconst getCellProps = (props, { cell }) => {\n if (!cell.column.stickyProps) {\n return props\n }\n return [props, cell.column.stickyProps]\n}\n\nconst getFooterProps = (props, { column }) => {\n if (!column.stickyProps) {\n return props\n }\n return [props, column.stickyProps]\n}\n\nconst getStickyProps = (column, columns) => {\n const props = {\n className: 'rt-sticky',\n style: {\n position: 'sticky'\n }\n }\n if (column.sticky === 'left') {\n const stickyCols = columns.filter(col => col.sticky === 'left')\n props.style.left = 0\n for (let col of stickyCols) {\n if (col.id === column.id) break\n props.style.left += col.totalWidth\n }\n } else if (column.sticky === 'right') {\n const stickyCols = columns.filter(col => col.sticky === 'right')\n props.style.right = 0\n for (let col of stickyCols.reverse()) {\n if (col.id === column.id) break\n props.style.right += col.totalWidth\n }\n }\n return props\n}\n\nfunction useInstance(instance) {\n const { plugins, headerGroups } = instance\n\n ensurePluginOrder(plugins, ['useResizeColumns'], 'useStickyColumns')\n\n headerGroups.forEach(headerGroup => {\n const columns = headerGroup.headers\n\n // Ensure all columns in the group have the same sticky property.\n // If any sticky properties in the group differ, the first sticky column's\n // property is used for the whole group.\n columns.forEach(column => {\n const groupColumns = [column]\n if (column.columns) {\n groupColumns.push(...getLeafColumns(column))\n }\n const firstStickyCol = groupColumns.find(col => col.sticky)\n if (firstStickyCol) {\n groupColumns.forEach(col => {\n col.sticky = firstStickyCol.sticky\n })\n }\n })\n\n columns.forEach(column => {\n if (column.sticky) {\n column.stickyProps = getStickyProps(column, columns)\n }\n })\n })\n}\n","// useGroupBy hook modified to:\n// - Pass row objects and aggregated row objects to aggregate functions\n// - Include groupBy columns in aggregations\n// - Set nesting depth for leaf rows\n// - Omit row index properties on aggregated rows\n\nimport React from 'react'\nimport {\n actions,\n makePropGetter,\n ensurePluginOrder,\n useMountedLayoutEffect,\n useGetLatest\n} from 'react-table'\n\nimport { getFirstDefined } from './utils'\n\n// Not using any built-in aggregations\nconst aggregations = {}\n\nconst emptyArray = []\nconst emptyObject = {}\n\n// Actions\nactions.resetGroupBy = 'resetGroupBy'\nactions.setGroupBy = 'setGroupBy'\nactions.toggleGroupBy = 'toggleGroupBy'\n\nexport default function useGroupBy(hooks) {\n hooks.getGroupByToggleProps = [defaultGetGroupByToggleProps]\n hooks.stateReducers.push(reducer)\n hooks.visibleColumnsDeps.push((deps, { instance }) => [...deps, instance.state.groupBy])\n hooks.visibleColumns.push(visibleColumns)\n hooks.useInstance.push(useInstance)\n hooks.prepareRow.push(prepareRow)\n}\n\nuseGroupBy.pluginName = 'useGroupBy'\n\nconst defaultGetGroupByToggleProps = (props, { header }) => [\n props,\n {\n onClick: header.canGroupBy\n ? e => {\n e.persist()\n header.toggleGroupBy()\n }\n : undefined,\n style: {\n cursor: header.canGroupBy ? 'pointer' : undefined\n },\n title: 'Toggle GroupBy'\n }\n]\n\n// Reducer\nfunction reducer(state, action, previousState, instance) {\n if (action.type === actions.init) {\n return {\n groupBy: [],\n ...state\n }\n }\n\n if (action.type === actions.resetGroupBy) {\n return {\n ...state,\n groupBy: instance.initialState.groupBy || []\n }\n }\n\n if (action.type === actions.setGroupBy) {\n const { value } = action\n return {\n ...state,\n groupBy: value\n }\n }\n\n if (action.type === actions.toggleGroupBy) {\n const { columnId, value: setGroupBy } = action\n\n const resolvedGroupBy =\n typeof setGroupBy !== 'undefined' ? setGroupBy : !state.groupBy.includes(columnId)\n\n if (resolvedGroupBy) {\n return {\n ...state,\n groupBy: [...state.groupBy, columnId]\n }\n }\n\n return {\n ...state,\n groupBy: state.groupBy.filter(d => d !== columnId)\n }\n }\n}\n\nfunction visibleColumns(\n columns,\n {\n instance: {\n state: { groupBy }\n }\n }\n) {\n // Sort grouped columns to the start of the column list\n // before the headers are built\n\n const groupByColumns = groupBy.map(g => columns.find(col => col.id === g)).filter(Boolean)\n\n const nonGroupByColumns = columns.filter(col => !groupBy.includes(col.id))\n\n columns = [...groupByColumns, ...nonGroupByColumns]\n\n columns.forEach(column => {\n column.isGrouped = groupBy.includes(column.id)\n column.groupedIndex = groupBy.indexOf(column.id)\n })\n\n return columns\n}\n\nconst defaultUserAggregations = {}\n\nfunction useInstance(instance) {\n const {\n data,\n rows,\n flatRows,\n rowsById,\n allColumns,\n flatHeaders,\n groupByFn = defaultGroupByFn,\n manualGroupBy,\n aggregations: userAggregations = defaultUserAggregations,\n plugins,\n state: { groupBy },\n dispatch,\n autoResetGroupBy = true,\n disableGroupBy,\n defaultCanGroupBy,\n getHooks\n } = instance\n\n ensurePluginOrder(plugins, ['useColumnOrder', 'useFilters'], 'useGroupBy')\n\n const getInstance = useGetLatest(instance)\n\n allColumns.forEach(column => {\n const {\n accessor,\n defaultGroupBy: defaultColumnGroupBy,\n disableGroupBy: columnDisableGroupBy\n } = column\n\n column.canGroupBy = accessor\n ? getFirstDefined(\n column.canGroupBy,\n columnDisableGroupBy === true ? false : undefined,\n disableGroupBy === true ? false : undefined,\n true\n )\n : getFirstDefined(column.canGroupBy, defaultColumnGroupBy, defaultCanGroupBy, false)\n\n if (column.canGroupBy) {\n column.toggleGroupBy = () => instance.toggleGroupBy(column.id)\n }\n\n column.Aggregated = column.Aggregated || column.Cell\n })\n\n const toggleGroupBy = React.useCallback(\n (columnId, value) => {\n dispatch({ type: actions.toggleGroupBy, columnId, value })\n },\n [dispatch]\n )\n\n const setGroupBy = React.useCallback(\n value => {\n dispatch({ type: actions.setGroupBy, value })\n },\n [dispatch]\n )\n\n flatHeaders.forEach(header => {\n header.getGroupByToggleProps = makePropGetter(getHooks().getGroupByToggleProps, {\n instance: getInstance(),\n header\n })\n })\n\n const [\n groupedRows,\n groupedFlatRows,\n groupedRowsById,\n onlyGroupedFlatRows,\n onlyGroupedRowsById,\n nonGroupedFlatRows,\n nonGroupedRowsById\n ] = React.useMemo(() => {\n if (groupBy.length === 0) {\n return [rows, flatRows, rowsById, emptyArray, emptyObject, flatRows, rowsById]\n }\n\n if (manualGroupBy) {\n // Ensure that the list of filtered columns exist\n const existingGroupBy = groupBy.filter(g => allColumns.find(col => col.id === g))\n\n // Derive grouping props in each row that aren't present in manually grouped data.\n // Note that this excludes groupByVal and leafRows.\n const setGroupingProps = (rows, depth = 0) => {\n // Set nesting depth\n rows.forEach(row => {\n row.depth = depth\n })\n\n // Last level - these are leaf rows\n if (depth === existingGroupBy.length) {\n return\n }\n\n const columnId = existingGroupBy[depth]\n\n // Find the columns that can be aggregated, including any columns in groupBy.\n // groupBy columns that aren't in the row's group are allowed to be aggregated.\n const groupedColumns = existingGroupBy.slice(0, depth + 1)\n const aggregatedColumns = allColumns\n .filter(col => !groupedColumns.includes(col.id))\n .map(col => col.id)\n\n rows.forEach(row => {\n if (!row.isGrouped) {\n return\n }\n\n // Required but unset: row.groupByID, row.isGrouped\n row.groupByID = columnId\n // All columns that can be aggregated (including groupBy columns)\n row.aggregatedColumns = aggregatedColumns\n setGroupingProps(row.subRows, depth + 1)\n })\n }\n\n const flatRows = rows.filter(row => row.parentId == null)\n setGroupingProps(flatRows)\n\n return [rows, flatRows, rowsById, emptyArray, emptyObject, flatRows, rowsById]\n }\n\n // Ensure that the list of filtered columns exist\n const existingGroupBy = groupBy.filter(g => allColumns.find(col => col.id === g))\n\n // Find the columns that can or are aggregating\n // Uses each column to aggregate rows into a single value\n const aggregateRowsToValues = (leafRows, groupedRows, depth, aggregatedColumns) => {\n const values = {}\n\n allColumns.forEach(column => {\n // Only aggregate columns that aren't being grouped. Originally, all groupBy\n // columns were excluded, but now, groupBy columns not in the row's group\n // may be aggregated.\n if (!aggregatedColumns.includes(column.id)) {\n // Set placeholder values\n values[column.id] = groupedRows[0] ? groupedRows[0].values[column.id] : null\n return\n }\n\n // Get the columnValues to aggregate (no longer used)\n // const groupedValues = groupedRows.map(row => row.values[column.id])\n\n // Aggregate the values\n let aggregateFn =\n typeof column.aggregate === 'function'\n ? column.aggregate\n : userAggregations[column.aggregate] || aggregations[column.aggregate]\n\n if (aggregateFn) {\n // Get the columnValues to aggregate\n const leafValues = leafRows.map(row => {\n let columnValue = row.values[column.id]\n\n if (!depth && column.aggregateValue) {\n const aggregateValueFn =\n typeof column.aggregateValue === 'function'\n ? column.aggregateValue\n : userAggregations[column.aggregateValue] || aggregations[column.aggregateValue]\n\n if (!aggregateValueFn) {\n console.info({ column })\n throw new Error(\n `React Table: Invalid column.aggregateValue option for column listed above`\n )\n }\n\n columnValue = aggregateValueFn(columnValue, row, column)\n }\n return columnValue\n })\n\n // Originally, the leafValues and groupedValues were passed to the aggregate function.\n // Now, the aggregate function takes:\n // - leafValues: flattened array of values in the column\n // - leafRows: flattened array of rows in the column (for v6 compatibility)\n // - groupedRows: array of aggregated rows in the column\n values[column.id] = aggregateFn(\n leafValues,\n leafRows.map(row => row.values),\n groupedRows.map(row => row.values)\n )\n } else if (column.aggregate) {\n console.info({ column })\n throw new Error(`React Table: Invalid column.aggregate option for column listed above`)\n } else {\n values[column.id] = null\n }\n })\n\n return values\n }\n\n let groupedFlatRows = []\n const groupedRowsById = {}\n const onlyGroupedFlatRows = []\n const onlyGroupedRowsById = {}\n const nonGroupedFlatRows = []\n const nonGroupedRowsById = {}\n\n // Recursively group the data\n const groupUpRecursively = (rows, depth = 0, parentId) => {\n // This is the last level, just return the rows\n if (depth === existingGroupBy.length) {\n // Set nesting depth for leaf rows\n rows.forEach(row => {\n row.depth = depth\n })\n return rows\n }\n\n const columnId = existingGroupBy[depth]\n\n // Group the rows together for this level\n let rowGroupsMap = groupByFn(rows, columnId)\n\n // Peform aggregations for each group\n const aggregatedGroupedRows = Object.entries(rowGroupsMap).map(\n ([groupByVal, groupedRows], index) => {\n let id = `${columnId}:${groupByVal}`\n id = parentId ? `${parentId}>${id}` : id\n\n // First, Recurse to group sub rows before aggregation\n const subRows = groupUpRecursively(groupedRows, depth + 1, id)\n\n // Flatten the leaf rows of the rows in this group\n const leafRows = depth ? flattenBy(groupedRows, 'leafRows') : groupedRows\n\n // Find the columns that can be aggregated, including any columns in\n // groupBy. Originally, no groupBy columns were aggregated. Now we\n // aggregate groupBy columns that aren't in the row's group.\n const groupedColumns = existingGroupBy.slice(0, depth + 1)\n const aggregatedColumns = allColumns\n .filter(col => !groupedColumns.includes(col.id))\n .map(col => col.id)\n\n // Originally, groupedRows were passed here, which were the same as\n // the leafRows. Now, the subRows are passed, which contain the aggregated\n // values of the immediate child rows.\n const values = aggregateRowsToValues(leafRows, subRows, depth, aggregatedColumns)\n\n const row = {\n id,\n isGrouped: true,\n groupByID: columnId,\n groupByVal,\n values,\n subRows,\n leafRows,\n depth,\n // Originally, aggregated rows had a row index corresponding to the index within\n // rowGroupsMap. This row index doesn't map to a valid data row and overlaps\n // with the leaf rows, so explicitly omit it.\n // index: undefined,\n index: undefined,\n groupIndex: index,\n // All columns that can be aggregated (including groupBy columns)\n aggregatedColumns\n }\n\n subRows.forEach(subRow => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n if (subRow.isGrouped) {\n onlyGroupedFlatRows.push(subRow)\n onlyGroupedRowsById[subRow.id] = subRow\n } else {\n nonGroupedFlatRows.push(subRow)\n nonGroupedRowsById[subRow.id] = subRow\n }\n })\n\n return row\n }\n )\n\n return aggregatedGroupedRows\n }\n\n const groupedRows = groupUpRecursively(rows)\n\n groupedRows.forEach(subRow => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n if (subRow.isGrouped) {\n onlyGroupedFlatRows.push(subRow)\n onlyGroupedRowsById[subRow.id] = subRow\n } else {\n nonGroupedFlatRows.push(subRow)\n nonGroupedRowsById[subRow.id] = subRow\n }\n })\n\n // Assign the new data\n return [\n groupedRows,\n groupedFlatRows,\n groupedRowsById,\n onlyGroupedFlatRows,\n onlyGroupedRowsById,\n nonGroupedFlatRows,\n nonGroupedRowsById\n ]\n }, [manualGroupBy, groupBy, rows, flatRows, rowsById, allColumns, userAggregations, groupByFn])\n\n const getAutoResetGroupBy = useGetLatest(autoResetGroupBy)\n\n useMountedLayoutEffect(() => {\n if (getAutoResetGroupBy()) {\n dispatch({ type: actions.resetGroupBy })\n }\n }, [dispatch, manualGroupBy ? null : data])\n\n Object.assign(instance, {\n preGroupedRows: rows,\n preGroupedFlatRow: flatRows,\n preGroupedRowsById: rowsById,\n groupedRows,\n groupedFlatRows,\n groupedRowsById,\n onlyGroupedFlatRows,\n onlyGroupedRowsById,\n nonGroupedFlatRows,\n nonGroupedRowsById,\n rows: groupedRows,\n flatRows: groupedFlatRows,\n rowsById: groupedRowsById,\n toggleGroupBy,\n setGroupBy\n })\n}\n\nfunction prepareRow(row) {\n row.allCells.forEach(cell => {\n // Grouped cells are in the groupBy and the pivot cell for the row\n cell.isGrouped = cell.column.isGrouped && cell.column.id === row.groupByID\n\n // Aggregated cells are not grouped, not repeated, but still have subRows\n cell.isAggregated =\n !cell.isGrouped && row.aggregatedColumns?.includes(cell.column.id) && row.subRows?.length\n\n // Placeholder cells are any columns in the groupBy that are not grouped or aggregated\n cell.isPlaceholder = !cell.isGrouped && cell.column.isGrouped && !cell.isAggregated\n })\n}\n\nexport function defaultGroupByFn(rows, columnId) {\n return rows.reduce((prev, row) => {\n // TODO: Might want to implement a key serializer here so\n // irregular column values can still be grouped if needed?\n const resKey = `${row.values[columnId]}`\n prev[resKey] = Array.isArray(prev[resKey]) ? prev[resKey] : []\n prev[resKey].push(row)\n return prev\n }, {})\n}\n\nfunction flattenBy(arr, key) {\n const flat = []\n\n const recurse = arr => {\n arr.forEach(d => {\n if (!d[key]) {\n flat.push(d)\n } else {\n recurse(d[key])\n }\n })\n }\n\n recurse(arr)\n\n return flat\n}\n","// useResizeColumns modified to:\n// - Resize based on actual DOM width of column, like in v6. Requires a\n// getDOMWidth() method to be defined on each column header and header group.\n// - Clean up touchend listeners properly (https://github.com/tannerlinsley/react-table/issues/2622)\n// - Optimize number of calls to dispatch (https://github.com/tannerlinsley/react-table/pull/3231)\n\nimport React from 'react'\nimport {\n actions,\n defaultColumn,\n makePropGetter,\n ensurePluginOrder,\n useMountedLayoutEffect,\n useGetLatest\n} from 'react-table'\n\nimport { getFirstDefined } from './utils'\n\nlet passiveSupported = null\nfunction passiveEventSupported() {\n // memoize support to avoid adding multiple test events\n if (typeof passiveSupported === 'boolean') return passiveSupported\n\n let supported = false\n try {\n const options = {\n get passive() {\n supported = true\n return false\n }\n }\n\n window.addEventListener('test', null, options)\n window.removeEventListener('test', null, options)\n } catch (err) {\n supported = false\n }\n passiveSupported = supported\n return passiveSupported\n}\n\n// Default Column\ndefaultColumn.canResize = true\n\n// Actions\nactions.columnStartResizing = 'columnStartResizing'\nactions.columnResizing = 'columnResizing'\nactions.columnDoneResizing = 'columnDoneResizing'\nactions.resetResize = 'resetResize'\n\nexport default function useResizeColumns(hooks) {\n hooks.getResizerProps = [defaultGetResizerProps]\n hooks.getHeaderProps.push({\n style: {\n position: 'relative'\n }\n })\n hooks.stateReducers.push(reducer)\n hooks.useInstance.push(useInstance)\n hooks.useInstanceBeforeDimensions.push(useInstanceBeforeDimensions)\n}\n\nconst defaultGetResizerProps = (props, { instance, header }) => {\n const { dispatch } = instance\n\n const onResizeStart = (e, header) => {\n let isTouchEvent = false\n if (e.type === 'touchstart') {\n // lets not respond to multiple touches (e.g. 2 or 3 fingers)\n if (e.touches && e.touches.length > 1) {\n return\n }\n isTouchEvent = true\n }\n const headersToResize = getAllColumns(header)\n const headerIdWidths = headersToResize.map(d => [d.id, d.getDOMWidth()])\n const columnWidth = headerIdWidths.find(([id]) => id === header.id)[1]\n\n const clientX = isTouchEvent ? Math.round(e.touches[0].clientX) : e.clientX\n\n let raf\n let mostRecentClientX\n\n const dispatchMove = () => {\n window.cancelAnimationFrame(raf)\n raf = null\n dispatch({ type: actions.columnResizing, clientX: mostRecentClientX })\n }\n const dispatchEnd = () => {\n window.cancelAnimationFrame(raf)\n raf = null\n dispatch({ type: actions.columnDoneResizing })\n }\n\n const scheduleDispatchMoveOnNextAnimationFrame = clientXPos => {\n mostRecentClientX = clientXPos\n if (!raf) {\n raf = window.requestAnimationFrame(dispatchMove)\n }\n }\n\n const handlersAndEvents = {\n mouse: {\n moveEvent: 'mousemove',\n moveHandler: e => scheduleDispatchMoveOnNextAnimationFrame(e.clientX),\n upEvent: 'mouseup',\n upHandler: () => {\n document.removeEventListener('mousemove', handlersAndEvents.mouse.moveHandler)\n document.removeEventListener('mouseup', handlersAndEvents.mouse.upHandler)\n dispatchEnd()\n }\n },\n touch: {\n moveEvent: 'touchmove',\n moveHandler: e => {\n if (e.cancelable) {\n e.preventDefault()\n e.stopPropagation()\n }\n scheduleDispatchMoveOnNextAnimationFrame(e.touches[0].clientX)\n return false\n },\n upEvent: 'touchend',\n upHandler: () => {\n document.removeEventListener(\n handlersAndEvents.touch.moveEvent,\n handlersAndEvents.touch.moveHandler\n )\n document.removeEventListener(\n handlersAndEvents.touch.upEvent,\n handlersAndEvents.touch.upHandler\n )\n dispatchEnd()\n }\n }\n }\n\n const events = isTouchEvent ? handlersAndEvents.touch : handlersAndEvents.mouse\n const passiveIfSupported = passiveEventSupported() ? { passive: false } : false\n document.addEventListener(events.moveEvent, events.moveHandler, passiveIfSupported)\n document.addEventListener(events.upEvent, events.upHandler, passiveIfSupported)\n\n dispatch({\n type: actions.columnStartResizing,\n columnId: header.id,\n columnWidth,\n headerIdWidths,\n clientX\n })\n }\n\n return [\n props,\n {\n onMouseDown: e => e.persist() || onResizeStart(e, header),\n onTouchStart: e => e.persist() || onResizeStart(e, header),\n style: {\n cursor: 'col-resize'\n },\n draggable: false,\n role: 'separator'\n }\n ]\n}\n\nuseResizeColumns.pluginName = 'useResizeColumns'\n\nfunction reducer(state, action) {\n if (action.type === actions.init) {\n return {\n columnResizing: {\n columnWidths: {}\n },\n ...state\n }\n }\n\n if (action.type === actions.resetResize) {\n return {\n ...state,\n columnResizing: {\n columnWidths: {}\n }\n }\n }\n\n if (action.type === actions.columnStartResizing) {\n const { clientX, columnId, columnWidth, headerIdWidths } = action\n\n return {\n ...state,\n columnResizing: {\n ...state.columnResizing,\n startX: clientX,\n headerIdWidths,\n columnWidth,\n isResizingColumn: columnId\n }\n }\n }\n\n if (action.type === actions.columnResizing) {\n const { clientX } = action\n const { startX, columnWidth, headerIdWidths = [] } = state.columnResizing\n\n const deltaX = clientX - startX\n const percentageDeltaX = deltaX / columnWidth\n\n const newColumnWidths = {}\n\n headerIdWidths.forEach(([headerId, headerWidth]) => {\n newColumnWidths[headerId] = Math.max(headerWidth + headerWidth * percentageDeltaX, 0)\n })\n\n return {\n ...state,\n columnResizing: {\n ...state.columnResizing,\n columnWidths: {\n ...state.columnResizing.columnWidths,\n ...newColumnWidths\n }\n }\n }\n }\n\n if (action.type === actions.columnDoneResizing) {\n return {\n ...state,\n columnResizing: {\n ...state.columnResizing,\n startX: null,\n isResizingColumn: null\n }\n }\n }\n}\n\nconst useInstanceBeforeDimensions = instance => {\n const {\n flatHeaders,\n disableResizing,\n getHooks,\n state: { columnResizing }\n } = instance\n\n const getInstance = useGetLatest(instance)\n\n flatHeaders.forEach(header => {\n const canResize = getFirstDefined(\n header.disableResizing === true ? false : undefined,\n disableResizing === true ? false : undefined,\n true\n )\n\n header.canResize = canResize\n header.width = getFirstDefined(\n columnResizing.columnWidths[header.id],\n header.originalWidth,\n header.width\n )\n header.isResizing = columnResizing.isResizingColumn === header.id\n\n if (canResize) {\n header.getResizerProps = makePropGetter(getHooks().getResizerProps, {\n instance: getInstance(),\n header\n })\n }\n })\n}\n\nfunction useInstance(instance) {\n const { plugins, dispatch, autoResetResize = true, columns } = instance\n\n ensurePluginOrder(plugins, ['useAbsoluteLayout'], 'useResizeColumns')\n\n const getAutoResetResize = useGetLatest(autoResetResize)\n useMountedLayoutEffect(() => {\n if (getAutoResetResize()) {\n dispatch({ type: actions.resetResize })\n }\n }, [columns])\n\n const resetResizing = React.useCallback(() => dispatch({ type: actions.resetResize }), [dispatch])\n\n Object.assign(instance, {\n resetResizing\n })\n}\n\nfunction getAllColumns(column) {\n const allColumns = []\n const recurseColumn = column => {\n if (column.columns && column.columns.length) {\n column.columns.forEach(recurseColumn)\n }\n allColumns.push(column)\n }\n recurseColumn(column)\n return allColumns\n}\n","// useRowSelect hook modified to:\n// - Set row.isSelected for sub rows when paginateExpandedRows = false\n// (https://github.com/TanStack/react-table/issues/2908)\n// - Include an instance.setRowsSelected() function to set selected rows.\n// This is also useful to clear all selection, since toggleAllRowsSelected()\n// only affects visible rows, excluding any selected rows that may be filtered out.\n// - Handle sub rows correctly when custom getSubRows is used\n// (https://github.com/TanStack/react-table/pull/2886)\n\nimport React from 'react'\nimport {\n actions,\n makePropGetter,\n ensurePluginOrder,\n useGetLatest,\n useMountedLayoutEffect\n} from 'react-table'\n\nconst pluginName = 'useRowSelect'\n\n// Actions\nactions.resetSelectedRows = 'resetSelectedRows'\nactions.toggleAllRowsSelected = 'toggleAllRowsSelected'\nactions.toggleRowSelected = 'toggleRowSelected'\nactions.toggleAllPageRowsSelected = 'toggleAllPageRowsSelected'\nactions.setRowsSelected = 'setRowsSelected'\n\nexport default function useRowSelect(hooks) {\n hooks.getToggleRowSelectedProps = [defaultGetToggleRowSelectedProps]\n hooks.getToggleAllRowsSelectedProps = [defaultGetToggleAllRowsSelectedProps]\n hooks.getToggleAllPageRowsSelectedProps = [defaultGetToggleAllPageRowsSelectedProps]\n hooks.stateReducers.push(reducer)\n hooks.useInstance.push(useInstance)\n hooks.prepareRow.push(prepareRow)\n}\n\nuseRowSelect.pluginName = pluginName\n\nconst defaultGetToggleRowSelectedProps = (props, { instance, row }) => {\n const { manualRowSelectedKey = 'isSelected' } = instance\n let checked = false\n\n if (row.original && row.original[manualRowSelectedKey]) {\n checked = true\n } else {\n checked = row.isSelected\n }\n\n return [\n props,\n {\n onChange: e => {\n row.toggleRowSelected(e.target.checked)\n },\n style: {\n cursor: 'pointer'\n },\n checked,\n title: 'Toggle Row Selected',\n indeterminate: row.isSomeSelected\n }\n ]\n}\n\nconst defaultGetToggleAllRowsSelectedProps = (props, { instance }) => [\n props,\n {\n onChange: e => {\n instance.toggleAllRowsSelected(e.target.checked)\n },\n style: {\n cursor: 'pointer'\n },\n checked: instance.isAllRowsSelected,\n title: 'Toggle All Rows Selected',\n indeterminate: Boolean(\n !instance.isAllRowsSelected && Object.keys(instance.state.selectedRowIds).length\n )\n }\n]\n\nconst defaultGetToggleAllPageRowsSelectedProps = (props, { instance }) => [\n props,\n {\n onChange(e) {\n instance.toggleAllPageRowsSelected(e.target.checked)\n },\n style: {\n cursor: 'pointer'\n },\n checked: instance.isAllPageRowsSelected,\n title: 'Toggle All Current Page Rows Selected',\n indeterminate: Boolean(\n !instance.isAllPageRowsSelected &&\n instance.page.some(({ id }) => instance.state.selectedRowIds[id])\n )\n }\n]\n\n// eslint-disable-next-line max-params\nfunction reducer(state, action, previousState, instance) {\n if (action.type === actions.init) {\n return {\n selectedRowIds: {},\n ...state\n }\n }\n\n if (action.type === actions.resetSelectedRows) {\n return {\n ...state,\n selectedRowIds: instance.initialState.selectedRowIds || {}\n }\n }\n\n if (action.type === actions.toggleAllRowsSelected) {\n const { value: setSelected } = action\n const { isAllRowsSelected, rowsById, nonGroupedRowsById = rowsById } = instance\n\n const selectAll = typeof setSelected !== 'undefined' ? setSelected : !isAllRowsSelected\n\n // Only remove/add the rows that are visible on the screen\n // Leave all the other rows that are selected alone.\n const selectedRowIds = Object.assign({}, state.selectedRowIds)\n\n if (selectAll) {\n Object.keys(nonGroupedRowsById).forEach(rowId => {\n selectedRowIds[rowId] = true\n })\n } else {\n Object.keys(nonGroupedRowsById).forEach(rowId => {\n delete selectedRowIds[rowId]\n })\n }\n\n return {\n ...state,\n selectedRowIds\n }\n }\n\n if (action.type === actions.toggleRowSelected) {\n const { id, value: setSelected } = action\n const { rowsById, selectSubRows = true } = instance\n const isSelected = state.selectedRowIds[id]\n const shouldExist = typeof setSelected !== 'undefined' ? setSelected : !isSelected\n\n if (isSelected === shouldExist) {\n return state\n }\n\n const newSelectedRowIds = { ...state.selectedRowIds }\n\n const handleRowById = id => {\n const row = rowsById[id]\n if (!row.isGrouped) {\n if (shouldExist) {\n newSelectedRowIds[id] = true\n } else {\n delete newSelectedRowIds[id]\n }\n }\n\n if (selectSubRows && row.subRows) {\n return row.subRows.forEach(row => handleRowById(row.id))\n }\n }\n\n handleRowById(id)\n\n return {\n ...state,\n selectedRowIds: newSelectedRowIds\n }\n }\n\n if (action.type === actions.toggleAllPageRowsSelected) {\n const { value: setSelected } = action\n const { page, rowsById, selectSubRows = true, isAllPageRowsSelected } = instance\n\n const selectAll = typeof setSelected !== 'undefined' ? setSelected : !isAllPageRowsSelected\n\n const newSelectedRowIds = { ...state.selectedRowIds }\n\n const handleRowById = id => {\n const row = rowsById[id]\n\n if (!row.isGrouped) {\n if (selectAll) {\n newSelectedRowIds[id] = true\n } else {\n delete newSelectedRowIds[id]\n }\n }\n\n if (selectSubRows && row.subRows) {\n return row.subRows.forEach(row => handleRowById(row.id))\n }\n }\n\n page.forEach(row => handleRowById(row.id))\n\n return {\n ...state,\n selectedRowIds: newSelectedRowIds\n }\n }\n\n if (action.type === actions.setRowsSelected) {\n const { ids: setSelected } = action\n const { rowsById, selectSubRows = true } = instance\n\n const newSelectedRowIds = {}\n\n const handleRowById = id => {\n const row = rowsById[id]\n\n // Select a filtered or (less likely) invalid row (rowsById only contains visible rows).\n if (!row) {\n newSelectedRowIds[id] = true\n return\n }\n\n if (!row.isGrouped) {\n newSelectedRowIds[id] = true\n }\n\n if (selectSubRows && row.subRows) {\n return row.subRows.forEach(row => handleRowById(row.id))\n }\n }\n\n setSelected.forEach(rowId => handleRowById(rowId))\n\n return {\n ...state,\n selectedRowIds: newSelectedRowIds\n }\n }\n return state\n}\n\nfunction useInstance(instance) {\n const {\n data,\n rows,\n getHooks,\n plugins,\n rowsById,\n nonGroupedRowsById = rowsById,\n autoResetSelectedRows = true,\n state: { selectedRowIds },\n selectSubRows = true,\n dispatch,\n page\n } = instance\n\n ensurePluginOrder(\n plugins,\n ['useFilters', 'useGroupBy', 'useSortBy', 'useExpanded', 'usePagination'],\n 'useRowSelect'\n )\n\n const selectedFlatRows = React.useMemo(() => {\n const selectedFlatRows = []\n\n // Ensure row.isSelected is set for sub rows when paginateExpandedRows = false\n // https://github.com/TanStack/react-table/issues/2908\n const handleRow = row => {\n const isSelected = selectSubRows\n ? getRowIsSelected(row, selectedRowIds)\n : !!selectedRowIds[row.id]\n row.isSelected = !!isSelected\n row.isSomeSelected = isSelected === null\n\n if (isSelected) {\n selectedFlatRows.push(row)\n }\n\n if (row.subRows && row.subRows.length) {\n row.subRows.forEach(row => handleRow(row))\n }\n }\n\n rows.forEach(row => handleRow(row))\n\n return selectedFlatRows\n }, [rows, selectSubRows, selectedRowIds])\n\n let isAllRowsSelected = Boolean(\n Object.keys(nonGroupedRowsById).length && Object.keys(selectedRowIds).length\n )\n\n let isAllPageRowsSelected = isAllRowsSelected\n\n if (isAllRowsSelected) {\n if (Object.keys(nonGroupedRowsById).some(id => !selectedRowIds[id])) {\n isAllRowsSelected = false\n }\n }\n\n if (!isAllRowsSelected) {\n if (page && page.length && page.some(({ id }) => !selectedRowIds[id])) {\n isAllPageRowsSelected = false\n }\n }\n\n const getAutoResetSelectedRows = useGetLatest(autoResetSelectedRows)\n\n useMountedLayoutEffect(() => {\n if (getAutoResetSelectedRows()) {\n dispatch({ type: actions.resetSelectedRows })\n }\n }, [dispatch, data])\n\n const toggleAllRowsSelected = React.useCallback(\n value => dispatch({ type: actions.toggleAllRowsSelected, value }),\n [dispatch]\n )\n\n const toggleAllPageRowsSelected = React.useCallback(\n value => dispatch({ type: actions.toggleAllPageRowsSelected, value }),\n [dispatch]\n )\n\n const toggleRowSelected = React.useCallback(\n (id, value) => dispatch({ type: actions.toggleRowSelected, id, value }),\n [dispatch]\n )\n\n const setRowsSelected = React.useCallback(\n ids => dispatch({ type: actions.setRowsSelected, ids }),\n [dispatch]\n )\n\n const getInstance = useGetLatest(instance)\n\n const getToggleAllRowsSelectedProps = makePropGetter(getHooks().getToggleAllRowsSelectedProps, {\n instance: getInstance()\n })\n\n const getToggleAllPageRowsSelectedProps = makePropGetter(\n getHooks().getToggleAllPageRowsSelectedProps,\n { instance: getInstance() }\n )\n\n Object.assign(instance, {\n selectedFlatRows,\n isAllRowsSelected,\n isAllPageRowsSelected,\n toggleRowSelected,\n toggleAllRowsSelected,\n setRowsSelected,\n getToggleAllRowsSelectedProps,\n getToggleAllPageRowsSelectedProps,\n toggleAllPageRowsSelected\n })\n}\n\nfunction prepareRow(row, { instance }) {\n row.toggleRowSelected = set => instance.toggleRowSelected(row.id, set)\n\n row.getToggleRowSelectedProps = makePropGetter(instance.getHooks().getToggleRowSelectedProps, {\n instance: instance,\n row\n })\n}\n\nfunction getRowIsSelected(row, selectedRowIds) {\n if (selectedRowIds[row.id]) {\n return true\n }\n\n const subRows = row.subRows\n\n if (subRows && subRows.length) {\n let allChildrenSelected = true\n let someSelected = false\n\n // TODO: For server-side pagination, if sub rows are paginated, there's no way to know \n // whether all sub rows are selected if not present on the page. Row selection needs \n // to be fully server-side, so this is a temporary workaround to prevent grouped\n // rows from always appearing as selected.\n const availableSubRows = subRows.filter(row => row != null)\n if (availableSubRows.length !== subRows.length) {\n return false\n }\n\n subRows.forEach(subRow => {\n // Bail out early if we know both of these\n if (someSelected && !allChildrenSelected) {\n return\n }\n\n if (getRowIsSelected(subRow, selectedRowIds)) {\n someSelected = true\n } else {\n allChildrenSelected = false\n }\n })\n return allChildrenSelected ? true : someSelected ? null : false\n }\n\n return false\n}\n","// usePagination modified to:\n// - Allow pagination to be disabled. This makes it easier to use the hook\n// conditionally while keeping pagination functionality intact (e.g., the\n// pagination bar and API can still be used when pagination is disabled).\n// - Provide instance.pageRowCount for the number of paginated rows on the\n// page, excluding expanded rows when paginateExpandedRows = false.\n// - Support a rowCount option in useTable() for manual pagination as an\n// alternative to pageCount. Server-side pagination typically requires\n// the server-side row count to be known, so providing page count is\n// unnecessary when it can be derived from row count and page size.\n\nimport React from 'react'\nimport {\n actions,\n ensurePluginOrder,\n functionalUpdate,\n useMountedLayoutEffect,\n useGetLatest\n} from 'react-table'\n\nconst pluginName = 'usePagination'\n\n// Actions\nactions.resetPage = 'resetPage'\nactions.gotoPage = 'gotoPage'\nactions.setPageSize = 'setPageSize'\n\nexport default function usePagination(hooks) {\n hooks.stateReducers.push(reducer)\n hooks.useInstance.push(useInstance)\n}\n\nusePagination.pluginName = pluginName\n\nfunction reducer(state, action, previousState, instance) {\n if (action.type === actions.init) {\n return {\n pageSize: 10,\n pageIndex: 0,\n ...state\n }\n }\n\n if (action.type === actions.resetPage) {\n return {\n ...state,\n pageIndex: instance.initialState.pageIndex || 0\n }\n }\n\n if (action.type === actions.gotoPage) {\n const { pageCount, page } = instance\n const newPageIndex = functionalUpdate(action.pageIndex, state.pageIndex)\n let canNavigate = false\n\n if (newPageIndex > state.pageIndex) {\n // next page\n canNavigate = pageCount === -1 ? page.length >= state.pageSize : newPageIndex < pageCount\n } else if (newPageIndex < state.pageIndex) {\n // prev page\n canNavigate = newPageIndex > -1\n }\n\n if (!canNavigate) {\n return state\n }\n\n return {\n ...state,\n pageIndex: newPageIndex\n }\n }\n\n if (action.type === actions.setPageSize) {\n const { pageSize } = action\n const topRowIndex = state.pageSize * state.pageIndex\n const pageIndex = Math.floor(topRowIndex / pageSize)\n\n return {\n ...state,\n pageIndex,\n pageSize\n }\n }\n}\n\nfunction useInstance(instance) {\n const {\n rows,\n autoResetPage = true,\n manualExpandedKey = 'expanded',\n plugins,\n pageCount: userPageCount,\n paginateExpandedRows = true,\n expandSubRows = true,\n disablePagination,\n state: { pageIndex, expanded, globalFilter, filters, groupBy, sortBy },\n dispatch,\n data,\n manualPagination,\n // User-specified row count when using manual pagination. Takes precedence over pageCount.\n rowCount: userRowCount\n } = instance\n\n ensurePluginOrder(\n plugins,\n ['useGlobalFilter', 'useFilters', 'useGroupBy', 'useSortBy', 'useExpanded'],\n 'usePagination'\n )\n\n const getAutoResetPage = useGetLatest(autoResetPage)\n\n useMountedLayoutEffect(() => {\n if (getAutoResetPage()) {\n dispatch({ type: actions.resetPage })\n }\n }, [dispatch, manualPagination ? null : data, globalFilter, filters, groupBy, sortBy])\n\n // Disabling pagination effectively means setting the page size to the table size.\n // This is best done by the hook, rather than the user, because the row count\n // isn't known until other row-manipulating hooks have run (e.g., useGroupBy).\n const pageSize = disablePagination ? rows.length : instance.state.pageSize\n\n let pageCount\n if (manualPagination) {\n // Prefer user-specified row count for manual pagination. Server-side pagination\n // typically requires the server-side row count to be known, so providing page count\n // is unnecessary when it can be derived from row count and page size.\n pageCount =\n userRowCount != null && userRowCount >= 0 ? Math.ceil(userRowCount / pageSize) : userPageCount\n } else {\n pageCount = Math.ceil(rows.length / pageSize)\n }\n\n const pageOptions = React.useMemo(\n () => (pageCount > 0 ? [...new Array(pageCount)].fill(null).map((d, i) => i) : []),\n [pageCount]\n )\n\n const [page, pageRowCount] = React.useMemo(() => {\n let page\n\n if (manualPagination) {\n page = rows\n } else {\n const pageStart = pageSize * pageIndex\n const pageEnd = pageStart + pageSize\n\n page = rows.slice(pageStart, pageEnd)\n }\n\n const pageRowCount = page.length\n\n if (paginateExpandedRows) {\n return [page, pageRowCount]\n }\n\n return [expandRows(page, { manualExpandedKey, expanded, expandSubRows }), pageRowCount]\n }, [\n expandSubRows,\n expanded,\n manualExpandedKey,\n manualPagination,\n pageIndex,\n pageSize,\n paginateExpandedRows,\n rows\n ])\n\n const canPreviousPage = pageIndex > 0\n const canNextPage = pageCount === -1 ? page.length >= pageSize : pageIndex < pageCount - 1\n\n const gotoPage = React.useCallback(\n pageIndex => {\n dispatch({ type: actions.gotoPage, pageIndex })\n },\n [dispatch]\n )\n\n const previousPage = React.useCallback(() => {\n return gotoPage(old => old - 1)\n }, [gotoPage])\n\n const nextPage = React.useCallback(() => {\n return gotoPage(old => old + 1)\n }, [gotoPage])\n\n const setPageSize = React.useCallback(\n pageSize => {\n dispatch({ type: actions.setPageSize, pageSize })\n },\n [dispatch]\n )\n\n Object.assign(instance, {\n pageOptions,\n pageCount,\n page,\n pageRowCount,\n canPreviousPage,\n canNextPage,\n gotoPage,\n previousPage,\n nextPage,\n setPageSize\n })\n}\n\nfunction expandRows(rows, { manualExpandedKey, expanded, expandSubRows = true }) {\n const expandedRows = []\n\n const handleRow = (row, addToExpandedRows = true) => {\n row.isExpanded = (row.original && row.original[manualExpandedKey]) || expanded[row.id]\n\n row.canExpand = row.subRows && !!row.subRows.length\n\n if (addToExpandedRows) {\n expandedRows.push(row)\n }\n\n if (row.subRows && row.subRows.length && row.isExpanded) {\n row.subRows.forEach(row => handleRow(row, expandSubRows))\n }\n }\n\n rows.forEach(row => handleRow(row))\n\n return expandedRows\n}\n","export function sum(values) {\n const numbers = omitMissingNumbers(values)\n if (numbers.length === 0) {\n return 0\n }\n const result = numbers.reduce((a, b) => a + b, 0)\n // Adjust for floating-point precision errors\n return round(result, 12)\n}\n\nexport function mean(values) {\n const numbers = omitMissingNumbers(values)\n if (numbers.length === 0) {\n return NaN\n }\n const result = sum(numbers) / numbers.length\n // Adjust for floating-point precision errors\n return round(result, 12)\n}\n\nexport function maxNumber(values) {\n const numbers = omitMissingNumbers(values)\n if (numbers.length === 0) {\n return NaN\n }\n return Math.max.apply(null, numbers)\n}\n\nexport function minNumber(values) {\n const numbers = omitMissingNumbers(values)\n if (numbers.length === 0) {\n return NaN\n }\n return Math.min.apply(null, numbers)\n}\n\nexport function median(values) {\n const numbers = omitMissingNumbers(values)\n if (numbers.length === 0) {\n return NaN\n }\n numbers.sort((a, b) => a - b)\n if (numbers.length % 2 === 1) {\n return numbers[(numbers.length - 1) / 2]\n } else {\n return mean(numbers.slice(numbers.length / 2 - 1, numbers.length / 2 + 1))\n }\n}\n\nexport function max(values) {\n let maxValue\n values.forEach(value => {\n if (maxValue == null || value > maxValue) {\n maxValue = value\n }\n })\n return maxValue\n}\n\nexport function min(values) {\n let minValue\n values.forEach(value => {\n if (minValue == null || value < minValue) {\n minValue = value\n }\n })\n return minValue\n}\n\nexport function count(values) {\n return values.length\n}\n\nexport function unique(values) {\n return [...new Set(values)].join(', ')\n}\n\nexport function frequency(values) {\n const counts = {}\n values.forEach(value => {\n counts[value] = counts[value] || 0\n counts[value] += 1\n })\n const strs = Object.keys(counts).map(val => {\n return val + (counts[val] > 1 ? ` (${counts[val]})` : '')\n })\n return strs.join(', ')\n}\n\nconst numericAggregators = {\n mean,\n sum,\n max: maxNumber,\n min: minNumber,\n median\n}\n\nconst defaultAggregators = {\n max,\n min,\n count,\n unique,\n frequency\n}\n\nexport function getAggregateFunction(name, type) {\n if (type === 'numeric' && numericAggregators[name]) {\n return numericAggregators[name]\n }\n return defaultAggregators[name]\n}\n\nexport function round(n, digits = 3) {\n if (!Number.isFinite(n)) {\n return n\n }\n digits = digits > 0 ? digits : 0\n const c = Math.pow(10, digits)\n // Round away from zero rather than up (Math.round rounds -1.5 to -1)\n return (Math.sign(n) * Math.round(Math.abs(n) * c)) / c\n}\n\nfunction omitMissingNumbers(values) {\n return values.filter(n => n != null && !Number.isNaN(n))\n}\n","import React, { Fragment } from 'react'\nimport { hydrate } from 'reactR'\n\nimport WidgetContainer from './WidgetContainer'\nimport { getAggregateFunction } from './aggregators'\nimport {\n classNames,\n escapeRegExp,\n getFirstDefined,\n getLeafColumns,\n removeEmptyProps\n} from './utils'\n\n// Use zero-width spaces to preserve the height of empty cells\nexport const emptyValue = '\\u200b'\n\n// Override default subRows property\nconst subRowsKey = '.subRows'\n\nexport const rowSelectedKey = '.selected'\nexport const rowExpandedKey = '.expanded'\n\nexport const rowStateKey = '__state'\n\nexport function getSubRows(row) {\n return row[subRowsKey] || []\n}\n\n// Normalize raw column data from R for use in reactable\nexport function normalizeColumnData(data, columns) {\n for (let col of columns) {\n if (col.type === 'numeric' && data[col.id]) {\n convertJSONNumbers(data[col.id])\n }\n }\n return columnsToRows(data)\n}\n\n// Convert JSON-serialized numbers to JavaScript numbers in place. jsonlite::toJSON() converts\n// numeric NA, NaN, Inf, -Inf to strings, as there isn't a way to represent them in JSON otherwise.\nexport function convertJSONNumbers(arr) {\n for (let i = 0; i < arr.length; i++) {\n let n = arr[i]\n // Numeric columns can have nulls in pre-grouped data\n if (typeof n === 'number' || n == null) {\n continue\n }\n if (n === 'NA') {\n n = null\n } else if (n === 'NaN') {\n n = NaN\n } else if (n === 'Inf') {\n n = Infinity\n } else if (n === '-Inf') {\n n = -Infinity\n } else {\n n = Number(n)\n }\n arr[i] = n\n }\n}\n\n// Convert column-based data to rows\n// e.g. { a: [1, 2], b: ['x', 'y'] } to [{ a: 1, b: 'x' }, { a: 2, b: 'y' }]\nexport function columnsToRows(columns) {\n const names = Object.keys(columns)\n if (names.length === 0) {\n return []\n }\n\n if (columns[rowStateKey]) {\n columns[rowStateKey] = normalizeColumnData(columns[rowStateKey], numericRowStateColumns)\n }\n\n const rows = new Array(columns[names[0]].length)\n for (let i = 0; i < rows.length; i++) {\n rows[i] = {}\n for (let name of names) {\n const value = columns[name][i]\n if (name === subRowsKey) {\n if (value instanceof Object) {\n rows[i][name] = columnsToRows(value)\n }\n } else {\n rows[i][name] = value\n }\n }\n }\n return rows\n}\n\nconst numericRowStateColumns = [{ id: 'index', type: 'numeric' }]\nexport function materializedRowsToData(rows, paginateSubRows) {\n const parentRowIds = {}\n return rows.map(row => {\n let parentId\n let subRowCount\n if (paginateSubRows) {\n parentId = parentRowIds[row.id]\n subRowCount = row.subRows.length\n row.subRows.forEach(subRow => {\n parentRowIds[subRow.id] = row.id\n })\n }\n const rowState = {\n id: row.id,\n index: row.index,\n grouped: row.isGrouped ? true : null,\n parentId,\n subRowCount,\n // Currently unused\n expanded: row.isExpanded ? true : null,\n selected: row.isSelected ? true : null\n }\n removeEmptyProps(rowState)\n const dataRow = { ...row.values, [rowStateKey]: rowState }\n if (!paginateSubRows) {\n if (row.subRows && row.subRows.length > 0) {\n dataRow[subRowsKey] = materializedRowsToData(row.subRows)\n }\n }\n return dataRow\n })\n}\n\nexport function RawHTML({ html, className, ...props }) {\n return (\n \n {renderTemplate(language.pageNumbers, { page, pages: totalPages })}\n
\n )\n }\n\n const prevButton = (\n