mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-02 05:03:44 +08:00
Merge pull request #12520 from diedu89/feat/sorting-include-name
Core: Add option to include story names when sorting
This commit is contained in:
commit
303e4bfaa8
@ -100,11 +100,12 @@ The `storySort` can also accept a configuration object.
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
| Field | Type | Description | Required | Default Value | Example |
|
||||
| ----------- | :----: | :------------------------------------------------------: | :------: | :---------------------: | :-----------------------: |
|
||||
| **method** | String | Tells Storybook in which order the stories are displayed | No | Storybook configuration | `'alphabetical'` |
|
||||
| **order** | Array | The stories to be shown, ordered by supplied name | No | Empty Array `[]` | `['Intro', 'Components']` |
|
||||
| **locales** | String | The locale required to be displayed | No | System locale | `en-US` |
|
||||
| Field | Type | Description | Required | Default Value | Example |
|
||||
| --------------- | :-----: | :------------------------------------------------------: | :------: | :---------------------: | :-----------------------: |
|
||||
| **method** | String | Tells Storybook in which order the stories are displayed | No | Storybook configuration | `'alphabetical'` |
|
||||
| **order** | Array | The stories to be show, ordered by supplied name | No | Empty Array `[]` | `['Intro', 'Components']` |
|
||||
| **includeName** | Boolean | Include story name in sort calculation | No | `false` | `true` |
|
||||
| **locales** | String | The locale required to be displayed | No | System locale | `en-US` |
|
||||
|
||||
To sort your stories alphabetically, set `method` to `'alphabetical'` and optionally set the `locales` string. To sort your stories using a custom list, use the `order` array; stories that don't match an item in the `order` list will appear after the items in the list.
|
||||
|
||||
|
@ -77,6 +77,7 @@ export interface StorySortObjectParameter {
|
||||
method?: StorySortMethod;
|
||||
order?: any[];
|
||||
locales?: string;
|
||||
includeNames?: boolean;
|
||||
}
|
||||
// The `any` here is the story store's `StoreItem` record. Ideally we should probably only
|
||||
// pass a defined subset of that full data, but we pass it all so far :shrug:
|
||||
|
@ -14,6 +14,11 @@ describe('preview.storySort', () => {
|
||||
c: ['', { kind: 'c' }],
|
||||
locale1: ['', { kind: 'Б' }],
|
||||
locale2: ['', { kind: 'Г' }],
|
||||
c__a: ['', { kind: 'c', name: 'a' }],
|
||||
c_b__a: ['', { kind: 'c/b', name: 'a' }],
|
||||
c_b__b: ['', { kind: 'c/b', name: 'b' }],
|
||||
c_b__c: ['', { kind: 'c/b', name: 'c' }],
|
||||
c__c: ['', { kind: 'c', name: 'c' }],
|
||||
};
|
||||
|
||||
it('uses configure order by default', () => {
|
||||
@ -76,6 +81,28 @@ describe('preview.storySort', () => {
|
||||
expect(sortFn(fixture.a_b, fixture.a_a)).toBeLessThan(0);
|
||||
});
|
||||
|
||||
it('sorts alphabetically including story names', () => {
|
||||
const sortFn = storySort({ method: 'alphabetical', includeNames: true });
|
||||
expect(sortFn(fixture.c_b__a, fixture.c__a)).toBeGreaterThan(0);
|
||||
expect(sortFn(fixture.c__a, fixture.c_b__a)).toBeLessThan(0);
|
||||
|
||||
expect(sortFn(fixture.c__c, fixture.c__a)).toBeGreaterThan(0);
|
||||
expect(sortFn(fixture.c__a, fixture.c__c)).toBeLessThan(0);
|
||||
});
|
||||
|
||||
it('sorts according to the order array including story names', () => {
|
||||
const sortFn = storySort({
|
||||
order: ['c', ['b', ['c', 'b', 'a'], 'c', 'a']],
|
||||
includeNames: true,
|
||||
});
|
||||
expect(sortFn(fixture.c_b__a, fixture.c_b__b)).toBeGreaterThan(0);
|
||||
expect(sortFn(fixture.c_b__b, fixture.c_b__c)).toBeGreaterThan(0);
|
||||
expect(sortFn(fixture.c_b__a, fixture.c_b__c)).toBeGreaterThan(0);
|
||||
expect(sortFn(fixture.c_b__a, fixture.c__a)).toBeLessThan(0);
|
||||
expect(sortFn(fixture.c_b__a, fixture.c__c)).toBeLessThan(0);
|
||||
expect(sortFn(fixture.c__a, fixture.c__c)).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('sorts according to the order array with a wildcard', () => {
|
||||
const sortFn = storySort({ order: ['a', '*', 'b'] });
|
||||
|
||||
|
@ -6,7 +6,8 @@ export const storySort = (options: StorySortObjectParameter = {}): StorySortComp
|
||||
): number => {
|
||||
// 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) {
|
||||
// only when includeNames is falsy
|
||||
if (a[1].kind === b[1].kind && !options.includeNames) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -15,8 +16,8 @@ export const storySort = (options: StorySortObjectParameter = {}): StorySortComp
|
||||
let order = options.order || [];
|
||||
|
||||
// Examine each part of the story kind in turn.
|
||||
const storyKindA = a[1].kind.split('/');
|
||||
const storyKindB = b[1].kind.split('/');
|
||||
const storyKindA = [...a[1].kind.split('/'), ...(options.includeNames ? a[1].name : [])];
|
||||
const storyKindB = [...b[1].kind.split('/'), ...(options.includeNames ? b[1].name : [])];
|
||||
let depth = 0;
|
||||
while (storyKindA[depth] || storyKindB[depth]) {
|
||||
// Stories with a shorter depth should go first.
|
||||
|
@ -1195,6 +1195,84 @@ describe('preview.story_store', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('sorts stories in specified order including story names or configure', () => {
|
||||
const store = new StoryStore({ channel });
|
||||
store.addGlobalMetadata({
|
||||
decorators: [],
|
||||
parameters: {
|
||||
options: {
|
||||
storySort: {
|
||||
method: 'configure',
|
||||
order: ['b', ['bc', 'ba', 'bb'], 'a', 'c'],
|
||||
includeNames: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
addStoryToStore(store, 'a/b', '1', () => 0);
|
||||
addStoryToStore(store, 'a', '2', () => 0);
|
||||
addStoryToStore(store, 'a', '1', () => 0);
|
||||
addStoryToStore(store, 'c', '1', () => 0);
|
||||
addStoryToStore(store, 'b/bd', '1', () => 0);
|
||||
addStoryToStore(store, 'b/bb', '1', () => 0);
|
||||
addStoryToStore(store, 'b/ba', '1', () => 0);
|
||||
addStoryToStore(store, 'b/bc', '1', () => 0);
|
||||
addStoryToStore(store, 'b', '1', () => 0);
|
||||
|
||||
const extracted = store.extract();
|
||||
|
||||
expect(Object.keys(extracted)).toEqual([
|
||||
'b-bc--1',
|
||||
'b-ba--1',
|
||||
'b-bb--1',
|
||||
'b-bd--1',
|
||||
'b--1',
|
||||
'a-b--1',
|
||||
'a--2',
|
||||
'a--1',
|
||||
'c--1',
|
||||
]);
|
||||
});
|
||||
|
||||
it('sorts stories in specified order including story names or alphabetically', () => {
|
||||
const store = new StoryStore({ channel });
|
||||
store.addGlobalMetadata({
|
||||
decorators: [],
|
||||
parameters: {
|
||||
options: {
|
||||
storySort: {
|
||||
method: 'alphabetical',
|
||||
order: ['b', ['bc', 'ba', 'bb'], 'a', 'c'],
|
||||
includeNames: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
addStoryToStore(store, 'a/b', '1', () => 0);
|
||||
addStoryToStore(store, 'a', '2', () => 0);
|
||||
addStoryToStore(store, 'a', '1', () => 0);
|
||||
addStoryToStore(store, 'c', '1', () => 0);
|
||||
addStoryToStore(store, 'b/bd', '1', () => 0);
|
||||
addStoryToStore(store, 'b/bb', '1', () => 0);
|
||||
addStoryToStore(store, 'b/ba', '1', () => 0);
|
||||
addStoryToStore(store, 'b/bc', '1', () => 0);
|
||||
addStoryToStore(store, 'b', '1', () => 0);
|
||||
|
||||
const extracted = store.extract();
|
||||
|
||||
expect(Object.keys(extracted)).toEqual([
|
||||
'b-bc--1',
|
||||
'b-ba--1',
|
||||
'b-bb--1',
|
||||
'b--1',
|
||||
'b-bd--1',
|
||||
'a--1',
|
||||
'a--2',
|
||||
'a-b--1',
|
||||
'c--1',
|
||||
]);
|
||||
});
|
||||
|
||||
it('passes kind and global parameters to sort', () => {
|
||||
const store = new StoryStore({ channel });
|
||||
const storySort = jest.fn();
|
||||
|
@ -4,7 +4,9 @@ import { ZoomIFrame as IFrame } from './ZoomIFrame';
|
||||
|
||||
export const browserSupportsCssZoom = (): boolean => {
|
||||
try {
|
||||
return globalWindow.document.implementation.createHTMLDocument('').body.style.zoom !== undefined;
|
||||
return (
|
||||
globalWindow.document.implementation.createHTMLDocument('').body.style.zoom !== undefined
|
||||
);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2,7 +2,9 @@ import { window as globalWindow } from 'global';
|
||||
|
||||
export function browserSupportsCssZoom(): boolean {
|
||||
try {
|
||||
return globalWindow.document.implementation.createHTMLDocument('').body.style.zoom !== undefined;
|
||||
return (
|
||||
globalWindow.document.implementation.createHTMLDocument('').body.style.zoom !== undefined
|
||||
);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
@ -73,4 +73,4 @@ const Handle = styled.div<{ isDragging: boolean; axis: Axis }>(
|
||||
);
|
||||
|
||||
export { Draggable, Handle };
|
||||
export type { DraggableEvent, DraggableData };
|
||||
export type { DraggableEvent, DraggableData };
|
||||
|
Loading…
x
Reference in New Issue
Block a user