-
-
Notifications
You must be signed in to change notification settings - Fork 9.5k
/
Copy pathSource.tsx
127 lines (115 loc) · 3.26 KB
/
Source.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import type { ComponentProps, FunctionComponent } from 'react';
import React from 'react';
import { styled, ThemeProvider, convert, themes, ignoreSsrWarning } from '@storybook/theming';
import { SyntaxHighlighter } from '@storybook/components';
import { EmptyBlock } from './EmptyBlock';
const StyledSyntaxHighlighter: typeof SyntaxHighlighter = styled(SyntaxHighlighter)(
({ theme }) => ({
// DocBlocks-specific styling and overrides
fontSize: `${theme.typography.size.s2 - 1}px`,
lineHeight: '19px',
margin: '25px 0 40px',
borderRadius: theme.appBorderRadius,
boxShadow:
theme.base === 'light'
? 'rgba(0, 0, 0, 0.10) 0 1px 3px 0'
: 'rgba(0, 0, 0, 0.20) 0 2px 5px 0',
'pre.prismjs': {
padding: 20,
background: 'inherit',
},
})
);
export enum SourceError {
NO_STORY = 'There\u2019s no story here.',
SOURCE_UNAVAILABLE = 'Oh no! The source is not available.',
}
export interface SourceCodeProps {
/**
* The language the syntax highlighter uses for your story’s code
*/
language?: string;
/**
* Use this to override the content of the source block.
*/
code?: string;
/**
* The (prettier) formatter the syntax highlighter uses for your story’s code.
*/
format?: ComponentProps<typeof SyntaxHighlighter>['format'];
/**
* Display the source snippet in a dark mode.
*/
dark?: boolean;
}
export interface SourceProps extends SourceCodeProps {
isLoading?: boolean;
error?: SourceError;
}
const SourceSkeletonWrapper = styled.div(({ theme }) => ({
background: theme.background.content,
borderRadius: theme.appBorderRadius,
border: `1px solid ${theme.appBorderColor}`,
boxShadow:
theme.base === 'light' ? 'rgba(0, 0, 0, 0.10) 0 1px 3px 0' : 'rgba(0, 0, 0, 0.20) 0 2px 5px 0',
margin: '25px 0 40px',
padding: '20px 20px 20px 22px',
}));
const SourceSkeletonPlaceholder = styled.div(({ theme }) => ({
animation: `${theme.animation.glow} 1.5s ease-in-out infinite`,
background: theme.appBorderColor,
height: 17,
marginTop: 1,
width: '60%',
[`&:first-child${ignoreSsrWarning}`]: {
margin: 0,
},
}));
const SourceSkeleton = () => (
<SourceSkeletonWrapper>
<SourceSkeletonPlaceholder />
<SourceSkeletonPlaceholder style={{ width: '80%' }} />
<SourceSkeletonPlaceholder style={{ width: '30%' }} />
<SourceSkeletonPlaceholder style={{ width: '80%' }} />
</SourceSkeletonWrapper>
);
/**
* Syntax-highlighted source code for a component (or anything!)
*/
const Source: FunctionComponent<SourceProps> = ({
isLoading,
error,
language,
code,
dark,
format,
...rest
}) => {
if (isLoading) {
return <SourceSkeleton />;
}
if (error) {
return <EmptyBlock>{error}</EmptyBlock>;
}
const syntaxHighlighter = (
<StyledSyntaxHighlighter
bordered
copyable
format={format}
language={language}
className="docblock-source sb-unstyled"
{...rest}
>
{code}
</StyledSyntaxHighlighter>
);
if (typeof dark === 'undefined') {
return syntaxHighlighter;
}
const overrideTheme = dark ? themes.dark : themes.light;
return <ThemeProvider theme={convert(overrideTheme)}>{syntaxHighlighter}</ThemeProvider>;
};
Source.defaultProps = {
format: false,
};
export { Source, StyledSyntaxHighlighter };