-
-
Notifications
You must be signed in to change notification settings - Fork 9.1k
/
Story.tsx
107 lines (89 loc) · 3.04 KB
/
Story.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
101
102
103
104
105
106
107
import React, { createElement, ElementType, FunctionComponent, ReactNode } from 'react';
import { MDXProvider } from '@mdx-js/react';
import { components as docsComponents } from '@storybook/components/html';
import { Story, StoryProps as PureStoryProps } from '@storybook/components';
import { CURRENT_SELECTION } from './shared';
import { DocsContext, DocsContextProps } from './DocsContext';
export const storyBlockIdFromId = (storyId: string) => `story--${storyId}`;
const resetComponents: Record<string, ElementType> = {};
Object.keys(docsComponents).forEach(key => {
resetComponents[key] = (props: any) => createElement(key, props);
});
interface CommonProps {
height?: string;
inline?: boolean;
}
type StoryDefProps = {
name: string;
children: ReactNode;
} & CommonProps;
type StoryRefProps = {
id?: string;
} & CommonProps;
export type StoryProps = StoryDefProps | StoryRefProps;
const inferInlineStories = (framework: string): boolean => {
switch (framework) {
case 'react':
return true;
default:
return false;
}
};
export const getStoryProps = (
props: StoryProps,
{ id: currentId, storyStore, parameters, mdxStoryNameToId }: DocsContextProps | null
): PureStoryProps => {
const { id } = props as StoryRefProps;
const { name } = props as StoryDefProps;
const inputId = id === CURRENT_SELECTION ? currentId : id;
const previewId = inputId || mdxStoryNameToId[name];
const { height, inline } = props;
const data = storyStore.fromId(previewId);
const { framework = null } = (data && data.parameters) || {};
const docsParam = (data && data.parameters && data.parameters.docs) || {};
if (docsParam.disable) {
return null;
}
// prefer props, then global options, then framework-inferred values
const {
inlineStories = inferInlineStories(framework),
iframeHeight = undefined,
prepareForInline = undefined,
} = docsParam;
const { storyFn = undefined, name: storyName = undefined } = data || {};
const storyIsInline = typeof inline === 'boolean' ? inline : inlineStories;
if (storyIsInline && !prepareForInline && framework !== 'react') {
throw new Error(
`Story '${storyName}' is set to render inline, but no 'prepareForInline' function is implemented in your docs configuration!`
);
}
return {
inline: storyIsInline,
id: previewId,
storyFn: prepareForInline && storyFn ? () => prepareForInline(storyFn) : storyFn,
height: height || (storyIsInline ? undefined : iframeHeight),
title: storyName,
};
};
const StoryContainer: FunctionComponent<StoryProps> = props => (
<DocsContext.Consumer>
{context => {
const storyProps = getStoryProps(props, context);
if (!storyProps) {
return null;
}
return (
<div id={storyBlockIdFromId(storyProps.id)}>
<MDXProvider components={resetComponents}>
<Story {...storyProps} />
</MDXProvider>
</div>
);
}}
</DocsContext.Consumer>
);
StoryContainer.defaultProps = {
children: null,
name: null,
};
export { StoryContainer as Story };