-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathgatsby-ssr.js
More file actions
113 lines (89 loc) · 2.85 KB
/
Copy pathgatsby-ssr.js
File metadata and controls
113 lines (89 loc) · 2.85 KB
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
/**
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/ssr-apis/
*/
import React from 'react';
import PropTypes from 'prop-types';
import App from './src/components/App';
import colors, {
DARK,
INITIAL_THEME_CSS_PROP,
LIGHT,
THEME_KEY,
} from './src/data/colors';
const PLACEHOLDERS = {
COLORS: "'__REPLACE_COLORS__'",
DARK: '__REPLACE_DARK__',
INITIAL_THEME_CSS_PROP: '__REPLACE_INITIAL_THEME_CSS_PROP__',
LIGHT: '__REPLACE_LIGHT__',
THEME_KEY: '__REPLACE_THEME_KEY__',
};
const setColorsByTheme = () => {
const colors = '__REPLACE_COLORS__';
const dark = '__REPLACE_DARK__';
const initialThemeCssProp = '__REPLACE_INITIAL_THEME_CSS_PROP__';
const light = '__REPLACE_LIGHT__';
const themeKey = '__REPLACE_THEME_KEY__';
function getInitialTheme() {
const persistedColorPreference = window.localStorage.getItem(themeKey);
const hasPersistedPreference = typeof persistedColorPreference === 'string';
if (hasPersistedPreference) {
return persistedColorPreference;
}
const mql = window.matchMedia('(prefers-color-scheme: dark)');
const hasMediaQueryPreference = typeof mql.matches === 'boolean';
if (hasMediaQueryPreference) {
return mql.matches ? dark : light;
}
return light;
}
const theme = getInitialTheme();
const root = window.document.documentElement;
Object.entries(colors).forEach(([name, colorByTheme]) => {
const cssVarName = `--color-${name}`;
root.style.setProperty(cssVarName, colorByTheme[theme]);
});
root.style.setProperty(initialThemeCssProp, theme);
};
const SetInitialTheme = () => {
const functionStr = String(setColorsByTheme)
.replace(PLACEHOLDERS.COLORS, JSON.stringify(colors))
.replace(PLACEHOLDERS.DARK, DARK)
.replace(PLACEHOLDERS.INITIAL_THEME_CSS_PROP, INITIAL_THEME_CSS_PROP)
.replace(PLACEHOLDERS.LIGHT, LIGHT)
.replace(PLACEHOLDERS.THEME_KEY, THEME_KEY);
const codeToRunOnClient = `(${functionStr})()`;
return <script dangerouslySetInnerHTML={{ __html: codeToRunOnClient }} />;
};
const FallbackStyles = () => {
const cssVarStr = Object.entries(colors).reduce(
(acc, [name, colorByTheme]) => {
return `${acc}\n--color-${name}: ${colorByTheme[LIGHT]};`;
},
''
);
const wrappedInSelector = `html { ${cssVarStr} }`;
return <style>{wrappedInSelector}</style>;
};
const BodyAttributes = {
style: {
backgroundColor: 'var(--color-background)',
color: 'var(--color-text)',
},
};
export const onRenderBody = ({
setBodyAttributes,
setHeadComponents,
setPreBodyComponents,
}) => {
setHeadComponents(<FallbackStyles />);
setPreBodyComponents(<SetInitialTheme />);
setBodyAttributes(BodyAttributes);
};
export const wrapRootElement = ({ element }) => {
return <App>{element}</App>;
};
wrapRootElement.propTypes = {
element: PropTypes.node,
};