UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

134 lines (120 loc) 3.91 kB
'use strict'; // The directions in which a column can be sorted // Note: if a table is sorted, one column _must_ have a direction other than // NONE // A mapping of names to SortDirection const SortDirection = { ASC: 'ASC', DESC: 'DESC', NONE: 'NONE' }; // The default sort direction for a column going from NONE to sorted const DEFAULT_SORT_DIRECTION = SortDirection.ASC; // Transition the given sort direction to the next direction // Note: we can only cycle between ASC <-> DESC, NONE is not supported function transition(direction) { if (direction === SortDirection.ASC) { return SortDirection.DESC; } return SortDirection.ASC; } // ---------------------------------------------------------------------------- // Sort strategies // ---------------------------------------------------------------------------- /** * A sort strategy for comparing any two values */ function basic(a, b) { return a === b ? 0 : a < b ? -1 : 1; } /** * A sort strategy for comparing two `Date` values. Also includes support for * values from `Date.now()` */ function datetime(a, b) { const timeA = a instanceof Date ? a.getTime() : a; const timeB = b instanceof Date ? b.getTime() : b; return timeA > timeB ? 1 : timeA < timeB ? -1 : 0; } /** * Compare two numbers using alphanumeric, or natural order, sorting. This * sorting function breaks up the inputs into groups of text and numbers and * compares the different sub-groups of each to determine the order of a set of * strings * * @see https://en.wikipedia.org/wiki/Natural_sort_order */ function alphanumeric(inputA, inputB) { const groupsA = getAlphaNumericGroups(inputA); const groupsB = getAlphaNumericGroups(inputB); while (groupsA.length !== 0 && groupsB.length !== 0) { const a = groupsA.shift(); const b = groupsB.shift(); // If the two groups are equal, move on to the next set of groups if (a === b) { continue; } else if (typeof a === 'string' && typeof b === 'string') { // If both groups are strings, compare them using the current locale return a.localeCompare(b); } else if (typeof a === 'number' && typeof b === 'number') { // If both groups are numbers, compare them numerically return a > b ? 1 : -1; } else if (typeof a === 'number' && typeof b === 'string') { // Sort numbers before strings return -1; } else if (typeof a === 'string' && typeof b === 'number') { // Sort numbers before strings return 1; } else if (a === undefined || b === undefined) { // If either group is undefined, break out of the loop. The input with the // fewest number of groups will be ordered first break; } } // If all else is equal, the string with the fewest number of "groups" is // ordered before the other string return groupsA.length > groupsB.length ? 1 : -1; } /** * Break up the given input string into groups of text and numbers */ function getAlphaNumericGroups(input) { const groups = []; let i = 0; while (i < input.length) { let group = input[i]; if (isNumeric(group)) { while (i + 1 < input.length && isNumeric(input[i + 1])) { group = group + input[i + 1]; i++; } groups.push(parseInt(group, 10)); } else { while (i + 1 < input.length && !isNumeric(input[i + 1])) { group = group + input[i + 1]; i++; } groups.push(group); } i++; } return groups; } /** * Determine if the given value is a number */ function isNumeric(value) { return !Number.isNaN(parseInt(value, 10)); } const strategies = { alphanumeric, basic, datetime }; exports.DEFAULT_SORT_DIRECTION = DEFAULT_SORT_DIRECTION; exports.SortDirection = SortDirection; exports.alphanumeric = alphanumeric; exports.basic = basic; exports.datetime = datetime; exports.strategies = strategies; exports.transition = transition;