lion/packages/ui/components/helpers/sortEachDepth.js
2022-10-31 16:55:07 +01:00

84 lines
2.9 KiB
JavaScript

/**
* Sorts each depth level according to the provided array order.
*
* @example
* addParameters({
* options: {
* showRoots: true,
* storySort: sortEachDepth([
* ['Intro', 'Forms', 'Buttons', '...'] // 1. level - ordered like this rest default order
* ['Intro', '...', 'System'], // 2. level - Intro first, System last in between default order
* ['Overview', '...'] // 3. level - Intro first rest default order
* ]),
* });
*
* @param {Array.<[]>} orderPerDepth array of arrays giving the order of each level
*/
export function sortEachDepth(orderPerDepth) {
return (/** @type {Array.<?>} */ a, /** @type {Array.<?>} */ b) => {
// If the two stories have the same story kind, then use the default
// ordering, which is the order they are defined in the story file.
if (a[1].kind === b[1].kind) {
return 0;
}
const storyKindA = a[1].kind.split('/');
const storyKindB = b[1].kind.split('/');
let depth = 0;
let nameA;
let nameB;
let indexA;
let indexB;
/** @type {Array.<?>} */
let ordering = orderPerDepth[0] || [];
if (ordering.indexOf('...') !== -1 && ordering.indexOf('...abc') !== -1) {
throw new Error(
`Found ${ordering.join(',')} You need to use either "..." or "...abc" for each level.`,
);
}
// eslint-disable-next-line no-constant-condition
while (true) {
nameA = storyKindA[depth] ? storyKindA[depth] : '';
nameB = storyKindB[depth] ? storyKindB[depth] : '';
if (nameA === nameB) {
// We'll need to look at the next part of the name.
depth += 1;
ordering = orderPerDepth[depth] || [];
if (ordering.indexOf('...') !== -1 && ordering.indexOf('...abc') !== -1) {
throw new Error('You need to use either "..." or "...abc" for each level.');
}
// eslint-disable-next-line no-continue
continue;
} else {
// Look for the names in the given `ordering` array.
indexA = ordering.indexOf(nameA);
indexB = ordering.indexOf(nameB);
// If at least one of the names is found, sort by the `ordering` array.
if (indexA !== -1 || indexB !== -1) {
// If one of the names is not found in `ordering`, list it at the place of '...' or last.
let insertPosition = ordering.length;
if (ordering.indexOf('...') !== -1) {
insertPosition = ordering.indexOf('...');
}
if (ordering.indexOf('...abc') !== -1) {
insertPosition = ordering.indexOf('...abc');
}
if (indexA === -1) {
indexA = insertPosition;
}
if (indexB === -1) {
indexB = insertPosition;
}
return indexA - indexB;
}
}
if (ordering.indexOf('...abc') !== -1) {
return nameA.localeCompare(nameB);
}
// Otherwise, use source code order.
return 0;
}
};
}