UNPKG

@mskcc/carbon-react

Version:

Carbon react components for the MSKCC DSM

115 lines (108 loc) 3.56 kB
/** * MSKCC 2021, 2024 */ import { getCellId } from './cells.js'; import { sortStates } from '../state/sortStates.js'; /** * Compare two primitives to determine which comes first. Initially, this method * will try and figure out if both entries are the same type. If so, it will * apply the default sort algorithm for those types. Otherwise, it defaults to a * string conversion. * * @param {number|string} a * @param {number|string} b * @param {string} locale * @returns {number} */ const compare = function (a, b) { let locale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'en'; // prevent multiple null values in one column (sorting breaks) a === null ? a = '' : null; b === null ? b = '' : null; if (typeof a === 'number' && typeof b === 'number') { return a - b; } if (typeof a === 'string' && typeof b === 'string') { return compareStrings(a, b, locale); } // if column has React elements, this should sort by the child string if there is one if (typeof a === 'object' && typeof b === 'object') { if (typeof a.props.children === 'string' && typeof b.props.children === 'string') { return compareStrings(a.props.children, b.props.children, locale); } } return compareStrings('' + a, '' + b, locale); }; /** * Use the built-in `localeCompare` function available on strings to compare two * strings. * * @param {string} a * @param {string} b * @param {string} locale * @returns {number} */ const compareStrings = function (a, b) { let locale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'en'; // Only set `numeric: true` if the string only contains numbers // https://stackoverflow.com/a/175787 if (!isNaN(a) && !isNaN(parseFloat(a)) && !isNaN(b) && !isNaN(parseFloat(b))) { return a.localeCompare(b, locale, { numeric: true }); } return a.localeCompare(b, locale); }; /** * Default implementation of how we sort rows internally. The idea behind this * implementation is to use the given list of row ids to look up the cells in * the row by the given key. We then use the value of these cells and pipe them * into our local `compareStrings` method, including the locale where * appropriate. * * @param {object} config * @param {Array[string]} config.rowIds array of all the row ids in the table * @param {object} config.cellsById object containing a mapping of cell id to * cell * @param {string} config.key the header key that we use to lookup the cell * @param {string} [config.locale] optional locale used in the comparison * function * @param {string} config.sortDirection the sort direction used to determine the * order the comparison is called in * @param {Function} config.sortRow * @returns {Array[string]} array of sorted rowIds */ const sortRows = _ref => { let { rowIds, cellsById, sortDirection, key, locale, sortRow } = _ref; return rowIds.slice().sort((a, b) => { const cellA = cellsById[getCellId(a, key)]; const cellB = cellsById[getCellId(b, key)]; return sortRow(cellA && cellA.value, cellB && cellB.value, { key, sortDirection, locale, sortStates, compare, rowIds: [a, b] }); }); }; const defaultSortRow = (cellA, cellB, _ref2) => { let { sortDirection, sortStates, locale } = _ref2; if (sortDirection === sortStates.ASC) { return compare(cellA, cellB, locale); } return compare(cellB, cellA, locale); }; export { compare, compareStrings, defaultSortRow, sortRows };