-
-
Notifications
You must be signed in to change notification settings - Fork 9.1k
/
DocsContainer.tsx
100 lines (92 loc) · 3.14 KB
/
DocsContainer.tsx
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
96
97
98
99
100
import React, { FunctionComponent, useEffect } from 'react';
import global from 'global';
import deprecate from 'util-deprecate';
import dedent from 'ts-dedent';
import { MDXProvider } from '@mdx-js/react';
import { ThemeProvider, ensure as ensureTheme } from '@storybook/theming';
import { DocsWrapper, DocsContent, components as htmlComponents } from '@storybook/components';
import { DocsContextProps, DocsContext } from './DocsContext';
import { anchorBlockIdFromId } from './Anchor';
import { storyBlockIdFromId } from './Story';
import { SourceContainer } from './SourceContainer';
import { CodeOrSourceMdx, AnchorMdx, HeadersMdx } from './mdx';
import { scrollToElement } from './utils';
const { document, window: globalWindow } = global;
export interface DocsContainerProps<StoryFnReturnType> {
context: DocsContextProps<StoryFnReturnType>;
}
const defaultComponents = {
...htmlComponents,
code: CodeOrSourceMdx,
a: AnchorMdx,
...HeadersMdx,
};
const warnOptionsTheme = deprecate(
() => {},
dedent`
Deprecated parameter: options.theme => docs.theme
https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/theming.md#storybook-theming
`
);
export const DocsContainer: FunctionComponent<DocsContainerProps<any>> = ({
context,
children,
}) => {
const { id: storyId, storyById } = context;
const {
parameters: { options = {}, docs = {} },
} = storyById(storyId);
let themeVars = docs.theme;
if (!themeVars && options.theme) {
warnOptionsTheme();
themeVars = options.theme;
}
const theme = ensureTheme(themeVars);
const allComponents = { ...defaultComponents, ...docs.components };
useEffect(() => {
let url;
try {
url = new URL(globalWindow.parent.location);
} catch (err) {
return;
}
if (url.hash) {
const element = document.getElementById(url.hash.substring(1));
if (element) {
// Introducing a delay to ensure scrolling works when it's a full refresh.
setTimeout(() => {
scrollToElement(element);
}, 200);
}
} else {
const element =
document.getElementById(anchorBlockIdFromId(storyId)) ||
document.getElementById(storyBlockIdFromId(storyId));
if (element) {
const allStories = element.parentElement.querySelectorAll('[id|="anchor-"]');
let scrollTarget = element;
if (allStories && allStories[0] === element) {
// Include content above first story
scrollTarget = document.getElementById('docs-root');
}
// Introducing a delay to ensure scrolling works when it's a full refresh.
setTimeout(() => {
scrollToElement(scrollTarget, 'start');
}, 200);
}
}
}, [storyId]);
return (
<DocsContext.Provider value={context}>
<SourceContainer>
<ThemeProvider theme={theme}>
<MDXProvider components={allComponents}>
<DocsWrapper className="sbdocs sbdocs-wrapper">
<DocsContent className="sbdocs sbdocs-content">{children}</DocsContent>
</DocsWrapper>
</MDXProvider>
</ThemeProvider>
</SourceContainer>
</DocsContext.Provider>
);
};