-
-
Notifications
You must be signed in to change notification settings - Fork 9.1k
/
utils.ts
95 lines (84 loc) · 3.23 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import memoize from 'memoizerific';
import { document, window, DOCS_MODE } from 'global';
import { SyntheticEvent } from 'react';
import type { StoriesHash } from '@storybook/api';
import { isRoot } from '@storybook/api';
import { DEFAULT_REF_ID } from './data';
import { Item, RefType, Dataset, SearchItem } from './types';
export const createId = (itemId: string, refId?: string) =>
!refId || refId === DEFAULT_REF_ID ? itemId : `${refId}_${itemId}`;
export const getLink = (itemId: string, refId?: string) => {
const type = DOCS_MODE ? 'docs' : 'story';
return `${document.location.pathname}?path=/${type}/${createId(itemId, refId)}`;
};
export const prevent = (e: SyntheticEvent) => {
e.preventDefault();
return false;
};
export const get = memoize(1000)((id: string, dataset: Dataset) => dataset[id]);
export const getParent = memoize(1000)((id: string, dataset: Dataset) => {
const item = get(id, dataset);
return item && !isRoot(item) ? get(item.parent, dataset) : undefined;
});
export const getParents = memoize(1000)((id: string, dataset: Dataset): Item[] => {
const parent = getParent(id, dataset);
return parent ? [parent, ...getParents(parent.id, dataset)] : [];
});
export const getAncestorIds = memoize(1000)((data: StoriesHash, id: string): string[] =>
getParents(id, data).map((item) => item.id)
);
export const getDescendantIds = memoize(1000)(
(data: StoriesHash, id: string, skipLeafs: boolean): string[] => {
const { children = [] } = data[id] || {};
return children.reduce((acc, childId) => {
if (skipLeafs && data[childId].isLeaf) return acc;
acc.push(childId, ...getDescendantIds(data, childId, skipLeafs));
return acc;
}, []);
}
);
export function getPath(item: Item, ref: RefType): string[] {
const parent = !isRoot(item) && item.parent ? ref.stories[item.parent] : null;
if (parent) return [...getPath(parent, ref), parent.name];
return ref.id === DEFAULT_REF_ID ? [] : [ref.title || ref.id];
}
export const searchItem = (item: Item, ref: RefType): SearchItem => {
return { ...item, refId: ref.id, path: getPath(item, ref) };
};
export function cycle<T>(array: T[], index: number, delta: number): number {
let next = index + (delta % array.length);
if (next < 0) next = array.length + next;
if (next >= array.length) next -= array.length;
return next;
}
export const scrollIntoView = (element: Element, center = false) => {
if (!element) return;
const { top, bottom } = element.getBoundingClientRect();
const isInView =
top >= 0 && bottom <= (window.innerHeight || document.documentElement.clientHeight);
if (!isInView) element.scrollIntoView({ block: center ? 'center' : 'nearest' });
};
export const getStateType = (
isLoading: boolean,
isAuthRequired: boolean,
isError: boolean,
isEmpty: boolean
) => {
switch (true) {
case isAuthRequired:
return 'auth';
case isError:
return 'error';
case isLoading:
return 'loading';
case isEmpty:
return 'empty';
default:
return 'ready';
}
};
export const isAncestor = (element?: Element, maybeAncestor?: Element): boolean => {
if (!element || !maybeAncestor) return false;
if (element === maybeAncestor) return true;
return isAncestor(element.parentElement, maybeAncestor);
};