-
-
Notifications
You must be signed in to change notification settings - Fork 231
/
theme-provider.tsx
84 lines (76 loc) 路 2.21 KB
/
theme-provider.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
/**
* @module
*
* The `ThemeProvider` to wrap your editor with when using these components.
*/
import React, {
createContext,
ElementType,
ReactElement,
ReactNode,
useContext,
useMemo,
} from 'react';
import { cx, deepMerge } from '@remirror/core';
import {
createThemeVariables,
CSSProperties,
defaultRemirrorTheme,
RemirrorThemeType,
THEME,
} from '@remirror/theme';
const ThemeContext = createContext<RemirrorThemeType>({});
export interface UseThemeProps {
/**
* The theme to customise the look and feel of your remirror editor.
*/
theme?: RemirrorThemeType;
/**
* Any extra class names to add to the wrapper component.
*/
className?: string;
}
/**
* Get the theme from the context and convert it to a style object which can be
* attached to any element.
*
* The theme provided is deeply merged with the parent theme.
*/
export function useTheme(props: UseThemeProps = {}): {
theme: RemirrorThemeType;
style: CSSProperties;
className?: string;
} {
// Get theme from parent context.
const parent = useContext(ThemeContext);
const theme = useMemo(() => deepMerge(parent, props.theme ?? {}), [parent, props.theme]);
const style = useMemo(() => createThemeVariables(theme).styles, [theme]);
const className = cx(THEME, props.className);
return useMemo(() => ({ style, className, theme }), [style, className, theme]);
}
export interface ThemeProviderProps extends UseThemeProps {
/**
* A custom component to use for the wrapper.
*
* @defaultValue 'div'
*/
as?: ElementType<{ style?: CSSProperties; className?: string }>;
children: ReactNode;
}
/**
* This the `ThemeProvider`. Wrap your editor with it to customise the theming
* of content within your editor.
*
* Please be aware that this wraps your component in an extra dom layer.
*/
export const ThemeProvider = (props: ThemeProviderProps): ReactElement<ThemeProviderProps> => {
const { children, as: Component = 'div' } = props;
const { theme, style, className } = useTheme({ theme: props.theme ?? defaultRemirrorTheme });
return (
<ThemeContext.Provider value={theme}>
<Component style={style} className={className}>
{children}
</Component>
</ThemeContext.Provider>
);
};