forked from 100mslive/web-sdks
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathThemeProvider.tsx
98 lines (88 loc) · 2.78 KB
/
ThemeProvider.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
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { Theme } from './stitches.config';
import { createTheme, theme } from './stitches.config';
import useSSR from './useSSR';
const defaultAspectRatio = {
width: 1,
height: 1,
};
export enum ThemeTypes {
// eslint-disable-next-line no-unused-vars
default = 'default',
}
export type ThemeContextValue = {
themeType: string;
theme: Theme;
aspectRatio: { width: number; height: number };
/**
* @param {ThemeTypes} themeToUpdateTo - optional
* Use this to toggle or update the currentTheme.
* if a param is passed, it will set the theme to passed value, otherwise will toggle between light and dark
* depending on current applied theme
*/
toggleTheme: (themeToUpdateTo?: ThemeTypes) => void;
};
export type ThemeProviderProps = {
themeType?: string;
theme?: Theme;
aspectRatio?: { width: number; height: number };
};
const defaultContext = {
themeType: ThemeTypes.default,
theme,
aspectRatio: { width: 1, height: 1 },
toggleTheme: (_themeToUpdateTo?: ThemeTypes) => {
return;
},
};
export const ThemeContext = React.createContext<ThemeContextValue>(defaultContext);
/**
* Wrap this around your root component to get access to theme
* eg:
* <ThemeProvider type="dark" appBuilder={{ aspectRatio: { width:1, height: 1} }}>
* <App />
* </ThemeProvider>
*/
export const HMSThemeProvider: React.FC<React.PropsWithChildren<ThemeProviderProps>> = ({
themeType,
theme: userTheme,
aspectRatio = defaultAspectRatio,
children,
}) => {
const systemTheme = ThemeTypes.default;
const [currentTheme, setCurrentTheme] = useState(themeType || systemTheme);
const previousClassName = useRef('');
const { isBrowser } = useSSR();
const updatedTheme = useMemo(() => {
const updatedTheme = createTheme({ themeType: currentTheme, theme: userTheme || {} });
if (!isBrowser) {
return updatedTheme;
}
if (previousClassName.current) {
document.documentElement.classList.remove(previousClassName.current);
}
previousClassName.current = updatedTheme.className;
document.documentElement.classList.add(updatedTheme);
return updatedTheme;
}, [userTheme, currentTheme, isBrowser]);
const toggleTheme = useCallback((themeToUpdateTo?: ThemeTypes) => {
if (themeToUpdateTo) {
setCurrentTheme(themeToUpdateTo);
return;
}
setCurrentTheme(ThemeTypes.default);
}, []);
useEffect(() => {
if (themeType) {
setCurrentTheme(themeType);
}
}, [themeType]);
return (
<ThemeContext.Provider
value={{ themeType: currentTheme, theme: updatedTheme as unknown as Theme, aspectRatio, toggleTheme }}
>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => React.useContext(ThemeContext);