-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
createGlobalStyle.ts
88 lines (76 loc) 路 3.22 KB
/
createGlobalStyle.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
import React from 'react';
import { STATIC_EXECUTION_CONTEXT } from '../constants';
import GlobalStyle from '../models/GlobalStyle';
import { useStyleSheetContext } from '../models/StyleSheetManager';
import { DefaultTheme, ThemeContext } from '../models/ThemeProvider';
import StyleSheet from '../sheet';
import { ExecutionContext, ExecutionProps, Interpolation, Stringifier, Styles } from '../types';
import { checkDynamicCreation } from '../utils/checkDynamicCreation';
import determineTheme from '../utils/determineTheme';
import generateComponentId from '../utils/generateComponentId';
import css from './css';
export default function createGlobalStyle<Props extends object>(
strings: Styles<Props>,
...interpolations: Array<Interpolation<Props>>
) {
const rules = css<Props>(strings, ...interpolations);
const styledComponentId = `sc-global-${generateComponentId(JSON.stringify(rules))}`;
const globalStyle = new GlobalStyle<Props>(rules, styledComponentId);
if (process.env.NODE_ENV !== 'production') {
checkDynamicCreation(styledComponentId);
}
const GlobalStyleComponent: React.ComponentType<ExecutionProps & Props> = props => {
const ssc = useStyleSheetContext();
const theme = React.useContext(ThemeContext);
const instanceRef = React.useRef(ssc.styleSheet.allocateGSInstance(styledComponentId));
const instance = instanceRef.current;
if (process.env.NODE_ENV !== 'production' && React.Children.count(props.children)) {
console.warn(
`The global style component ${styledComponentId} was given child JSX. createGlobalStyle does not render children.`
);
}
if (
process.env.NODE_ENV !== 'production' &&
rules.some(rule => typeof rule === 'string' && rule.indexOf('@import') !== -1)
) {
console.warn(
`Please do not use @import CSS syntax in createGlobalStyle at this time, as the CSSOM APIs we use in production do not handle it well. Instead, we recommend using a library such as react-helmet to inject a typical <link> meta tag to the stylesheet, or simply embedding it manually in your index.html <head> section for a simpler app.`
);
}
if (ssc.styleSheet.server) {
renderStyles(instance, props, ssc.styleSheet, theme, ssc.stylis);
}
if (!__SERVER__) {
React.useLayoutEffect(() => {
if (!ssc.styleSheet.server) {
renderStyles(instance, props, ssc.styleSheet, theme, ssc.stylis);
return () => globalStyle.removeStyles(instance, ssc.styleSheet);
}
}, [instance, props, ssc.styleSheet, theme, ssc.stylis]);
}
return null;
};
function renderStyles(
instance: number,
props: ExecutionProps,
styleSheet: StyleSheet,
theme: DefaultTheme | undefined,
stylis: Stringifier
) {
if (globalStyle.isStatic) {
globalStyle.renderStyles(
instance,
STATIC_EXECUTION_CONTEXT as unknown as ExecutionContext & Props,
styleSheet,
stylis
);
} else {
const context = {
...props,
theme: determineTheme(props, theme, GlobalStyleComponent.defaultProps),
} as ExecutionContext & Props;
globalStyle.renderStyles(instance, context, styleSheet, stylis);
}
}
return React.memo(GlobalStyleComponent);
}