UNPKG

@atlaskit/dynamic-table

Version:

A dynamic table displays rows of data with built-in pagination, sorting, and re-ordering functionality.

146 lines (142 loc) 4.45 kB
import _extends from "@babel/runtime/helpers/extends"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import React from 'react'; import { getPageRows } from '../internal/get-page-rows'; import { validateSortKey } from '../internal/validate-sort-key'; const getSortingCellValue = (cells, head, sortKey) => { for (let i = 0; i < cells.length; i++) { var _head$cells$i; if (head.cells[i] && ((_head$cells$i = head.cells[i]) === null || _head$cells$i === void 0 ? void 0 : _head$cells$i.key) === sortKey) { var _cells$i; return (_cells$i = cells[i]) === null || _cells$i === void 0 ? void 0 : _cells$i.key; } } return undefined; }; // sort all rows based on sort key and order const getSortedRows = (head, rows, sortKey, sortOrder) => { if (!sortKey || !head) { return rows; } if (!rows) { return []; } const modifier = sortOrder === 'ASC' ? 1 : -1; // Re-initialising an I18n Collator on every sort is performance intensive, thus constructed outside const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'accent' }); // Get copy of rows to avoid sorting prop in place const sortableRows = Array.from(rows); // Reorder rows in table based on sorting cell value // Algorithm will sort numerics or strings, but not both return sortableRows.sort((a, b) => { const valA = getSortingCellValue(a.cells, head, sortKey); const valB = getSortingCellValue(b.cells, head, sortKey); if (valA === undefined || valB === undefined) { return modifier; } if (typeof valA !== typeof valB) { // numbers are always grouped higher in the sort if (typeof valA === 'number') { return -1; } if (typeof valB === 'number') { return 1; } // strings are grouped next if (typeof valA === 'string') { return -1; } if (typeof valB === 'string') { return 1; } } if (typeof valA === 'string' && typeof valB === 'string') { return modifier * collator.compare(valA, valB); } if (!valA && valA !== 0 || valA < valB) { return -modifier; } if (!valB && valB !== 0 || valA > valB) { return modifier; } if (valA === valB) { return 0; } return 1; }); }; // get one page of data in table, sorting all rows previously export default function withSortedPageRows(WrappedComponent) { // eslint-disable-next-line @repo/internal/react/no-class-components class WithSortedPageRows extends React.Component { constructor(...args) { super(...args); _defineProperty(this, "state", { pageRows: [] }); } static getDerivedStateFromProps(props, state) { const { rows, head, sortKey, sortOrder, page, rowsPerPage, isTotalPagesControlledExternally } = props; validateSortKey(sortKey, head); let sortedRows; let pageRows; if (isTotalPagesControlledExternally) { sortedRows = rows; pageRows = rows; } else { sortedRows = getSortedRows(head, rows, sortKey, sortOrder) || []; pageRows = getPageRows(sortedRows, page, rowsPerPage); } return { ...state, pageRows }; } componentDidMount() { this.props.onPageRowsUpdate && this.props.onPageRowsUpdate(this.state.pageRows); } componentDidUpdate(_prevProps, prevState) { if (this.props.onPageRowsUpdate && this.state.pageRows !== prevState.pageRows) { this.props.onPageRowsUpdate(this.state.pageRows); } } render() { const { rows, head, sortKey, sortOrder, rowsPerPage, page, forwardedRef, ...restProps } = this.props; return /*#__PURE__*/React.createElement(WrappedComponent //@ts-expect-error TODO Fix legit TypeScript 3.9.6 improved inference error , _extends({ pageRows: this.state.pageRows, head: head }, restProps, { ref: forwardedRef })); } } return /*#__PURE__*/React.forwardRef((props, ref) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: to unblock React 18.2.0 -> 18.3.1 version bump in Jira return /*#__PURE__*/React.createElement(WithSortedPageRows, _extends({}, props, { forwardedRef: ref })); }); }