@arcblock/ux 2.12.48 → 2.12.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Config/config-provider.d.ts +37 -0
- package/lib/Config/config-provider.js +93 -0
- package/lib/Config/theme-mode-toggle.d.ts +1 -0
- package/lib/Config/theme-mode-toggle.js +22 -0
- package/lib/Locale/context.d.ts +1 -1
- package/lib/Theme/theme-provider.d.ts +6 -5
- package/lib/Theme/theme-provider.js +0 -1
- package/lib/Theme/theme.d.ts +19 -16
- package/lib/Theme/theme.js +73 -41
- package/lib/Util/index.d.ts +1 -0
- package/lib/Util/index.js +5 -1
- package/lib/type.d.ts +2 -1
- package/lib/withTheme/index.d.ts +4 -2
- package/package.json +6 -5
- package/src/Config/config-provider.tsx +123 -0
- package/src/Config/theme-mode-toggle.tsx +22 -0
- package/src/Locale/context.tsx +1 -1
- package/src/Theme/theme-provider.tsx +7 -9
- package/src/Theme/theme.ts +117 -94
- package/src/Util/index.ts +5 -0
- package/src/type.d.ts +2 -1
- package/src/withTheme/index.tsx +3 -1
@@ -0,0 +1,37 @@
|
|
1
|
+
import { ReactNode } from 'react';
|
2
|
+
import type { ThemeOptions } from '@mui/material/styles';
|
3
|
+
import { LocaleProviderProps } from '../Locale/context';
|
4
|
+
import { ThemeProviderProps } from '../Theme/theme-provider';
|
5
|
+
import { ThemeMode } from '../type';
|
6
|
+
export interface ConfigContextType {
|
7
|
+
mode: ThemeMode;
|
8
|
+
themeOptions: ThemeOptions;
|
9
|
+
toggleMode: () => void;
|
10
|
+
}
|
11
|
+
export declare function isThemeRecord(theme: ThemeOptions | Record<ThemeMode, ThemeOptions>): theme is Record<ThemeMode, ThemeOptions>;
|
12
|
+
export interface ConfigProviderProps extends Omit<LocaleProviderProps, 'translations'>, Omit<ThemeProviderProps, 'theme'> {
|
13
|
+
children: ReactNode;
|
14
|
+
prefer?: ThemeMode;
|
15
|
+
theme?: ThemeOptions | Record<ThemeMode, ThemeOptions>;
|
16
|
+
translations?: Record<string, any>;
|
17
|
+
}
|
18
|
+
/**
|
19
|
+
* 集中化配置
|
20
|
+
*/
|
21
|
+
export declare function ConfigProvider({ children, prefer, theme: themeOptions, injectFirst, locale, fallbackLocale, translations, languages, onLoadingTranslation, }: ConfigProviderProps): import("react/jsx-runtime").JSX.Element;
|
22
|
+
export declare namespace ConfigProvider {
|
23
|
+
var useConfig: typeof import("./config-provider").useConfig;
|
24
|
+
}
|
25
|
+
export declare function useConfig(): {
|
26
|
+
mode: ThemeMode;
|
27
|
+
themeOptions: ThemeOptions;
|
28
|
+
toggleMode: () => void;
|
29
|
+
locale: import("../type").Locale;
|
30
|
+
changeLocale: (locale: import("../type").Locale) => void;
|
31
|
+
t: (key: string, data?: Record<string, any>) => string;
|
32
|
+
languages: {
|
33
|
+
code: string;
|
34
|
+
name: string;
|
35
|
+
}[];
|
36
|
+
theme: import("@mui/material/styles").Theme;
|
37
|
+
};
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import { createContext, useContext, useMemo, useState, useCallback } from 'react';
|
3
|
+
import useMediaQuery from '@mui/material/useMediaQuery';
|
4
|
+
import set from 'lodash/set';
|
5
|
+
import { LocaleProvider, useLocaleContext } from '../Locale/context';
|
6
|
+
import ThemeProvider from '../Theme/theme-provider';
|
7
|
+
import { createTheme, useTheme } from '../Theme';
|
8
|
+
const ConfigContext = /*#__PURE__*/createContext({});
|
9
|
+
const preferThemeModeKey = 'blocklet_theme_prefer';
|
10
|
+
export function isThemeRecord(theme) {
|
11
|
+
return 'light' in theme || 'dark' in theme;
|
12
|
+
}
|
13
|
+
/**
|
14
|
+
* 集中化配置
|
15
|
+
*/
|
16
|
+
export function ConfigProvider({
|
17
|
+
children,
|
18
|
+
// theme config
|
19
|
+
prefer,
|
20
|
+
theme: themeOptions,
|
21
|
+
injectFirst,
|
22
|
+
// locale config
|
23
|
+
locale,
|
24
|
+
fallbackLocale,
|
25
|
+
translations = {},
|
26
|
+
languages,
|
27
|
+
onLoadingTranslation
|
28
|
+
}) {
|
29
|
+
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
30
|
+
const [mode, setMode] = useState(() => {
|
31
|
+
const preferMode = localStorage.getItem(preferThemeModeKey);
|
32
|
+
if (preferMode && (preferMode === 'light' || preferMode === 'dark')) {
|
33
|
+
return preferMode;
|
34
|
+
}
|
35
|
+
return prefer || (prefersDarkMode ? 'dark' : 'light');
|
36
|
+
});
|
37
|
+
const _themeOptions = useMemo(() => {
|
38
|
+
let result = {};
|
39
|
+
if (themeOptions) {
|
40
|
+
if (isThemeRecord(themeOptions)) {
|
41
|
+
result = themeOptions[mode] ? {
|
42
|
+
...themeOptions[mode]
|
43
|
+
} : {};
|
44
|
+
} else {
|
45
|
+
result = {
|
46
|
+
...themeOptions
|
47
|
+
};
|
48
|
+
}
|
49
|
+
}
|
50
|
+
set(result, 'palette.mode', mode);
|
51
|
+
set(result, 'mode', mode);
|
52
|
+
return result;
|
53
|
+
}, [mode, themeOptions]);
|
54
|
+
const theme = useMemo(() => {
|
55
|
+
return createTheme(_themeOptions);
|
56
|
+
}, [_themeOptions]);
|
57
|
+
const toggleMode = useCallback(() => {
|
58
|
+
const newMode = mode === 'light' ? 'dark' : 'light';
|
59
|
+
setMode(newMode);
|
60
|
+
localStorage.setItem(preferThemeModeKey, newMode);
|
61
|
+
}, [mode, setMode]);
|
62
|
+
const config = useMemo(() => ({
|
63
|
+
mode,
|
64
|
+
themeOptions: _themeOptions,
|
65
|
+
toggleMode
|
66
|
+
}), [mode, _themeOptions, toggleMode]);
|
67
|
+
return /*#__PURE__*/_jsx(ConfigContext.Provider, {
|
68
|
+
value: config,
|
69
|
+
children: /*#__PURE__*/_jsx(LocaleProvider, {
|
70
|
+
locale: locale,
|
71
|
+
fallbackLocale: fallbackLocale,
|
72
|
+
translations: translations,
|
73
|
+
onLoadingTranslation: onLoadingTranslation,
|
74
|
+
languages: languages,
|
75
|
+
children: /*#__PURE__*/_jsx(ThemeProvider, {
|
76
|
+
theme: theme,
|
77
|
+
injectFirst: injectFirst,
|
78
|
+
children: children
|
79
|
+
})
|
80
|
+
})
|
81
|
+
});
|
82
|
+
}
|
83
|
+
export function useConfig() {
|
84
|
+
const theme = useTheme();
|
85
|
+
const localeCtx = useLocaleContext();
|
86
|
+
const configCtx = useContext(ConfigContext);
|
87
|
+
return {
|
88
|
+
theme,
|
89
|
+
...localeCtx,
|
90
|
+
...configCtx
|
91
|
+
};
|
92
|
+
}
|
93
|
+
ConfigProvider.useConfig = useConfig;
|
@@ -0,0 +1 @@
|
|
1
|
+
export default function ThemeModeToggle(): import("react/jsx-runtime").JSX.Element | null;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import { IconButton } from '@mui/material';
|
3
|
+
import LightModeOutlinedIcon from '@mui/icons-material/LightModeOutlined';
|
4
|
+
import Brightness2OutlinedIcon from '@mui/icons-material/Brightness2Outlined';
|
5
|
+
import { useConfig } from './config-provider';
|
6
|
+
export default function ThemeModeToggle() {
|
7
|
+
const {
|
8
|
+
mode,
|
9
|
+
toggleMode
|
10
|
+
} = useConfig();
|
11
|
+
if (!toggleMode) {
|
12
|
+
if (process.env.NODE_ENV !== 'production') {
|
13
|
+
console.warn('Please ensure the component is wrapped with ConfigProvider context');
|
14
|
+
}
|
15
|
+
return null;
|
16
|
+
}
|
17
|
+
return /*#__PURE__*/_jsx(IconButton, {
|
18
|
+
onClick: toggleMode,
|
19
|
+
color: "inherit",
|
20
|
+
children: mode === 'light' ? /*#__PURE__*/_jsx(LightModeOutlinedIcon, {}) : /*#__PURE__*/_jsx(Brightness2OutlinedIcon, {})
|
21
|
+
});
|
22
|
+
}
|
package/lib/Locale/context.d.ts
CHANGED
@@ -4,7 +4,7 @@ declare const getLocale: (languages?: {
|
|
4
4
|
code: string;
|
5
5
|
}[]) => string;
|
6
6
|
declare const setLocale: (locale: Locale) => void;
|
7
|
-
interface LocaleProviderProps {
|
7
|
+
export interface LocaleProviderProps {
|
8
8
|
children: ReactNode;
|
9
9
|
locale?: Locale;
|
10
10
|
fallbackLocale?: Locale;
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import { Theme } from '@mui/material/styles';
|
3
|
+
export interface ThemeProviderProps {
|
4
|
+
children?: React.ReactNode;
|
5
|
+
theme: Theme;
|
6
|
+
injectFirst?: boolean;
|
7
|
+
}
|
3
8
|
/**
|
4
9
|
* 默认的 theme provider, 可以为 webapp/blocklet 快捷的配置好 mui theme provider
|
5
10
|
*/
|
6
|
-
declare function ThemeProvider({ children, theme, injectFirst
|
7
|
-
children?: React.ReactNode;
|
8
|
-
theme: Theme;
|
9
|
-
injectFirst: boolean;
|
10
|
-
}): import("react/jsx-runtime").JSX.Element;
|
11
|
+
declare function ThemeProvider({ children, theme, injectFirst }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
11
12
|
declare namespace ThemeProvider {
|
12
13
|
var propTypes: {
|
13
14
|
children: PropTypes.Requireable<any>;
|
@@ -5,7 +5,6 @@ import StyledEngineProvider from '@mui/material/StyledEngineProvider';
|
|
5
5
|
import CssBaseline from '@mui/material/CssBaseline';
|
6
6
|
import { createTheme } from './theme';
|
7
7
|
const defaultTheme = createTheme();
|
8
|
-
|
9
8
|
/**
|
10
9
|
* 默认的 theme provider, 可以为 webapp/blocklet 快捷的配置好 mui theme provider
|
11
10
|
*/
|
package/lib/Theme/theme.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { Components, type
|
2
|
-
import { Typography
|
1
|
+
import { Components, type ThemeOptions } from '@mui/material/styles';
|
2
|
+
import type { Typography } from '@mui/material/styles/createTypography';
|
3
3
|
import '@fontsource/inter/latin-300.css';
|
4
4
|
import '@fontsource/inter/latin-400.css';
|
5
5
|
import '@fontsource/inter/latin-500.css';
|
@@ -8,9 +8,10 @@ import '@fontsource/inter/latin-ext-300.css';
|
|
8
8
|
import '@fontsource/inter/latin-ext-400.css';
|
9
9
|
import '@fontsource/inter/latin-ext-500.css';
|
10
10
|
import '@fontsource/inter/latin-ext-700.css';
|
11
|
+
import { ThemeMode } from '../type';
|
11
12
|
declare module '@mui/material/styles' {
|
12
13
|
interface Theme {
|
13
|
-
mode?:
|
14
|
+
mode?: ThemeMode;
|
14
15
|
themeName?: string;
|
15
16
|
pageWidth?: string;
|
16
17
|
colors?: Record<string, string>;
|
@@ -23,24 +24,26 @@ declare module '@mui/material/styles' {
|
|
23
24
|
};
|
24
25
|
}
|
25
26
|
interface ThemeOptions {
|
26
|
-
mode?: string;
|
27
27
|
themeName?: string;
|
28
|
+
mode?: ThemeMode;
|
28
29
|
pageWidth?: string;
|
29
30
|
colors?: Record<string, string>;
|
31
|
+
/** @deprecated 请使用 components */
|
32
|
+
overrides?: Components<Omit<Theme, 'components'>>;
|
30
33
|
}
|
31
34
|
interface TypeText {
|
32
35
|
hint: string;
|
33
36
|
}
|
34
37
|
}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
}
|
38
|
+
declare module '@mui/material/styles/createTypography' {
|
39
|
+
interface TypographyOptions {
|
40
|
+
useNextVariants?: boolean;
|
41
|
+
color?: Record<string, string>;
|
42
|
+
button?: {
|
43
|
+
fontWeight?: number;
|
44
|
+
};
|
45
|
+
}
|
46
|
+
}
|
47
|
+
export declare function createDefaultThemeOptions(mode?: ThemeMode): ThemeOptions;
|
48
|
+
export declare const create: ({ mode, pageWidth, overrides, palette, components, ...rest }?: ThemeOptions) => import("@mui/material/styles").Theme;
|
49
|
+
export declare const createTheme: ({ mode, pageWidth, overrides, palette, components, ...rest }?: ThemeOptions) => import("@mui/material/styles").Theme;
|
package/lib/Theme/theme.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
/* eslint-disable no-shadow */
|
2
2
|
// https://app.zeplin.io/styleguide/5d1436f1e97c2156f49c0725/colors
|
3
3
|
import { createTheme as _createTheme, responsiveFontSizes } from '@mui/material/styles';
|
4
|
+
import { deepmerge } from '@mui/utils';
|
4
5
|
// 为了避免加载全量的字体导致打包后体积太大,目前只选择了 latin 语系的字体
|
5
6
|
import '@fontsource/inter/latin-300.css';
|
6
7
|
import '@fontsource/inter/latin-400.css';
|
@@ -11,49 +12,29 @@ import '@fontsource/inter/latin-ext-400.css';
|
|
11
12
|
import '@fontsource/inter/latin-ext-500.css';
|
12
13
|
import '@fontsource/inter/latin-ext-700.css';
|
13
14
|
import colors from '../Colors';
|
15
|
+
import { cleanedObj } from '../Util';
|
14
16
|
|
15
17
|
// 扩展 Theme
|
16
18
|
|
19
|
+
// 扩展 TypographyOptions
|
20
|
+
|
17
21
|
const muiDarkTheme = _createTheme({
|
18
22
|
palette: {
|
19
23
|
mode: 'dark'
|
20
24
|
}
|
21
25
|
});
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
components,
|
33
|
-
...rest
|
34
|
-
} = {}) => {
|
35
|
-
// palette 考虑 light & dark mode, dark mode 需要持续完善
|
36
|
-
// - 能配合 ColorModeContext 使用
|
37
|
-
// - 为 dark mode 系统的设计整个 palette, 不要单个 color 设置
|
38
|
-
const _palette = mode === 'light' ? Object.assign({
|
39
|
-
...colors,
|
40
|
-
background: {
|
41
|
-
paper: colors.common.white,
|
42
|
-
default: colors.background.default
|
43
|
-
},
|
44
|
-
mode
|
45
|
-
}, palette || {}) : Object.assign({
|
46
|
-
...muiDarkTheme.palette,
|
47
|
-
background: {
|
48
|
-
paper: colors.grey[900],
|
49
|
-
default: colors.grey[900]
|
26
|
+
const DEFAULT_FONT_FAMILY = ['Inter', 'Avenir', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', '"Helvetica Neue"', 'Arial', 'sans-serif', '"Apple Color Emoji"', '"Segoe UI Emoji"', '"Segoe UI Symbol"'].join(',');
|
27
|
+
export function createDefaultThemeOptions(mode = 'light') {
|
28
|
+
const result = {
|
29
|
+
palette: {
|
30
|
+
mode,
|
31
|
+
...colors,
|
32
|
+
background: {
|
33
|
+
paper: colors.common.white,
|
34
|
+
default: colors.background.default
|
35
|
+
}
|
50
36
|
},
|
51
|
-
|
52
|
-
}, palette || {});
|
53
|
-
const theme = _createTheme({
|
54
|
-
themeName: 'ArcBlock',
|
55
|
-
palette: _palette,
|
56
|
-
typography: Object.assign({
|
37
|
+
typography: {
|
57
38
|
useNextVariants: true,
|
58
39
|
color: {
|
59
40
|
// 此处 #222222 必须硬编码, layout/sidebar.js -> Icon/image 加载图片时 color 会影响加载路径
|
@@ -63,12 +44,12 @@ export const create = ({
|
|
63
44
|
main: mode === 'light' ? '#222222' : colors.common.white,
|
64
45
|
gray: mode === 'light' ? colors.grey[500] : colors.grey[300]
|
65
46
|
},
|
66
|
-
fontFamily:
|
47
|
+
fontFamily: DEFAULT_FONT_FAMILY,
|
67
48
|
// button 默认使用粗体
|
68
49
|
button: {
|
69
50
|
fontWeight: 700
|
70
51
|
}
|
71
|
-
},
|
52
|
+
},
|
72
53
|
components: {
|
73
54
|
MuiButton: {
|
74
55
|
styleOverrides: {
|
@@ -111,14 +92,45 @@ export const create = ({
|
|
111
92
|
color: mode === 'light' ? colors.grey[900] : colors.grey[300]
|
112
93
|
}
|
113
94
|
}
|
114
|
-
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
};
|
98
|
+
// 深色主题
|
99
|
+
if (mode === 'dark') {
|
100
|
+
result.palette = {
|
101
|
+
...muiDarkTheme.palette,
|
102
|
+
background: {
|
103
|
+
paper: colors.grey[900],
|
104
|
+
default: colors.grey[900]
|
105
|
+
}
|
106
|
+
};
|
107
|
+
}
|
108
|
+
return result;
|
109
|
+
}
|
110
|
+
|
111
|
+
// https://material-ui.com/customization/default-theme/
|
112
|
+
export const create = ({
|
113
|
+
mode = 'light',
|
114
|
+
pageWidth = 'md',
|
115
|
+
overrides,
|
116
|
+
// original theme options
|
117
|
+
palette,
|
118
|
+
components,
|
119
|
+
...rest
|
120
|
+
} = {}) => {
|
121
|
+
const userThemeOptions = {
|
122
|
+
themeName: 'ArcBlock',
|
123
|
+
palette: {
|
124
|
+
...palette,
|
125
|
+
mode
|
126
|
+
},
|
127
|
+
components: {
|
115
128
|
...overrides,
|
116
129
|
...components
|
117
130
|
},
|
131
|
+
// @TODO 考虑使用 theme.shape.pageWidth
|
118
132
|
pageWidth,
|
119
|
-
|
120
|
-
* @deprecated 应使用 theme.palette 中的颜色
|
121
|
-
*/
|
133
|
+
// @TODO 考虑使用 theme.palette.common
|
122
134
|
colors: {
|
123
135
|
white: '#FFFFFF',
|
124
136
|
dark: '#4A707C',
|
@@ -139,9 +151,29 @@ export const create = ({
|
|
139
151
|
danger: '#D0021B',
|
140
152
|
lightGrey: '#BCBCBC'
|
141
153
|
},
|
154
|
+
// @deprecated use theme.palette.mode
|
142
155
|
mode,
|
143
156
|
...rest
|
144
|
-
}
|
157
|
+
};
|
158
|
+
// Blocklet Server 后台配置的全局主题
|
159
|
+
const blockletThemeOptions = window.blocklet?.theme?.[mode] ?? {};
|
160
|
+
// choose mode
|
161
|
+
const defaultThemeOptions = createDefaultThemeOptions(mode);
|
162
|
+
// 同官方合并行为
|
163
|
+
const mergedThemeOptions = deepmerge(deepmerge(defaultThemeOptions, cleanedObj(blockletThemeOptions)), cleanedObj(userThemeOptions));
|
164
|
+
const theme = _createTheme(mergedThemeOptions);
|
165
|
+
|
166
|
+
/**
|
167
|
+
* 响应式字体,配置后,theme.typography 会变为下面的结构
|
168
|
+
* {
|
169
|
+
* "h1": {
|
170
|
+
* "fontSize": "3rem",
|
171
|
+
* "@media (min-width:600px)": {
|
172
|
+
* "fontSize": "3.3125rem"
|
173
|
+
* }
|
174
|
+
* }
|
175
|
+
* }
|
176
|
+
*/
|
145
177
|
const enhanced = responsiveFontSizes(theme, {
|
146
178
|
breakpoints: ['xs', 'sm', 'md', 'lg'],
|
147
179
|
disableAlign: false,
|
package/lib/Util/index.d.ts
CHANGED
@@ -87,4 +87,5 @@ export declare const getTranslation: (translations: TranslationsObject, locale:
|
|
87
87
|
defaultValue?: string;
|
88
88
|
}) => string;
|
89
89
|
export declare const lazyRetry: (fn: () => Promise<any>) => import("react").LazyExoticComponent<import("react").ComponentType<any>>;
|
90
|
+
export declare const cleanedObj: (obj: object) => import("lodash").Dictionary<any>;
|
90
91
|
export {};
|
package/lib/Util/index.js
CHANGED
@@ -3,6 +3,7 @@ import { lazy } from 'react';
|
|
3
3
|
import padStart from 'lodash/padStart';
|
4
4
|
import { getDIDMotifInfo, colors } from '@arcblock/did-motif';
|
5
5
|
import isNil from 'lodash/isNil';
|
6
|
+
import omitBy from 'lodash/omitBy';
|
6
7
|
import pRetry from 'p-retry';
|
7
8
|
import { DID_PREFIX, BLOCKLET_SERVICE_PATH_PREFIX } from './constant';
|
8
9
|
let dateTool = null;
|
@@ -376,4 +377,7 @@ export const lazyRetry = fn => /*#__PURE__*/lazy(() => pRetry(async () => {
|
|
376
377
|
// 只需要重试两次,加上原本的一次,总共三次
|
377
378
|
{
|
378
379
|
retries: 2
|
379
|
-
}));
|
380
|
+
}));
|
381
|
+
export const cleanedObj = obj => {
|
382
|
+
return omitBy(obj, isNil);
|
383
|
+
};
|
package/lib/type.d.ts
CHANGED
@@ -4,6 +4,7 @@ import type { LiteralUnion } from 'type-fest';
|
|
4
4
|
export type $TSFixMe = any;
|
5
5
|
export type Translations = Record<string, Record<string, any>>;
|
6
6
|
export type Locale = LiteralUnion<'en' | 'zh', string>;
|
7
|
+
export type ThemeMode = 'light' | 'dark';
|
7
8
|
|
8
9
|
// TODO: 以下为 blocklet 应用专属的全局对象类型,可以更加具体
|
9
10
|
export type User = Record<string, any>;
|
@@ -25,7 +26,7 @@ export type Blocklet = {
|
|
25
26
|
version: string;
|
26
27
|
mode: string;
|
27
28
|
tenantMode: 'single' | 'multiple';
|
28
|
-
theme: Theme
|
29
|
+
theme: Record<ThemeMode, Theme>;
|
29
30
|
navigation: $TSFixMe[];
|
30
31
|
preferences: Record<string, any>;
|
31
32
|
languages: {
|
package/lib/withTheme/index.d.ts
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
import { Breakpoint } from '@mui/material';
|
1
2
|
import { type PaletteOptions } from '@mui/material/styles/createPalette';
|
2
3
|
import { type TypographyOptions } from '@mui/material/styles/createTypography';
|
4
|
+
import { ThemeMode } from '../type';
|
3
5
|
declare function withTheme<P extends object>(Component: React.ComponentType<P>, { mode, pageWidth, palette, typography, }?: {
|
4
|
-
mode?:
|
5
|
-
pageWidth?:
|
6
|
+
mode?: ThemeMode;
|
7
|
+
pageWidth?: Breakpoint;
|
6
8
|
palette?: PaletteOptions;
|
7
9
|
typography?: TypographyOptions;
|
8
10
|
}): (props: P) => import("react/jsx-runtime").JSX.Element;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "2.12.
|
3
|
+
"version": "2.12.49",
|
4
4
|
"description": "Common used react components for arcblock products",
|
5
5
|
"keywords": [
|
6
6
|
"react",
|
@@ -65,15 +65,16 @@
|
|
65
65
|
"@emotion/styled": "^11.10.4",
|
66
66
|
"@mui/icons-material": ">=5.15.0",
|
67
67
|
"@mui/material": ">=5.15.0",
|
68
|
+
"@mui/utils": ">=5.15.0",
|
68
69
|
"react": ">=18.2.0",
|
69
70
|
"react-router-dom": ">=6.22.3"
|
70
71
|
},
|
71
|
-
"gitHead": "
|
72
|
+
"gitHead": "ffebc9c5df6d576f08c3538b4db75d7ec8cf00be",
|
72
73
|
"dependencies": {
|
73
74
|
"@arcblock/did-motif": "^1.1.13",
|
74
|
-
"@arcblock/icons": "^2.12.
|
75
|
-
"@arcblock/nft-display": "^2.12.
|
76
|
-
"@arcblock/react-hooks": "^2.12.
|
75
|
+
"@arcblock/icons": "^2.12.49",
|
76
|
+
"@arcblock/nft-display": "^2.12.49",
|
77
|
+
"@arcblock/react-hooks": "^2.12.49",
|
77
78
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
78
79
|
"@fontsource/inter": "^5.0.16",
|
79
80
|
"@fontsource/ubuntu-mono": "^5.0.18",
|
@@ -0,0 +1,123 @@
|
|
1
|
+
import { createContext, useContext, ReactNode, useMemo, useState, useCallback } from 'react';
|
2
|
+
import type { ThemeOptions } from '@mui/material/styles';
|
3
|
+
import useMediaQuery from '@mui/material/useMediaQuery';
|
4
|
+
import set from 'lodash/set';
|
5
|
+
import { LocaleProvider, LocaleProviderProps, useLocaleContext } from '../Locale/context';
|
6
|
+
import ThemeProvider, { ThemeProviderProps } from '../Theme/theme-provider';
|
7
|
+
import { createTheme, useTheme } from '../Theme';
|
8
|
+
import { ThemeMode } from '../type';
|
9
|
+
|
10
|
+
export interface ConfigContextType {
|
11
|
+
mode: ThemeMode;
|
12
|
+
themeOptions: ThemeOptions;
|
13
|
+
toggleMode: () => void;
|
14
|
+
}
|
15
|
+
|
16
|
+
const ConfigContext = createContext<ConfigContextType>({} as ConfigContextType);
|
17
|
+
const preferThemeModeKey = 'blocklet_theme_prefer';
|
18
|
+
|
19
|
+
export function isThemeRecord(
|
20
|
+
theme: ThemeOptions | Record<ThemeMode, ThemeOptions>
|
21
|
+
): theme is Record<ThemeMode, ThemeOptions> {
|
22
|
+
return 'light' in theme || 'dark' in theme;
|
23
|
+
}
|
24
|
+
|
25
|
+
export interface ConfigProviderProps
|
26
|
+
extends Omit<LocaleProviderProps, 'translations'>,
|
27
|
+
Omit<ThemeProviderProps, 'theme'> {
|
28
|
+
children: ReactNode;
|
29
|
+
prefer?: ThemeMode;
|
30
|
+
theme?: ThemeOptions | Record<ThemeMode, ThemeOptions>;
|
31
|
+
translations?: Record<string, any>;
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* 集中化配置
|
36
|
+
*/
|
37
|
+
export function ConfigProvider({
|
38
|
+
children,
|
39
|
+
// theme config
|
40
|
+
prefer,
|
41
|
+
theme: themeOptions,
|
42
|
+
injectFirst,
|
43
|
+
// locale config
|
44
|
+
locale,
|
45
|
+
fallbackLocale,
|
46
|
+
translations = {},
|
47
|
+
languages,
|
48
|
+
onLoadingTranslation,
|
49
|
+
}: ConfigProviderProps) {
|
50
|
+
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
51
|
+
const [mode, setMode] = useState<ThemeMode>(() => {
|
52
|
+
const preferMode = localStorage.getItem(preferThemeModeKey) as ThemeMode;
|
53
|
+
if (preferMode && (preferMode === 'light' || preferMode === 'dark')) {
|
54
|
+
return preferMode;
|
55
|
+
}
|
56
|
+
return prefer || (prefersDarkMode ? 'dark' : 'light');
|
57
|
+
});
|
58
|
+
|
59
|
+
const _themeOptions = useMemo(() => {
|
60
|
+
let result: ThemeOptions = {};
|
61
|
+
|
62
|
+
if (themeOptions) {
|
63
|
+
if (isThemeRecord(themeOptions)) {
|
64
|
+
result = themeOptions[mode] ? { ...themeOptions[mode] } : {};
|
65
|
+
} else {
|
66
|
+
result = { ...themeOptions };
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
set(result, 'palette.mode', mode);
|
71
|
+
set(result, 'mode', mode);
|
72
|
+
|
73
|
+
return result;
|
74
|
+
}, [mode, themeOptions]);
|
75
|
+
|
76
|
+
const theme = useMemo(() => {
|
77
|
+
return createTheme(_themeOptions);
|
78
|
+
}, [_themeOptions]);
|
79
|
+
|
80
|
+
const toggleMode = useCallback(() => {
|
81
|
+
const newMode = mode === 'light' ? 'dark' : 'light';
|
82
|
+
setMode(newMode);
|
83
|
+
localStorage.setItem(preferThemeModeKey, newMode);
|
84
|
+
}, [mode, setMode]);
|
85
|
+
|
86
|
+
const config = useMemo(
|
87
|
+
() => ({
|
88
|
+
mode,
|
89
|
+
themeOptions: _themeOptions,
|
90
|
+
toggleMode,
|
91
|
+
}),
|
92
|
+
[mode, _themeOptions, toggleMode]
|
93
|
+
);
|
94
|
+
|
95
|
+
return (
|
96
|
+
<ConfigContext.Provider value={config}>
|
97
|
+
<LocaleProvider
|
98
|
+
locale={locale}
|
99
|
+
fallbackLocale={fallbackLocale}
|
100
|
+
translations={translations}
|
101
|
+
onLoadingTranslation={onLoadingTranslation}
|
102
|
+
languages={languages}>
|
103
|
+
<ThemeProvider theme={theme} injectFirst={injectFirst}>
|
104
|
+
{children}
|
105
|
+
</ThemeProvider>
|
106
|
+
</LocaleProvider>
|
107
|
+
</ConfigContext.Provider>
|
108
|
+
);
|
109
|
+
}
|
110
|
+
|
111
|
+
export function useConfig() {
|
112
|
+
const theme = useTheme();
|
113
|
+
const localeCtx = useLocaleContext();
|
114
|
+
const configCtx = useContext(ConfigContext);
|
115
|
+
|
116
|
+
return {
|
117
|
+
theme,
|
118
|
+
...localeCtx,
|
119
|
+
...configCtx,
|
120
|
+
};
|
121
|
+
}
|
122
|
+
|
123
|
+
ConfigProvider.useConfig = useConfig;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { IconButton } from '@mui/material';
|
2
|
+
import LightModeOutlinedIcon from '@mui/icons-material/LightModeOutlined';
|
3
|
+
import Brightness2OutlinedIcon from '@mui/icons-material/Brightness2Outlined';
|
4
|
+
import { useConfig } from './config-provider';
|
5
|
+
|
6
|
+
export default function ThemeModeToggle() {
|
7
|
+
const { mode, toggleMode } = useConfig();
|
8
|
+
|
9
|
+
if (!toggleMode) {
|
10
|
+
if (process.env.NODE_ENV !== 'production') {
|
11
|
+
console.warn('Please ensure the component is wrapped with ConfigProvider context');
|
12
|
+
}
|
13
|
+
|
14
|
+
return null;
|
15
|
+
}
|
16
|
+
|
17
|
+
return (
|
18
|
+
<IconButton onClick={toggleMode} color="inherit">
|
19
|
+
{mode === 'light' ? <LightModeOutlinedIcon /> : <Brightness2OutlinedIcon />}
|
20
|
+
</IconButton>
|
21
|
+
);
|
22
|
+
}
|
package/src/Locale/context.tsx
CHANGED
@@ -6,18 +6,16 @@ import { createTheme } from './theme';
|
|
6
6
|
|
7
7
|
const defaultTheme = createTheme();
|
8
8
|
|
9
|
+
export interface ThemeProviderProps {
|
10
|
+
children?: React.ReactNode;
|
11
|
+
theme: Theme;
|
12
|
+
injectFirst?: boolean;
|
13
|
+
}
|
14
|
+
|
9
15
|
/**
|
10
16
|
* 默认的 theme provider, 可以为 webapp/blocklet 快捷的配置好 mui theme provider
|
11
17
|
*/
|
12
|
-
export default function ThemeProvider({
|
13
|
-
children,
|
14
|
-
theme,
|
15
|
-
injectFirst,
|
16
|
-
}: {
|
17
|
-
children?: React.ReactNode;
|
18
|
-
theme: Theme;
|
19
|
-
injectFirst: boolean;
|
20
|
-
}) {
|
18
|
+
export default function ThemeProvider({ children, theme, injectFirst }: ThemeProviderProps) {
|
21
19
|
return (
|
22
20
|
// injectFirst 会影响 makeStyles 自定义样式和 mui styles 覆盖问题
|
23
21
|
<StyledEngineProvider injectFirst={injectFirst}>
|
package/src/Theme/theme.ts
CHANGED
@@ -1,14 +1,8 @@
|
|
1
1
|
/* eslint-disable no-shadow */
|
2
2
|
// https://app.zeplin.io/styleguide/5d1436f1e97c2156f49c0725/colors
|
3
|
-
import {
|
4
|
-
|
5
|
-
|
6
|
-
PaletteOptions,
|
7
|
-
responsiveFontSizes,
|
8
|
-
type Theme,
|
9
|
-
type ThemeOptions,
|
10
|
-
} from '@mui/material/styles';
|
11
|
-
import { Typography, TypographyOptions } from '@mui/material/styles/createTypography';
|
3
|
+
import { createTheme as _createTheme, Components, responsiveFontSizes, type ThemeOptions } from '@mui/material/styles';
|
4
|
+
import { deepmerge } from '@mui/utils';
|
5
|
+
import type { Typography } from '@mui/material/styles/createTypography';
|
12
6
|
// 为了避免加载全量的字体导致打包后体积太大,目前只选择了 latin 语系的字体
|
13
7
|
import '@fontsource/inter/latin-300.css';
|
14
8
|
import '@fontsource/inter/latin-400.css';
|
@@ -19,11 +13,13 @@ import '@fontsource/inter/latin-ext-400.css';
|
|
19
13
|
import '@fontsource/inter/latin-ext-500.css';
|
20
14
|
import '@fontsource/inter/latin-ext-700.css';
|
21
15
|
import colors from '../Colors';
|
16
|
+
import { ThemeMode } from '../type';
|
17
|
+
import { cleanedObj } from '../Util';
|
22
18
|
|
23
19
|
// 扩展 Theme
|
24
20
|
declare module '@mui/material/styles' {
|
25
21
|
interface Theme {
|
26
|
-
mode?:
|
22
|
+
mode?: ThemeMode;
|
27
23
|
themeName?: string;
|
28
24
|
pageWidth?: string;
|
29
25
|
colors?: Record<string, string>;
|
@@ -36,99 +32,71 @@ declare module '@mui/material/styles' {
|
|
36
32
|
};
|
37
33
|
}
|
38
34
|
interface ThemeOptions {
|
39
|
-
mode?: string;
|
40
35
|
themeName?: string;
|
36
|
+
mode?: ThemeMode;
|
41
37
|
pageWidth?: string;
|
42
38
|
colors?: Record<string, string>;
|
39
|
+
/** @deprecated 请使用 components */
|
40
|
+
overrides?: Components<Omit<Theme, 'components'>>;
|
43
41
|
}
|
44
|
-
|
45
42
|
interface TypeText {
|
46
43
|
hint: string;
|
47
44
|
}
|
48
45
|
}
|
46
|
+
// 扩展 TypographyOptions
|
47
|
+
declare module '@mui/material/styles/createTypography' {
|
48
|
+
interface TypographyOptions {
|
49
|
+
useNextVariants?: boolean;
|
50
|
+
color?: Record<string, string>;
|
51
|
+
button?: {
|
52
|
+
fontWeight?: number;
|
53
|
+
};
|
54
|
+
}
|
55
|
+
}
|
49
56
|
|
50
57
|
const muiDarkTheme = _createTheme({ palette: { mode: 'dark' } });
|
51
58
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
typography?: TypographyOptions;
|
67
|
-
overrides?: Components<Omit<Theme, 'components'>>;
|
68
|
-
} & ThemeOptions = {}) => {
|
69
|
-
// palette 考虑 light & dark mode, dark mode 需要持续完善
|
70
|
-
// - 能配合 ColorModeContext 使用
|
71
|
-
// - 为 dark mode 系统的设计整个 palette, 不要单个 color 设置
|
72
|
-
const _palette: PaletteOptions =
|
73
|
-
mode === 'light'
|
74
|
-
? Object.assign(
|
75
|
-
{
|
76
|
-
...colors,
|
77
|
-
background: {
|
78
|
-
paper: colors.common.white,
|
79
|
-
default: colors.background.default,
|
80
|
-
},
|
81
|
-
mode,
|
82
|
-
},
|
83
|
-
palette || {}
|
84
|
-
)
|
85
|
-
: Object.assign(
|
86
|
-
{
|
87
|
-
...muiDarkTheme.palette,
|
88
|
-
background: {
|
89
|
-
paper: colors.grey[900],
|
90
|
-
default: colors.grey[900],
|
91
|
-
},
|
92
|
-
mode,
|
93
|
-
},
|
94
|
-
palette || {}
|
95
|
-
);
|
59
|
+
const DEFAULT_FONT_FAMILY = [
|
60
|
+
'Inter',
|
61
|
+
'Avenir',
|
62
|
+
'-apple-system',
|
63
|
+
'BlinkMacSystemFont',
|
64
|
+
'"Segoe UI"',
|
65
|
+
'Roboto',
|
66
|
+
'"Helvetica Neue"',
|
67
|
+
'Arial',
|
68
|
+
'sans-serif',
|
69
|
+
'"Apple Color Emoji"',
|
70
|
+
'"Segoe UI Emoji"',
|
71
|
+
'"Segoe UI Symbol"',
|
72
|
+
].join(',');
|
96
73
|
|
97
|
-
|
98
|
-
|
99
|
-
palette:
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
'"Apple Color Emoji"',
|
122
|
-
'"Segoe UI Emoji"',
|
123
|
-
'"Segoe UI Symbol"',
|
124
|
-
].join(','),
|
125
|
-
// button 默认使用粗体
|
126
|
-
button: {
|
127
|
-
fontWeight: 700,
|
128
|
-
},
|
74
|
+
export function createDefaultThemeOptions(mode: ThemeMode = 'light'): ThemeOptions {
|
75
|
+
const result: ThemeOptions = {
|
76
|
+
palette: {
|
77
|
+
mode,
|
78
|
+
...colors,
|
79
|
+
background: {
|
80
|
+
paper: colors.common.white,
|
81
|
+
default: colors.background.default,
|
82
|
+
},
|
83
|
+
},
|
84
|
+
typography: {
|
85
|
+
useNextVariants: true,
|
86
|
+
color: {
|
87
|
+
// 此处 #222222 必须硬编码, layout/sidebar.js -> Icon/image 加载图片时 color 会影响加载路径
|
88
|
+
// TODO: 此处硬编码的色值后面需要改为 colors.grey[900],
|
89
|
+
// 或者如果可以的话直接删掉 typography#color, 文本颜色建议使用 theme.palette.text 中的色值?
|
90
|
+
// layout 组件建议重构, sidebar 中建议使用 icon 替换 img (#366)
|
91
|
+
main: mode === 'light' ? '#222222' : colors.common.white,
|
92
|
+
gray: mode === 'light' ? colors.grey[500] : colors.grey[300],
|
93
|
+
},
|
94
|
+
fontFamily: DEFAULT_FONT_FAMILY,
|
95
|
+
// button 默认使用粗体
|
96
|
+
button: {
|
97
|
+
fontWeight: 700,
|
129
98
|
},
|
130
|
-
|
131
|
-
),
|
99
|
+
},
|
132
100
|
components: {
|
133
101
|
MuiButton: {
|
134
102
|
styleOverrides: {
|
@@ -172,13 +140,45 @@ export const create = ({
|
|
172
140
|
},
|
173
141
|
},
|
174
142
|
},
|
143
|
+
},
|
144
|
+
};
|
145
|
+
// 深色主题
|
146
|
+
if (mode === 'dark') {
|
147
|
+
result.palette = {
|
148
|
+
...muiDarkTheme.palette,
|
149
|
+
background: {
|
150
|
+
paper: colors.grey[900],
|
151
|
+
default: colors.grey[900],
|
152
|
+
},
|
153
|
+
};
|
154
|
+
}
|
155
|
+
|
156
|
+
return result;
|
157
|
+
}
|
158
|
+
|
159
|
+
// https://material-ui.com/customization/default-theme/
|
160
|
+
export const create = ({
|
161
|
+
mode = 'light',
|
162
|
+
pageWidth = 'md',
|
163
|
+
overrides,
|
164
|
+
// original theme options
|
165
|
+
palette,
|
166
|
+
components,
|
167
|
+
...rest
|
168
|
+
}: ThemeOptions = {}) => {
|
169
|
+
const userThemeOptions: ThemeOptions = {
|
170
|
+
themeName: 'ArcBlock',
|
171
|
+
palette: {
|
172
|
+
...palette,
|
173
|
+
mode,
|
174
|
+
},
|
175
|
+
components: {
|
175
176
|
...overrides,
|
176
177
|
...components,
|
177
178
|
},
|
179
|
+
// @TODO 考虑使用 theme.shape.pageWidth
|
178
180
|
pageWidth,
|
179
|
-
|
180
|
-
* @deprecated 应使用 theme.palette 中的颜色
|
181
|
-
*/
|
181
|
+
// @TODO 考虑使用 theme.palette.common
|
182
182
|
colors: {
|
183
183
|
white: '#FFFFFF',
|
184
184
|
dark: '#4A707C',
|
@@ -199,10 +199,33 @@ export const create = ({
|
|
199
199
|
danger: '#D0021B',
|
200
200
|
lightGrey: '#BCBCBC',
|
201
201
|
},
|
202
|
+
// @deprecated use theme.palette.mode
|
202
203
|
mode,
|
203
204
|
...rest,
|
204
|
-
}
|
205
|
+
};
|
206
|
+
// Blocklet Server 后台配置的全局主题
|
207
|
+
const blockletThemeOptions = window.blocklet?.theme?.[mode] ?? {};
|
208
|
+
// choose mode
|
209
|
+
const defaultThemeOptions = createDefaultThemeOptions(mode);
|
210
|
+
// 同官方合并行为
|
211
|
+
const mergedThemeOptions = deepmerge(
|
212
|
+
deepmerge(defaultThemeOptions, cleanedObj(blockletThemeOptions)),
|
213
|
+
cleanedObj(userThemeOptions)
|
214
|
+
);
|
215
|
+
|
216
|
+
const theme = _createTheme(mergedThemeOptions);
|
205
217
|
|
218
|
+
/**
|
219
|
+
* 响应式字体,配置后,theme.typography 会变为下面的结构
|
220
|
+
* {
|
221
|
+
* "h1": {
|
222
|
+
* "fontSize": "3rem",
|
223
|
+
* "@media (min-width:600px)": {
|
224
|
+
* "fontSize": "3.3125rem"
|
225
|
+
* }
|
226
|
+
* }
|
227
|
+
* }
|
228
|
+
*/
|
206
229
|
const enhanced = responsiveFontSizes(theme, {
|
207
230
|
breakpoints: ['xs', 'sm', 'md', 'lg'],
|
208
231
|
disableAlign: false,
|
package/src/Util/index.ts
CHANGED
@@ -3,6 +3,7 @@ import { lazy } from 'react';
|
|
3
3
|
import padStart from 'lodash/padStart';
|
4
4
|
import { getDIDMotifInfo, colors } from '@arcblock/did-motif';
|
5
5
|
import isNil from 'lodash/isNil';
|
6
|
+
import omitBy from 'lodash/omitBy';
|
6
7
|
import pRetry from 'p-retry';
|
7
8
|
import { DID_PREFIX, BLOCKLET_SERVICE_PATH_PREFIX } from './constant';
|
8
9
|
import type { $TSFixMe, Locale } from '../type';
|
@@ -480,3 +481,7 @@ export const lazyRetry = (fn: () => Promise<any>) =>
|
|
480
481
|
{ retries: 2 }
|
481
482
|
)
|
482
483
|
);
|
484
|
+
|
485
|
+
export const cleanedObj = (obj: object) => {
|
486
|
+
return omitBy(obj, isNil);
|
487
|
+
};
|
package/src/type.d.ts
CHANGED
@@ -4,6 +4,7 @@ import type { LiteralUnion } from 'type-fest';
|
|
4
4
|
export type $TSFixMe = any;
|
5
5
|
export type Translations = Record<string, Record<string, any>>;
|
6
6
|
export type Locale = LiteralUnion<'en' | 'zh', string>;
|
7
|
+
export type ThemeMode = 'light' | 'dark';
|
7
8
|
|
8
9
|
// TODO: 以下为 blocklet 应用专属的全局对象类型,可以更加具体
|
9
10
|
export type User = Record<string, any>;
|
@@ -25,7 +26,7 @@ export type Blocklet = {
|
|
25
26
|
version: string;
|
26
27
|
mode: string;
|
27
28
|
tenantMode: 'single' | 'multiple';
|
28
|
-
theme: Theme
|
29
|
+
theme: Record<ThemeMode, Theme>;
|
29
30
|
navigation: $TSFixMe[];
|
30
31
|
preferences: Record<string, any>;
|
31
32
|
languages: {
|
package/src/withTheme/index.tsx
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
import { useEffect } from 'react';
|
2
2
|
import { Global, css } from '@emotion/react';
|
3
3
|
import CssBaseline from '@mui/material/CssBaseline';
|
4
|
+
import { Breakpoint } from '@mui/material';
|
4
5
|
import { type PaletteOptions } from '@mui/material/styles/createPalette';
|
5
6
|
import { type TypographyOptions } from '@mui/material/styles/createTypography';
|
6
7
|
|
7
8
|
import { createTheme, ThemeProvider } from '../Theme';
|
9
|
+
import { ThemeMode } from '../type';
|
8
10
|
|
9
11
|
function withTheme<P extends object>(
|
10
12
|
Component: React.ComponentType<P>,
|
@@ -13,7 +15,7 @@ function withTheme<P extends object>(
|
|
13
15
|
pageWidth = 'md',
|
14
16
|
palette,
|
15
17
|
typography,
|
16
|
-
}: { mode?:
|
18
|
+
}: { mode?: ThemeMode; pageWidth?: Breakpoint; palette?: PaletteOptions; typography?: TypographyOptions } = {}
|
17
19
|
) {
|
18
20
|
const theme = createTheme({ mode, pageWidth, palette, typography });
|
19
21
|
|