@arcblock/ux 2.13.6 → 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.
- package/lib/Colors/index.d.ts +3 -1
- package/lib/Colors/index.js +4 -2
- package/lib/Config/config-provider.d.ts +7 -7
- package/lib/Config/config-provider.js +1 -1
- package/lib/Theme/theme.d.ts +7 -41
- package/lib/Theme/theme.js +50 -132
- package/lib/type.d.ts +2 -3
- package/lib/withTheme/index.d.ts +2 -3
- package/package.json +6 -5
- package/src/Colors/index.ts +7 -2
- package/src/Config/config-provider.tsx +9 -9
- package/src/Theme/theme.ts +55 -166
- package/src/type.d.ts +2 -3
- package/src/withTheme/index.tsx +2 -3
package/lib/Colors/index.d.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
-
|
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';
|
package/lib/Colors/index.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
2
|
-
|
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:
|
7
|
+
mode: PaletteMode;
|
8
8
|
themeOptions: ThemeOptions;
|
9
9
|
toggleMode: () => void;
|
10
10
|
}
|
11
|
-
export declare function isThemeRecord(theme: ThemeOptions | Record<
|
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?:
|
15
|
-
theme?: ThemeOptions | Record<
|
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:
|
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
|
37
|
+
theme: import("@mui/material").Theme;
|
38
38
|
};
|
package/lib/Theme/theme.d.ts
CHANGED
@@ -1,54 +1,20 @@
|
|
1
|
-
import {
|
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?:
|
48
|
-
export
|
14
|
+
export declare function createDefaultThemeOptions(mode?: PaletteMode): ThemeOptions;
|
15
|
+
export interface UserThemeOptions extends ThemeOptions {
|
49
16
|
disableBlockletTheme?: boolean;
|
50
|
-
}
|
51
|
-
export declare const
|
52
|
-
|
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 };
|
package/lib/Theme/theme.js
CHANGED
@@ -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
|
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
|
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
|
-
|
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
|
69
|
+
return BLOCKLET_THEME_LIGHT;
|
159
70
|
}
|
160
|
-
|
161
|
-
|
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
|
-
|
173
|
-
|
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
|
-
|
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
|
-
*
|
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<
|
28
|
+
theme: Record<PaletteMode, Theme>;
|
30
29
|
navigation: $TSFixMe[];
|
31
30
|
preferences: Record<string, any>;
|
32
31
|
languages: {
|
package/lib/withTheme/index.d.ts
CHANGED
@@ -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?:
|
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.
|
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": "
|
73
|
+
"gitHead": "9db5da4c6bc8ec9bd239bcd6d080930b52601bd2",
|
74
74
|
"dependencies": {
|
75
75
|
"@arcblock/did-motif": "^1.1.13",
|
76
|
-
"@arcblock/icons": "^2.13.
|
77
|
-
"@arcblock/nft-display": "^2.13.
|
78
|
-
"@arcblock/react-hooks": "^2.13.
|
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",
|
package/src/Colors/index.ts
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
2
|
-
|
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:
|
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<
|
22
|
-
): theme is Record<
|
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?:
|
31
|
-
theme?: ThemeOptions | Record<
|
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<
|
54
|
+
const [mode, setMode] = useState<PaletteMode>(() => {
|
55
55
|
if (prefer) {
|
56
56
|
return prefer;
|
57
57
|
}
|
58
58
|
|
59
59
|
// 未启用暗色主题
|
60
|
-
if (
|
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
|
65
|
+
const localPrefer = localStorage.getItem(preferThemeModeKey) as PaletteMode;
|
66
66
|
if (localPrefer && (localPrefer === 'light' || localPrefer === 'dark')) {
|
67
67
|
return localPrefer;
|
68
68
|
}
|
package/src/Theme/theme.ts
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
/* eslint-disable no-shadow */
|
2
2
|
// https://app.zeplin.io/styleguide/5d1436f1e97c2156f49c0725/colors
|
3
|
-
import {
|
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
|
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:
|
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
|
-
|
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
|
80
|
+
return BLOCKLET_THEME_LIGHT;
|
199
81
|
}
|
200
82
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
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
|
-
|
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
|
-
*
|
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<
|
28
|
+
theme: Record<PaletteMode, Theme>;
|
30
29
|
navigation: $TSFixMe[];
|
31
30
|
preferences: Record<string, any>;
|
32
31
|
languages: {
|
package/src/withTheme/index.tsx
CHANGED
@@ -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?:
|
17
|
+
}: { mode?: PaletteMode; pageWidth?: Breakpoint; palette?: PaletteOptions; typography?: TypographyOptions } = {}
|
19
18
|
) {
|
20
19
|
const theme = createTheme({ mode, pageWidth, palette, typography });
|
21
20
|
|