@arcblock/ux 2.13.5 → 2.13.7

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.
@@ -1,3 +1,5 @@
1
- export { default } from './themes/default';
1
+ import type { Theme } from '@mui/material';
2
+ declare const colors: Theme["palette"];
3
+ export default colors;
2
4
  export { default as temp } from './themes/temp';
3
5
  export { default as didConnectColors } from './themes/did-connect';
@@ -1,4 +1,6 @@
1
- // eslint-disable-next-line no-restricted-exports
2
- export { default } from './themes/default';
1
+ import { BLOCKLET_THEME_LIGHT } from '@blocklet/theme';
2
+ // @compatibility
3
+ const colors = BLOCKLET_THEME_LIGHT.palette;
4
+ export default colors;
3
5
  export { default as temp } from './themes/temp';
4
6
  export { default as didConnectColors } from './themes/did-connect';
@@ -1,18 +1,18 @@
1
1
  import { ReactNode } from 'react';
2
+ import { type PaletteMode } from '@mui/material';
2
3
  import type { ThemeOptions } from '@mui/material/styles';
3
4
  import { LocaleProviderProps } from '../Locale/context';
4
5
  import { ThemeProviderProps } from '../Theme/theme-provider';
5
- import { ThemeMode } from '../type';
6
6
  export interface ConfigContextType {
7
- mode: ThemeMode;
7
+ mode: PaletteMode;
8
8
  themeOptions: ThemeOptions;
9
9
  toggleMode: () => void;
10
10
  }
11
- export declare function isThemeRecord(theme: ThemeOptions | Record<ThemeMode, ThemeOptions>): theme is Record<ThemeMode, ThemeOptions>;
11
+ export declare function isThemeRecord(theme: ThemeOptions | Record<PaletteMode, ThemeOptions>): theme is Record<PaletteMode, ThemeOptions>;
12
12
  export interface ConfigProviderProps extends Omit<LocaleProviderProps, 'translations'>, Omit<ThemeProviderProps, 'theme'> {
13
13
  children: ReactNode;
14
- prefer?: ThemeMode;
15
- theme?: ThemeOptions | Record<ThemeMode, ThemeOptions>;
14
+ prefer?: PaletteMode;
15
+ theme?: ThemeOptions | Record<PaletteMode, ThemeOptions>;
16
16
  disableBlockletTheme?: boolean;
17
17
  translations?: Record<string, any>;
18
18
  }
@@ -24,7 +24,7 @@ export declare namespace ConfigProvider {
24
24
  var useConfig: typeof import("./config-provider").useConfig;
25
25
  }
26
26
  export declare function useConfig(): {
27
- mode: ThemeMode;
27
+ mode: PaletteMode;
28
28
  themeOptions: ThemeOptions;
29
29
  toggleMode: () => void;
30
30
  locale: import("../type").Locale;
@@ -34,5 +34,5 @@ export declare function useConfig(): {
34
34
  code: string;
35
35
  name: string;
36
36
  }[];
37
- theme: import("@mui/material/styles").Theme;
37
+ theme: import("@mui/material").Theme;
38
38
  };
@@ -35,7 +35,7 @@ export function ConfigProvider({
35
35
  }
36
36
 
37
37
  // 未启用暗色主题
38
- if (!window.blocklet?.USE_DARK_THEME) {
38
+ if (['1', 'true'].includes(window.blocklet?.USE_DARK_THEME) === false) {
39
39
  return 'light';
40
40
  }
41
41
 
@@ -1,54 +1,20 @@
1
- import { Components, type ThemeOptions } from '@mui/material/styles';
1
+ import type { PaletteMode } from '@mui/material';
2
+ import { type ThemeOptions } from '@mui/material/styles';
2
3
  import { deepmerge } from '@mui/utils';
3
- import type { Typography } from '@mui/material/styles/createTypography';
4
- import { ThemeMode } from '../type';
5
4
  import '@fontsource/roboto/latin-400.css';
6
5
  import '@fontsource/roboto/latin-500.css';
7
6
  import '@fontsource/roboto/latin-700.css';
8
7
  import '@fontsource/roboto/latin-ext-400.css';
9
8
  import '@fontsource/roboto/latin-ext-500.css';
10
9
  import '@fontsource/roboto/latin-ext-700.css';
11
- declare module '@mui/material/styles' {
12
- interface Theme {
13
- mode?: ThemeMode;
14
- themeName?: string;
15
- pageWidth?: string;
16
- colors?: Record<string, string>;
17
- typography: Typography & {
18
- useNextVariants: boolean;
19
- color: Record<string, string>;
20
- button: {
21
- fontWeight?: number;
22
- };
23
- };
24
- }
25
- interface ThemeOptions {
26
- themeName?: string;
27
- mode?: ThemeMode;
28
- pageWidth?: string;
29
- colors?: Record<string, string>;
30
- /** @deprecated 请使用 components */
31
- overrides?: Components<Omit<Theme, 'components'>>;
32
- }
33
- interface TypeText {
34
- hint: string;
35
- }
36
- }
37
- declare module '@mui/material/styles/createTypography' {
38
- interface TypographyOptions {
39
- useNextVariants?: boolean;
40
- color?: Record<string, string>;
41
- }
42
- }
43
10
  export declare function collectFontFamilies(obj?: {
44
11
  fontFamily?: string;
45
12
  }, fontSet?: Set<string>): Set<string>;
46
13
  export declare function loadFonts(fonts: string[]): Promise<boolean>;
47
- export declare function createDefaultThemeOptions(mode?: ThemeMode): ThemeOptions;
48
- export declare const create: ({ disableBlockletTheme, mode, pageWidth, overrides, palette, components, ...rest }?: ThemeOptions & {
14
+ export declare function createDefaultThemeOptions(mode?: PaletteMode): ThemeOptions;
15
+ export interface UserThemeOptions extends ThemeOptions {
49
16
  disableBlockletTheme?: boolean;
50
- }) => import("@mui/material/styles").Theme;
51
- export declare const createTheme: ({ disableBlockletTheme, mode, pageWidth, overrides, palette, components, ...rest }?: ThemeOptions & {
52
- disableBlockletTheme?: boolean;
53
- }) => import("@mui/material/styles").Theme;
17
+ }
18
+ export declare const create: (...args: UserThemeOptions[]) => import("@mui/material").Theme;
19
+ export declare const createTheme: (...args: UserThemeOptions[]) => import("@mui/material").Theme;
54
20
  export { deepmerge };
@@ -1,9 +1,10 @@
1
1
  /* eslint-disable no-shadow */
2
2
  // https://app.zeplin.io/styleguide/5d1436f1e97c2156f49c0725/colors
3
+
3
4
  import { createTheme as _createTheme, responsiveFontSizes } from '@mui/material/styles';
4
5
  import { deepmerge } from '@mui/utils';
5
6
  import webfontloader from 'webfontloader';
6
- import colors from '../Colors';
7
+ import { BLOCKLET_THEME_LIGHT, BLOCKLET_THEME_DARK, DEFAULT_FONTS } from '@blocklet/theme';
7
8
  import { cleanedObj } from '../Util';
8
9
 
9
10
  // 默认只加载最基本的 roboto latin 字体
@@ -14,17 +15,6 @@ import '@fontsource/roboto/latin-ext-400.css';
14
15
  import '@fontsource/roboto/latin-ext-500.css';
15
16
  import '@fontsource/roboto/latin-ext-700.css';
16
17
 
17
- // 扩展 Theme
18
-
19
- // 扩展 TypographyOptions
20
-
21
- // 默认深色主题
22
- const defaultDarkTheme = _createTheme({
23
- palette: {
24
- mode: 'dark'
25
- }
26
- });
27
-
28
18
  // 收集字体配置
29
19
  export function collectFontFamilies(obj, fontSet = new Set()) {
30
20
  if (!obj || typeof obj !== 'object') return fontSet;
@@ -40,8 +30,7 @@ export function collectFontFamilies(obj, fontSet = new Set()) {
40
30
  }
41
31
 
42
32
  // 动态加载字体
43
- const defaultFonts = ['Roboto', 'Helvetica', 'Arial', 'sans-serif']; // 后三者是系统字体,无需动态加载
44
- const prevFonts = new Set(defaultFonts.concat('inherit')); // inherit 属于 MUI 特殊值,无需动态加载
33
+ const prevFonts = new Set(DEFAULT_FONTS.concat('inherit')); // inherit 属于 MUI 特殊值,无需动态加载
45
34
  export function loadFonts(fonts) {
46
35
  // 过滤出未加载的字体
47
36
  const unloadedFonts = fonts.filter(font => !prevFonts.has(font));
@@ -74,103 +63,21 @@ export function loadFonts(fonts) {
74
63
 
75
64
  // 创建默认主题配置
76
65
  export function createDefaultThemeOptions(mode = 'light') {
77
- const result = {
78
- palette: {
79
- mode,
80
- ...colors,
81
- background: {
82
- paper: colors.common.white,
83
- default: colors.background.default
84
- }
85
- },
86
- typography: {
87
- fontFamily: defaultFonts.join(','),
88
- useNextVariants: true,
89
- color: {
90
- // 此处 #222222 必须硬编码, layout/sidebar.js -> Icon/image 加载图片时 color 会影响加载路径
91
- // TODO: 此处硬编码的色值后面需要改为 colors.grey[900],
92
- // 或者如果可以的话直接删掉 typography#color, 文本颜色建议使用 theme.palette.text 中的色值?
93
- // layout 组件建议重构, sidebar 中建议使用 icon 替换 img (#366)
94
- main: mode === 'light' ? '#222222' : colors.common.white,
95
- gray: mode === 'light' ? colors.grey[500] : colors.grey[300]
96
- },
97
- // button 默认使用粗体
98
- button: {
99
- fontWeight: 700
100
- }
101
- },
102
- components: {
103
- MuiButton: {
104
- styleOverrides: {
105
- root: {
106
- boxShadow: 'none'
107
- }
108
- }
109
- },
110
- MuiButtonGroup: {
111
- styleOverrides: {
112
- root: {
113
- boxShadow: 'none'
114
- }
115
- }
116
- },
117
- MuiTableCell: {
118
- styleOverrides: {
119
- root: ({
120
- ownerState
121
- }) => ({
122
- ...(ownerState.size === 'small' ? {
123
- borderBottomWidth: '0',
124
- paddingTop: '8px',
125
- paddingBottom: '8px',
126
- paddingLeft: 0,
127
- paddingRight: '20px'
128
- } : {
129
- borderBottomWidth: '0',
130
- paddingTop: '14px',
131
- paddingBottom: '14px',
132
- paddingLeft: 0,
133
- paddingRight: '30px'
134
- })
135
- }),
136
- head: {
137
- textTransform: 'uppercase',
138
- color: mode === 'light' ? colors.grey[900] : colors.grey[300]
139
- },
140
- body: {
141
- color: mode === 'light' ? colors.grey[900] : colors.grey[300]
142
- }
143
- }
144
- }
145
- }
146
- };
147
-
148
- // 深色主题
149
66
  if (mode === 'dark') {
150
- result.palette = {
151
- ...defaultDarkTheme.palette,
152
- background: {
153
- paper: colors.grey[900],
154
- default: colors.grey[900]
155
- }
156
- };
67
+ return BLOCKLET_THEME_DARK;
157
68
  }
158
- return result;
69
+ return BLOCKLET_THEME_LIGHT;
159
70
  }
160
-
161
- // https://material-ui.com/customization/default-theme/
162
- export const create = ({
163
- disableBlockletTheme = false,
71
+ // 主要处理 mode 和 overrides
72
+ const normalizeUserThemeOptions = ({
164
73
  mode = 'light',
165
- pageWidth = 'md',
166
- overrides,
167
- // original theme options
168
74
  palette,
169
75
  components,
76
+ overrides,
170
77
  ...rest
171
- } = {}) => {
172
- const userThemeOptions = {
173
- themeName: 'ArcBlock',
78
+ }) => {
79
+ return {
80
+ mode,
174
81
  palette: {
175
82
  ...palette,
176
83
  mode
@@ -179,43 +86,54 @@ export const create = ({
179
86
  ...overrides,
180
87
  ...components
181
88
  },
182
- // @TODO 考虑使用 theme.shape.pageWidth
183
- pageWidth,
184
- // @TODO 考虑使用 theme.palette.common
185
- colors: {
186
- white: '#FFFFFF',
187
- dark: '#4A707C',
188
- gray: '#222222',
189
- minor: '#9B9B9B',
190
- darkText: '#DCDCDC',
191
- background: '#F7F8F8',
192
- yellow: '#FFCF71',
193
- green: '#44cdc6',
194
- red: '#D0021B',
195
- blue: '#4E6AF6',
196
- primary: '#222222',
197
- black: '#222222',
198
- secondary: '#44cdc6',
199
- mint: '#44cdc6',
200
- textSecondary: '#4A4A4A',
201
- active: '#5b9025',
202
- danger: '#D0021B',
203
- lightGrey: '#BCBCBC'
204
- },
205
- // @deprecated use theme.palette.mode
206
- mode,
207
89
  ...rest
208
90
  };
209
- // Blocklet Server 后台配置的全局主题
91
+ };
92
+ const defaultUserThemeOptions = {
93
+ themeName: 'ArcBlock',
94
+ pageWidth: 'md',
95
+ disableBlockletTheme: false,
96
+ // @deprecated use theme.palette
97
+ colors: {
98
+ white: '#FFFFFF',
99
+ dark: '#4A707C',
100
+ gray: '#222222',
101
+ minor: '#9B9B9B',
102
+ darkText: '#DCDCDC',
103
+ background: '#F7F8F8',
104
+ yellow: '#FFCF71',
105
+ green: '#44cdc6',
106
+ red: '#D0021B',
107
+ blue: '#4E6AF6',
108
+ primary: '#222222',
109
+ black: '#222222',
110
+ secondary: '#44cdc6',
111
+ mint: '#44cdc6',
112
+ textSecondary: '#4A4A4A',
113
+ active: '#5b9025',
114
+ danger: '#D0021B',
115
+ lightGrey: '#BCBCBC'
116
+ }
117
+ };
118
+
119
+ // https://material-ui.com/customization/default-theme/
120
+ export const create = (...args) => {
121
+ const userThemeOptions = args.reduce((acc, curr) => deepmerge(acc, normalizeUserThemeOptions(curr)), normalizeUserThemeOptions(defaultUserThemeOptions));
122
+ const {
123
+ mode,
124
+ disableBlockletTheme
125
+ } = userThemeOptions;
210
126
  const blockletThemeOptions = window.blocklet?.theme?.[mode] ?? {};
211
- // UX Theme 默认配置
212
127
  const defaultThemeOptions = createDefaultThemeOptions(mode);
128
+
213
129
  // 合并配置
214
130
  let mergedThemeOptions = defaultThemeOptions;
215
131
  if (!disableBlockletTheme) {
216
132
  mergedThemeOptions = deepmerge(defaultThemeOptions, cleanedObj(blockletThemeOptions));
217
133
  }
218
134
  mergedThemeOptions = deepmerge(mergedThemeOptions, cleanedObj(userThemeOptions));
135
+
136
+ // 创建主题
219
137
  const theme = _createTheme(mergedThemeOptions);
220
138
 
221
139
  // 异步加载字体
@@ -223,7 +141,7 @@ export const create = ({
223
141
  loadFonts(Array.from(fonts));
224
142
 
225
143
  /**
226
- * 响应式字体,配置后,theme.typography 会变为下面的结构
144
+ * 支持响应式字体,theme.typography.$variant 中会添加 @media 分支,比如
227
145
  * {
228
146
  * "h1": {
229
147
  * "fontSize": "3rem",
package/lib/type.d.ts CHANGED
@@ -1,10 +1,9 @@
1
- import type { Theme } from '@mui/material';
1
+ import type { Theme, PaletteMode } from '@mui/material';
2
2
  import type { LiteralUnion } from 'type-fest';
3
3
 
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';
8
7
 
9
8
  // TODO: 以下为 blocklet 应用专属的全局对象类型,可以更加具体
10
9
  export type User = Record<string, any>;
@@ -26,7 +25,7 @@ export type Blocklet = {
26
25
  version: string;
27
26
  mode: string;
28
27
  tenantMode: 'single' | 'multiple';
29
- theme: Record<ThemeMode, Theme>;
28
+ theme: Record<PaletteMode, Theme>;
30
29
  navigation: $TSFixMe[];
31
30
  preferences: Record<string, any>;
32
31
  languages: {
@@ -1,9 +1,8 @@
1
- import { Breakpoint } from '@mui/material';
1
+ import { Breakpoint, type PaletteMode } from '@mui/material';
2
2
  import { type PaletteOptions } from '@mui/material/styles/createPalette';
3
3
  import { type TypographyOptions } from '@mui/material/styles/createTypography';
4
- import { ThemeMode } from '../type';
5
4
  declare function withTheme<P extends object>(Component: React.ComponentType<P>, { mode, pageWidth, palette, typography, }?: {
6
- mode?: ThemeMode;
5
+ mode?: PaletteMode;
7
6
  pageWidth?: Breakpoint;
8
7
  palette?: PaletteOptions;
9
8
  typography?: TypographyOptions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/ux",
3
- "version": "2.13.5",
3
+ "version": "2.13.7",
4
4
  "description": "Common used react components for arcblock products",
5
5
  "keywords": [
6
6
  "react",
@@ -70,13 +70,14 @@
70
70
  "react": ">=18.2.0",
71
71
  "react-router-dom": ">=6.22.3"
72
72
  },
73
- "gitHead": "87e3a4b58baa0ebfd7d4ddb7c367b77eb170f679",
73
+ "gitHead": "9db5da4c6bc8ec9bd239bcd6d080930b52601bd2",
74
74
  "dependencies": {
75
75
  "@arcblock/did-motif": "^1.1.13",
76
- "@arcblock/icons": "^2.13.5",
77
- "@arcblock/nft-display": "^2.13.5",
78
- "@arcblock/react-hooks": "^2.13.5",
76
+ "@arcblock/icons": "^2.13.7",
77
+ "@arcblock/nft-display": "^2.13.7",
78
+ "@arcblock/react-hooks": "^2.13.7",
79
79
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
80
+ "@blocklet/theme": "^2.13.7",
80
81
  "@fontsource/roboto": "~5.1.1",
81
82
  "@fontsource/ubuntu-mono": "^5.0.18",
82
83
  "@iconify-icons/logos": "^1.2.36",
@@ -1,4 +1,9 @@
1
- // eslint-disable-next-line no-restricted-exports
2
- export { default } from './themes/default';
1
+ import { BLOCKLET_THEME_LIGHT } from '@blocklet/theme';
2
+ import type { Theme } from '@mui/material';
3
+
4
+ // @compatibility
5
+ const colors = BLOCKLET_THEME_LIGHT.palette as Theme['palette'];
6
+
7
+ export default colors;
3
8
  export { default as temp } from './themes/temp';
4
9
  export { default as didConnectColors } from './themes/did-connect';
@@ -1,4 +1,5 @@
1
1
  import { createContext, useContext, ReactNode, useMemo, useState, useCallback, useEffect } from 'react';
2
+ import { type PaletteMode } from '@mui/material';
2
3
  import type { ThemeOptions } from '@mui/material/styles';
3
4
  import useMediaQuery from '@mui/material/useMediaQuery';
4
5
  import set from 'lodash/set';
@@ -6,10 +7,9 @@ import { ThemeProvider as EmotionThemeProvider } from '@emotion/react';
6
7
  import { LocaleProvider, LocaleProviderProps, useLocaleContext } from '../Locale/context';
7
8
  import ThemeProvider, { ThemeProviderProps } from '../Theme/theme-provider';
8
9
  import { createTheme, useTheme } from '../Theme';
9
- import { ThemeMode } from '../type';
10
10
 
11
11
  export interface ConfigContextType {
12
- mode: ThemeMode;
12
+ mode: PaletteMode;
13
13
  themeOptions: ThemeOptions;
14
14
  toggleMode: () => void;
15
15
  }
@@ -18,8 +18,8 @@ const ConfigContext = createContext<ConfigContextType>({} as ConfigContextType);
18
18
  const preferThemeModeKey = 'blocklet_theme_prefer';
19
19
 
20
20
  export function isThemeRecord(
21
- theme: ThemeOptions | Record<ThemeMode, ThemeOptions>
22
- ): theme is Record<ThemeMode, ThemeOptions> {
21
+ theme: ThemeOptions | Record<PaletteMode, ThemeOptions>
22
+ ): theme is Record<PaletteMode, ThemeOptions> {
23
23
  return 'light' in theme || 'dark' in theme;
24
24
  }
25
25
 
@@ -27,8 +27,8 @@ export interface ConfigProviderProps
27
27
  extends Omit<LocaleProviderProps, 'translations'>,
28
28
  Omit<ThemeProviderProps, 'theme'> {
29
29
  children: ReactNode;
30
- prefer?: ThemeMode;
31
- theme?: ThemeOptions | Record<ThemeMode, ThemeOptions>;
30
+ prefer?: PaletteMode;
31
+ theme?: ThemeOptions | Record<PaletteMode, ThemeOptions>;
32
32
  disableBlockletTheme?: boolean;
33
33
  translations?: Record<string, any>;
34
34
  }
@@ -51,18 +51,18 @@ export function ConfigProvider({
51
51
  onLoadingTranslation,
52
52
  }: ConfigProviderProps) {
53
53
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
54
- const [mode, setMode] = useState<ThemeMode>(() => {
54
+ const [mode, setMode] = useState<PaletteMode>(() => {
55
55
  if (prefer) {
56
56
  return prefer;
57
57
  }
58
58
 
59
59
  // 未启用暗色主题
60
- if (!window.blocklet?.USE_DARK_THEME) {
60
+ if (['1', 'true'].includes(window.blocklet?.USE_DARK_THEME) === false) {
61
61
  return 'light';
62
62
  }
63
63
 
64
64
  // 本地缓存
65
- const localPrefer = localStorage.getItem(preferThemeModeKey) as ThemeMode;
65
+ const localPrefer = localStorage.getItem(preferThemeModeKey) as PaletteMode;
66
66
  if (localPrefer && (localPrefer === 'light' || localPrefer === 'dark')) {
67
67
  return localPrefer;
68
68
  }
@@ -1,12 +1,11 @@
1
1
  /* eslint-disable no-shadow */
2
2
  // https://app.zeplin.io/styleguide/5d1436f1e97c2156f49c0725/colors
3
- import { createTheme as _createTheme, Components, responsiveFontSizes, type ThemeOptions } from '@mui/material/styles';
3
+ import type { PaletteMode } from '@mui/material';
4
+ import { createTheme as _createTheme, responsiveFontSizes, type ThemeOptions } from '@mui/material/styles';
4
5
  import { deepmerge } from '@mui/utils';
5
- import type { Typography } from '@mui/material/styles/createTypography';
6
6
  import webfontloader from 'webfontloader';
7
+ import { BLOCKLET_THEME_LIGHT, BLOCKLET_THEME_DARK, DEFAULT_FONTS } from '@blocklet/theme';
7
8
 
8
- import colors from '../Colors';
9
- import { ThemeMode } from '../type';
10
9
  import { cleanedObj } from '../Util';
11
10
 
12
11
  // 默认只加载最基本的 roboto latin 字体
@@ -17,44 +16,6 @@ import '@fontsource/roboto/latin-ext-400.css';
17
16
  import '@fontsource/roboto/latin-ext-500.css';
18
17
  import '@fontsource/roboto/latin-ext-700.css';
19
18
 
20
- // 扩展 Theme
21
- declare module '@mui/material/styles' {
22
- interface Theme {
23
- mode?: ThemeMode;
24
- themeName?: string;
25
- pageWidth?: string;
26
- colors?: Record<string, string>;
27
- typography: Typography & {
28
- useNextVariants: boolean;
29
- color: Record<string, string>;
30
- button: {
31
- fontWeight?: number;
32
- };
33
- };
34
- }
35
- interface ThemeOptions {
36
- themeName?: string;
37
- mode?: ThemeMode;
38
- pageWidth?: string;
39
- colors?: Record<string, string>;
40
- /** @deprecated 请使用 components */
41
- overrides?: Components<Omit<Theme, 'components'>>;
42
- }
43
- interface TypeText {
44
- hint: string;
45
- }
46
- }
47
- // 扩展 TypographyOptions
48
- declare module '@mui/material/styles/createTypography' {
49
- interface TypographyOptions {
50
- useNextVariants?: boolean;
51
- color?: Record<string, string>;
52
- }
53
- }
54
-
55
- // 默认深色主题
56
- const defaultDarkTheme = _createTheme({ palette: { mode: 'dark' } });
57
-
58
19
  // 收集字体配置
59
20
  export function collectFontFamilies(obj?: { fontFamily?: string }, fontSet: Set<string> = new Set()): Set<string> {
60
21
  if (!obj || typeof obj !== 'object') return fontSet;
@@ -78,8 +39,7 @@ export function collectFontFamilies(obj?: { fontFamily?: string }, fontSet: Set<
78
39
  }
79
40
 
80
41
  // 动态加载字体
81
- const defaultFonts = ['Roboto', 'Helvetica', 'Arial', 'sans-serif']; // 后三者是系统字体,无需动态加载
82
- const prevFonts = new Set<string>(defaultFonts.concat('inherit')); // inherit 属于 MUI 特殊值,无需动态加载
42
+ const prevFonts = new Set<string>(DEFAULT_FONTS.concat('inherit')); // inherit 属于 MUI 特殊值,无需动态加载
83
43
  export function loadFonts(fonts: string[]) {
84
44
  // 过滤出未加载的字体
85
45
  const unloadedFonts = fonts.filter((font) => !prevFonts.has(font));
@@ -112,105 +72,22 @@ export function loadFonts(fonts: string[]) {
112
72
  }
113
73
 
114
74
  // 创建默认主题配置
115
- export function createDefaultThemeOptions(mode: ThemeMode = 'light'): ThemeOptions {
116
- const result: ThemeOptions = {
117
- palette: {
118
- mode,
119
- ...colors,
120
- background: {
121
- paper: colors.common.white,
122
- default: colors.background.default,
123
- },
124
- },
125
- typography: {
126
- fontFamily: defaultFonts.join(','),
127
- useNextVariants: true,
128
- color: {
129
- // 此处 #222222 必须硬编码, layout/sidebar.js -> Icon/image 加载图片时 color 会影响加载路径
130
- // TODO: 此处硬编码的色值后面需要改为 colors.grey[900],
131
- // 或者如果可以的话直接删掉 typography#color, 文本颜色建议使用 theme.palette.text 中的色值?
132
- // layout 组件建议重构, sidebar 中建议使用 icon 替换 img (#366)
133
- main: mode === 'light' ? '#222222' : colors.common.white,
134
- gray: mode === 'light' ? colors.grey[500] : colors.grey[300],
135
- },
136
- // button 默认使用粗体
137
- button: {
138
- fontWeight: 700,
139
- },
140
- },
141
- components: {
142
- MuiButton: {
143
- styleOverrides: {
144
- root: {
145
- boxShadow: 'none',
146
- },
147
- },
148
- },
149
- MuiButtonGroup: {
150
- styleOverrides: {
151
- root: {
152
- boxShadow: 'none',
153
- },
154
- },
155
- },
156
- MuiTableCell: {
157
- styleOverrides: {
158
- root: ({ ownerState }) => ({
159
- ...(ownerState.size === 'small'
160
- ? {
161
- borderBottomWidth: '0',
162
- paddingTop: '8px',
163
- paddingBottom: '8px',
164
- paddingLeft: 0,
165
- paddingRight: '20px',
166
- }
167
- : {
168
- borderBottomWidth: '0',
169
- paddingTop: '14px',
170
- paddingBottom: '14px',
171
- paddingLeft: 0,
172
- paddingRight: '30px',
173
- }),
174
- }),
175
- head: {
176
- textTransform: 'uppercase',
177
- color: mode === 'light' ? colors.grey[900] : colors.grey[300],
178
- },
179
- body: {
180
- color: mode === 'light' ? colors.grey[900] : colors.grey[300],
181
- },
182
- },
183
- },
184
- },
185
- };
186
-
187
- // 深色主题
75
+ export function createDefaultThemeOptions(mode: PaletteMode = 'light') {
188
76
  if (mode === 'dark') {
189
- result.palette = {
190
- ...defaultDarkTheme.palette,
191
- background: {
192
- paper: colors.grey[900],
193
- default: colors.grey[900],
194
- },
195
- };
77
+ return BLOCKLET_THEME_DARK;
196
78
  }
197
79
 
198
- return result;
80
+ return BLOCKLET_THEME_LIGHT;
199
81
  }
200
82
 
201
- // https://material-ui.com/customization/default-theme/
202
- export const create = ({
203
- disableBlockletTheme = false,
204
- mode = 'light',
205
- pageWidth = 'md',
206
- overrides,
207
- // original theme options
208
- palette,
209
- components,
210
- ...rest
211
- }: ThemeOptions & { disableBlockletTheme?: boolean } = {}) => {
212
- const userThemeOptions: ThemeOptions = {
213
- themeName: 'ArcBlock',
83
+ export interface UserThemeOptions extends ThemeOptions {
84
+ disableBlockletTheme?: boolean;
85
+ }
86
+
87
+ // 主要处理 mode 和 overrides
88
+ const normalizeUserThemeOptions = ({ mode = 'light', palette, components, overrides, ...rest }: UserThemeOptions) => {
89
+ return {
90
+ mode,
214
91
  palette: {
215
92
  ...palette,
216
93
  mode,
@@ -219,43 +96,55 @@ export const create = ({
219
96
  ...overrides,
220
97
  ...components,
221
98
  },
222
- // @TODO 考虑使用 theme.shape.pageWidth
223
- pageWidth,
224
- // @TODO 考虑使用 theme.palette.common
225
- colors: {
226
- white: '#FFFFFF',
227
- dark: '#4A707C',
228
- gray: '#222222',
229
- minor: '#9B9B9B',
230
- darkText: '#DCDCDC',
231
- background: '#F7F8F8',
232
- yellow: '#FFCF71',
233
- green: '#44cdc6',
234
- red: '#D0021B',
235
- blue: '#4E6AF6',
236
- primary: '#222222',
237
- black: '#222222',
238
- secondary: '#44cdc6',
239
- mint: '#44cdc6',
240
- textSecondary: '#4A4A4A',
241
- active: '#5b9025',
242
- danger: '#D0021B',
243
- lightGrey: '#BCBCBC',
244
- },
245
- // @deprecated use theme.palette.mode
246
- mode,
247
99
  ...rest,
248
100
  };
249
- // Blocklet Server 后台配置的全局主题
101
+ };
102
+
103
+ const defaultUserThemeOptions: UserThemeOptions = {
104
+ themeName: 'ArcBlock',
105
+ pageWidth: 'md',
106
+ disableBlockletTheme: false,
107
+ // @deprecated use theme.palette
108
+ colors: {
109
+ white: '#FFFFFF',
110
+ dark: '#4A707C',
111
+ gray: '#222222',
112
+ minor: '#9B9B9B',
113
+ darkText: '#DCDCDC',
114
+ background: '#F7F8F8',
115
+ yellow: '#FFCF71',
116
+ green: '#44cdc6',
117
+ red: '#D0021B',
118
+ blue: '#4E6AF6',
119
+ primary: '#222222',
120
+ black: '#222222',
121
+ secondary: '#44cdc6',
122
+ mint: '#44cdc6',
123
+ textSecondary: '#4A4A4A',
124
+ active: '#5b9025',
125
+ danger: '#D0021B',
126
+ lightGrey: '#BCBCBC',
127
+ },
128
+ };
129
+
130
+ // https://material-ui.com/customization/default-theme/
131
+ export const create = (...args: UserThemeOptions[]) => {
132
+ const userThemeOptions = args.reduce(
133
+ (acc, curr) => deepmerge(acc, normalizeUserThemeOptions(curr)),
134
+ normalizeUserThemeOptions(defaultUserThemeOptions)
135
+ );
136
+ const { mode, disableBlockletTheme } = userThemeOptions;
250
137
  const blockletThemeOptions = window.blocklet?.theme?.[mode] ?? {};
251
- // UX Theme 默认配置
252
138
  const defaultThemeOptions = createDefaultThemeOptions(mode);
139
+
253
140
  // 合并配置
254
141
  let mergedThemeOptions = defaultThemeOptions;
255
142
  if (!disableBlockletTheme) {
256
143
  mergedThemeOptions = deepmerge(defaultThemeOptions, cleanedObj(blockletThemeOptions));
257
144
  }
258
145
  mergedThemeOptions = deepmerge(mergedThemeOptions, cleanedObj(userThemeOptions));
146
+
147
+ // 创建主题
259
148
  const theme = _createTheme(mergedThemeOptions);
260
149
 
261
150
  // 异步加载字体
@@ -263,7 +152,7 @@ export const create = ({
263
152
  loadFonts(Array.from(fonts));
264
153
 
265
154
  /**
266
- * 响应式字体,配置后,theme.typography 会变为下面的结构
155
+ * 支持响应式字体,theme.typography.$variant 中会添加 @media 分支,比如
267
156
  * {
268
157
  * "h1": {
269
158
  * "fontSize": "3rem",
package/src/type.d.ts CHANGED
@@ -1,10 +1,9 @@
1
- import type { Theme } from '@mui/material';
1
+ import type { Theme, PaletteMode } from '@mui/material';
2
2
  import type { LiteralUnion } from 'type-fest';
3
3
 
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';
8
7
 
9
8
  // TODO: 以下为 blocklet 应用专属的全局对象类型,可以更加具体
10
9
  export type User = Record<string, any>;
@@ -26,7 +25,7 @@ export type Blocklet = {
26
25
  version: string;
27
26
  mode: string;
28
27
  tenantMode: 'single' | 'multiple';
29
- theme: Record<ThemeMode, Theme>;
28
+ theme: Record<PaletteMode, Theme>;
30
29
  navigation: $TSFixMe[];
31
30
  preferences: Record<string, any>;
32
31
  languages: {
@@ -1,12 +1,11 @@
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
+ import { Breakpoint, type PaletteMode } from '@mui/material';
5
5
  import { type PaletteOptions } from '@mui/material/styles/createPalette';
6
6
  import { type TypographyOptions } from '@mui/material/styles/createTypography';
7
7
 
8
8
  import { createTheme, ThemeProvider } from '../Theme';
9
- import { ThemeMode } from '../type';
10
9
 
11
10
  function withTheme<P extends object>(
12
11
  Component: React.ComponentType<P>,
@@ -15,7 +14,7 @@ function withTheme<P extends object>(
15
14
  pageWidth = 'md',
16
15
  palette,
17
16
  typography,
18
- }: { mode?: ThemeMode; pageWidth?: Breakpoint; palette?: PaletteOptions; typography?: TypographyOptions } = {}
17
+ }: { mode?: PaletteMode; pageWidth?: Breakpoint; palette?: PaletteOptions; typography?: TypographyOptions } = {}
19
18
  ) {
20
19
  const theme = createTheme({ mode, pageWidth, palette, typography });
21
20