@arcblock/ux 2.12.53 → 2.12.55

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,6 +1,12 @@
1
1
  import type { Blocklet } from '../type';
2
- declare const BlockletContext: import("react").Context<Blocklet | null>;
3
- declare const Consumer: import("react").Consumer<Blocklet | null>;
2
+ declare const BlockletContext: import("react").Context<{
3
+ blocklet: Blocklet | null;
4
+ masterBlocklet: Blocklet | null;
5
+ }>;
6
+ declare const Consumer: import("react").Consumer<{
7
+ blocklet: Blocklet | null;
8
+ masterBlocklet: Blocklet | null;
9
+ }>;
4
10
  declare function BlockletProvider({ children, baseUrl, loading, }: {
5
11
  children?: React.ReactNode;
6
12
  /**
@@ -11,5 +17,6 @@ declare function BlockletProvider({ children, baseUrl, loading, }: {
11
17
  }): import("react/jsx-runtime").JSX.Element;
12
18
  declare function useBlockletContext(): {
13
19
  blocklet: Blocklet | null;
20
+ masterBlocklet: Blocklet | null;
14
21
  };
15
22
  export { BlockletContext, BlockletProvider, Consumer as BlockletConsumer, useBlockletContext };
@@ -1,8 +1,11 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useMemoizedFn, useAsyncEffect } from 'ahooks';
3
3
  import { createContext, useContext, useState } from 'react';
4
- import { getBlockletData } from '../Util/federated';
5
- const BlockletContext = /*#__PURE__*/createContext(null);
4
+ import { getBlockletData, getFederatedEnabled, getMaster } from '../Util/federated';
5
+ const BlockletContext = /*#__PURE__*/createContext({
6
+ blocklet: null,
7
+ masterBlocklet: null
8
+ });
6
9
  const {
7
10
  Provider,
8
11
  Consumer
@@ -13,6 +16,7 @@ function BlockletProvider({
13
16
  loading = null
14
17
  }) {
15
18
  const [blockletData, setBlockletData] = useState(null);
19
+ const [masterBlockletData, setMasterBlockletData] = useState(null);
16
20
  const getBlockleDataWithCache = useMemoizedFn(async () => {
17
21
  if (!baseUrl || window.location.href.startsWith(baseUrl)) {
18
22
  throw new Error('no blocklet data');
@@ -21,25 +25,43 @@ function BlockletProvider({
21
25
  return jsonData;
22
26
  });
23
27
  useAsyncEffect(async () => {
28
+ let result = null;
29
+ let resultMaster = null;
24
30
  try {
25
- const data = await getBlockleDataWithCache();
26
- setBlockletData(data);
31
+ result = await getBlockleDataWithCache();
27
32
  } catch {
28
33
  // NOTICE: 如果获取指定 blockletData 失败,则使用 window.blocklet
29
34
  const data = globalThis.blocklet || globalThis.env;
30
- setBlockletData(data);
35
+ result = data;
31
36
  }
37
+ if (result) {
38
+ if (getFederatedEnabled(result)) {
39
+ const masterSite = getMaster(result);
40
+ if (masterSite) {
41
+ resultMaster = await getBlockletData(masterSite.appUrl);
42
+ }
43
+ }
44
+ }
45
+ setBlockletData(result);
46
+ setMasterBlockletData(resultMaster);
32
47
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
48
  }, [baseUrl]);
34
49
  return /*#__PURE__*/_jsx(Provider, {
35
- value: blockletData,
50
+ value: {
51
+ blocklet: blockletData,
52
+ masterBlocklet: masterBlockletData
53
+ },
36
54
  children: blockletData ? children : loading || null
37
55
  });
38
56
  }
39
57
  function useBlockletContext() {
40
- const blocklet = useContext(BlockletContext);
58
+ const {
59
+ blocklet,
60
+ masterBlocklet
61
+ } = useContext(BlockletContext);
41
62
  return {
42
- blocklet
63
+ blocklet,
64
+ masterBlocklet
43
65
  };
44
66
  }
45
67
  export { BlockletContext, BlockletProvider, Consumer as BlockletConsumer, useBlockletContext };
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useMemo, useState, useCallback } from 'react';
2
+ import { createContext, useContext, useMemo, useState, useCallback, useEffect } from 'react';
3
3
  import useMediaQuery from '@mui/material/useMediaQuery';
4
4
  import set from 'lodash/set';
5
5
  import { LocaleProvider, useLocaleContext } from '../Locale/context';
@@ -28,11 +28,14 @@ export function ConfigProvider({
28
28
  }) {
29
29
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
30
30
  const [mode, setMode] = useState(() => {
31
- const preferMode = localStorage.getItem(preferThemeModeKey);
32
- if (preferMode && (preferMode === 'light' || preferMode === 'dark')) {
33
- return preferMode;
31
+ if (prefer) {
32
+ return prefer;
34
33
  }
35
- return prefer || (prefersDarkMode ? 'dark' : 'light');
34
+ const localPrefer = localStorage.getItem(preferThemeModeKey);
35
+ if (localPrefer && (localPrefer === 'light' || localPrefer === 'dark')) {
36
+ return localPrefer;
37
+ }
38
+ return prefersDarkMode ? 'dark' : 'light';
36
39
  });
37
40
  const _themeOptions = useMemo(() => {
38
41
  let result = {};
@@ -64,6 +67,13 @@ export function ConfigProvider({
64
67
  themeOptions: _themeOptions,
65
68
  toggleMode
66
69
  }), [mode, _themeOptions, toggleMode]);
70
+
71
+ // change prefer manually
72
+ useEffect(() => {
73
+ if (prefer) {
74
+ setMode(prefer);
75
+ }
76
+ }, [prefer, setMode]);
67
77
  return /*#__PURE__*/_jsx(ConfigContext.Provider, {
68
78
  value: config,
69
79
  children: /*#__PURE__*/_jsx(LocaleProvider, {
@@ -1,13 +1,8 @@
1
1
  import { Components, type ThemeOptions } from '@mui/material/styles';
2
2
  import type { Typography } from '@mui/material/styles/createTypography';
3
- import '@fontsource/inter/latin-300.css';
4
- import '@fontsource/inter/latin-400.css';
5
- import '@fontsource/inter/latin-500.css';
6
- import '@fontsource/inter/latin-700.css';
7
- import '@fontsource/inter/latin-ext-300.css';
8
- import '@fontsource/inter/latin-ext-400.css';
9
- import '@fontsource/inter/latin-ext-500.css';
10
- import '@fontsource/inter/latin-ext-700.css';
3
+ import '@fontsource/roboto/400';
4
+ import '@fontsource/roboto/500';
5
+ import '@fontsource/roboto/700';
11
6
  import { ThemeMode } from '../type';
12
7
  declare module '@mui/material/styles' {
13
8
  interface Theme {
@@ -39,11 +34,12 @@ declare module '@mui/material/styles/createTypography' {
39
34
  interface TypographyOptions {
40
35
  useNextVariants?: boolean;
41
36
  color?: Record<string, string>;
42
- button?: {
43
- fontWeight?: number;
44
- };
45
37
  }
46
38
  }
39
+ export declare function collectFontFamilies(obj?: {
40
+ fontFamily?: string;
41
+ }, fontSet?: Set<string>): Set<string>;
42
+ export declare function loadFonts(fonts: string[]): Promise<boolean>;
47
43
  export declare function createDefaultThemeOptions(mode?: ThemeMode): ThemeOptions;
48
44
  export declare const create: ({ mode, pageWidth, overrides, palette, components, ...rest }?: ThemeOptions) => import("@mui/material/styles").Theme;
49
45
  export declare const createTheme: ({ mode, pageWidth, overrides, palette, components, ...rest }?: ThemeOptions) => import("@mui/material/styles").Theme;
@@ -2,15 +2,14 @@
2
2
  // https://app.zeplin.io/styleguide/5d1436f1e97c2156f49c0725/colors
3
3
  import { createTheme as _createTheme, responsiveFontSizes } from '@mui/material/styles';
4
4
  import { deepmerge } from '@mui/utils';
5
- // 为了避免加载全量的字体导致打包后体积太大,目前只选择了 latin 语系的字体
6
- import '@fontsource/inter/latin-300.css';
7
- import '@fontsource/inter/latin-400.css';
8
- import '@fontsource/inter/latin-500.css';
9
- import '@fontsource/inter/latin-700.css';
10
- import '@fontsource/inter/latin-ext-300.css';
11
- import '@fontsource/inter/latin-ext-400.css';
12
- import '@fontsource/inter/latin-ext-500.css';
13
- import '@fontsource/inter/latin-ext-700.css';
5
+ import webfontloader from 'webfontloader';
6
+ // 为了避免加载全量的字体导致打包后体积太大,目前只选择了 MUI 默认的 Roboto 字体
7
+ // eslint-disable-next-line import/no-unresolved
8
+ import '@fontsource/roboto/400';
9
+ // eslint-disable-next-line import/no-unresolved
10
+ import '@fontsource/roboto/500';
11
+ // eslint-disable-next-line import/no-unresolved
12
+ import '@fontsource/roboto/700';
14
13
  import colors from '../Colors';
15
14
  import { cleanedObj } from '../Util';
16
15
 
@@ -18,12 +17,56 @@ import { cleanedObj } from '../Util';
18
17
 
19
18
  // 扩展 TypographyOptions
20
19
 
21
- const muiDarkTheme = _createTheme({
20
+ // 默认深色主题
21
+ const defaultDarkTheme = _createTheme({
22
22
  palette: {
23
23
  mode: 'dark'
24
24
  }
25
25
  });
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(',');
26
+
27
+ // 收集字体配置
28
+ export function collectFontFamilies(obj, fontSet = new Set()) {
29
+ if (!obj || typeof obj !== 'object') return fontSet;
30
+ if (typeof obj.fontFamily === 'string') {
31
+ obj.fontFamily.replace(/"/g, '').split(',').map(font => font.trim()).filter(Boolean).forEach(font => fontSet.add(font));
32
+ }
33
+ Object.values(obj).forEach(value => {
34
+ if (typeof value === 'object') {
35
+ collectFontFamilies(value, fontSet);
36
+ }
37
+ });
38
+ return fontSet;
39
+ }
40
+
41
+ // 动态加载字体
42
+ const prevFonts = new Set(['Roboto', 'inherit']);
43
+ export function loadFonts(fonts) {
44
+ // 过滤出未加载的字体
45
+ const unloadedFonts = fonts.filter(font => !prevFonts.has(font));
46
+
47
+ // 如果所有字体都已加载,直接返回
48
+ if (unloadedFonts.length === 0) {
49
+ return Promise.resolve(true);
50
+ }
51
+
52
+ // record
53
+ unloadedFonts.forEach(font => prevFonts.add(font));
54
+ return new Promise(resolve => {
55
+ webfontloader.load({
56
+ google: {
57
+ families: unloadedFonts
58
+ },
59
+ active: () => resolve(true),
60
+ inactive: () => resolve(true),
61
+ fontinactive: (familyName, fvd) => {
62
+ prevFonts.delete(familyName);
63
+ console.warn(`font ${familyName} ${fvd} download failed`);
64
+ }
65
+ });
66
+ });
67
+ }
68
+
69
+ // 创建默认主题配置
27
70
  export function createDefaultThemeOptions(mode = 'light') {
28
71
  const result = {
29
72
  palette: {
@@ -44,7 +87,6 @@ export function createDefaultThemeOptions(mode = 'light') {
44
87
  main: mode === 'light' ? '#222222' : colors.common.white,
45
88
  gray: mode === 'light' ? colors.grey[500] : colors.grey[300]
46
89
  },
47
- fontFamily: DEFAULT_FONT_FAMILY,
48
90
  // button 默认使用粗体
49
91
  button: {
50
92
  fontWeight: 700
@@ -95,10 +137,11 @@ export function createDefaultThemeOptions(mode = 'light') {
95
137
  }
96
138
  }
97
139
  };
140
+
98
141
  // 深色主题
99
142
  if (mode === 'dark') {
100
143
  result.palette = {
101
- ...muiDarkTheme.palette,
144
+ ...defaultDarkTheme.palette,
102
145
  background: {
103
146
  paper: colors.grey[900],
104
147
  default: colors.grey[900]
@@ -163,6 +206,10 @@ export const create = ({
163
206
  const mergedThemeOptions = deepmerge(deepmerge(defaultThemeOptions, cleanedObj(blockletThemeOptions)), cleanedObj(userThemeOptions));
164
207
  const theme = _createTheme(mergedThemeOptions);
165
208
 
209
+ // 异步加载字体
210
+ const fonts = collectFontFamilies(theme.typography);
211
+ loadFonts(Array.from(fonts));
212
+
166
213
  /**
167
214
  * 响应式字体,配置后,theme.typography 会变为下面的结构
168
215
  * {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/ux",
3
- "version": "2.12.53",
3
+ "version": "2.12.55",
4
4
  "description": "Common used react components for arcblock products",
5
5
  "keywords": [
6
6
  "react",
@@ -47,6 +47,7 @@
47
47
  "@types/pako": "^2.0.3",
48
48
  "@types/react": "^18.3.4",
49
49
  "@types/react-helmet": "^6.1.11",
50
+ "@types/webfontloader": "^1.6.38",
50
51
  "@typescript-eslint/eslint-plugin": "^8.7.0",
51
52
  "@typescript-eslint/parser": "^8.7.0",
52
53
  "babel-jest": "29",
@@ -69,14 +70,14 @@
69
70
  "react": ">=18.2.0",
70
71
  "react-router-dom": ">=6.22.3"
71
72
  },
72
- "gitHead": "454c63f6d9b58724fa0176ac74de2f306b53207c",
73
+ "gitHead": "33f46387b9d5664d83854183a51b9c7e6641c6bf",
73
74
  "dependencies": {
74
75
  "@arcblock/did-motif": "^1.1.13",
75
- "@arcblock/icons": "^2.12.53",
76
- "@arcblock/nft-display": "^2.12.53",
77
- "@arcblock/react-hooks": "^2.12.53",
76
+ "@arcblock/icons": "^2.12.55",
77
+ "@arcblock/nft-display": "^2.12.55",
78
+ "@arcblock/react-hooks": "^2.12.55",
78
79
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
79
- "@fontsource/inter": "^5.0.16",
80
+ "@fontsource/roboto": "^5.2.5",
80
81
  "@fontsource/ubuntu-mono": "^5.0.18",
81
82
  "@iconify-icons/logos": "^1.2.36",
82
83
  "@iconify-icons/material-symbols": "^1.2.58",
@@ -123,6 +124,7 @@
123
124
  "topojson-client": "^3.1.0",
124
125
  "type-fest": "^4.28.0",
125
126
  "validator": "^13.9.0",
126
- "versor": "^0.0.4"
127
+ "versor": "^0.0.4",
128
+ "webfontloader": "^1.6.28"
127
129
  }
128
130
  }
@@ -1,9 +1,15 @@
1
1
  import { useMemoizedFn, useAsyncEffect } from 'ahooks';
2
2
  import { createContext, useContext, useState } from 'react';
3
3
  import type { Blocklet } from '../type';
4
- import { getBlockletData } from '../Util/federated';
4
+ import { getBlockletData, getFederatedEnabled, getMaster } from '../Util/federated';
5
5
 
6
- const BlockletContext = createContext<Blocklet | null>(null);
6
+ const BlockletContext = createContext<{
7
+ blocklet: Blocklet | null;
8
+ masterBlocklet: Blocklet | null;
9
+ }>({
10
+ blocklet: null,
11
+ masterBlocklet: null,
12
+ });
7
13
 
8
14
  const { Provider, Consumer } = BlockletContext;
9
15
 
@@ -20,6 +26,7 @@ function BlockletProvider({
20
26
  loading?: React.ReactNode;
21
27
  }) {
22
28
  const [blockletData, setBlockletData] = useState<Blocklet | null>(null);
29
+ const [masterBlockletData, setMasterBlockletData] = useState<Blocklet | null>(null);
23
30
  const getBlockleDataWithCache = useMemoizedFn(async () => {
24
31
  if (!baseUrl || window.location.href.startsWith(baseUrl)) {
25
32
  throw new Error('no blocklet data');
@@ -29,22 +36,37 @@ function BlockletProvider({
29
36
  });
30
37
 
31
38
  useAsyncEffect(async () => {
39
+ let result = null;
40
+ let resultMaster = null;
32
41
  try {
33
- const data = await getBlockleDataWithCache();
34
- setBlockletData(data);
42
+ result = await getBlockleDataWithCache();
35
43
  } catch {
36
44
  // NOTICE: 如果获取指定 blockletData 失败,则使用 window.blocklet
37
45
  const data = globalThis.blocklet || globalThis.env;
38
- setBlockletData(data);
46
+ result = data;
39
47
  }
48
+ if (result) {
49
+ if (getFederatedEnabled(result)) {
50
+ const masterSite = getMaster(result);
51
+ if (masterSite) {
52
+ resultMaster = await getBlockletData(masterSite.appUrl);
53
+ }
54
+ }
55
+ }
56
+ setBlockletData(result);
57
+ setMasterBlockletData(resultMaster);
40
58
  // eslint-disable-next-line react-hooks/exhaustive-deps
41
59
  }, [baseUrl]);
42
- return <Provider value={blockletData}>{blockletData ? children : loading || null}</Provider>;
60
+ return (
61
+ <Provider value={{ blocklet: blockletData, masterBlocklet: masterBlockletData }}>
62
+ {blockletData ? children : loading || null}
63
+ </Provider>
64
+ );
43
65
  }
44
66
 
45
67
  function useBlockletContext() {
46
- const blocklet = useContext(BlockletContext);
47
- return { blocklet };
68
+ const { blocklet, masterBlocklet } = useContext(BlockletContext);
69
+ return { blocklet, masterBlocklet };
48
70
  }
49
71
 
50
72
  export { BlockletContext, BlockletProvider, Consumer as BlockletConsumer, useBlockletContext };
@@ -1,4 +1,4 @@
1
- import { createContext, useContext, ReactNode, useMemo, useState, useCallback } from 'react';
1
+ import { createContext, useContext, ReactNode, useMemo, useState, useCallback, useEffect } from 'react';
2
2
  import type { ThemeOptions } from '@mui/material/styles';
3
3
  import useMediaQuery from '@mui/material/useMediaQuery';
4
4
  import set from 'lodash/set';
@@ -49,11 +49,16 @@ export function ConfigProvider({
49
49
  }: ConfigProviderProps) {
50
50
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
51
51
  const [mode, setMode] = useState<ThemeMode>(() => {
52
- const preferMode = localStorage.getItem(preferThemeModeKey) as ThemeMode;
53
- if (preferMode && (preferMode === 'light' || preferMode === 'dark')) {
54
- return preferMode;
52
+ if (prefer) {
53
+ return prefer;
55
54
  }
56
- return prefer || (prefersDarkMode ? 'dark' : 'light');
55
+
56
+ const localPrefer = localStorage.getItem(preferThemeModeKey) as ThemeMode;
57
+ if (localPrefer && (localPrefer === 'light' || localPrefer === 'dark')) {
58
+ return localPrefer;
59
+ }
60
+
61
+ return prefersDarkMode ? 'dark' : 'light';
57
62
  });
58
63
 
59
64
  const _themeOptions = useMemo(() => {
@@ -92,6 +97,13 @@ export function ConfigProvider({
92
97
  [mode, _themeOptions, toggleMode]
93
98
  );
94
99
 
100
+ // change prefer manually
101
+ useEffect(() => {
102
+ if (prefer) {
103
+ setMode(prefer);
104
+ }
105
+ }, [prefer, setMode]);
106
+
95
107
  return (
96
108
  <ConfigContext.Provider value={config}>
97
109
  <LocaleProvider
@@ -3,15 +3,15 @@
3
3
  import { createTheme as _createTheme, Components, responsiveFontSizes, type ThemeOptions } from '@mui/material/styles';
4
4
  import { deepmerge } from '@mui/utils';
5
5
  import type { Typography } from '@mui/material/styles/createTypography';
6
- // 为了避免加载全量的字体导致打包后体积太大,目前只选择了 latin 语系的字体
7
- import '@fontsource/inter/latin-300.css';
8
- import '@fontsource/inter/latin-400.css';
9
- import '@fontsource/inter/latin-500.css';
10
- import '@fontsource/inter/latin-700.css';
11
- import '@fontsource/inter/latin-ext-300.css';
12
- import '@fontsource/inter/latin-ext-400.css';
13
- import '@fontsource/inter/latin-ext-500.css';
14
- import '@fontsource/inter/latin-ext-700.css';
6
+ import webfontloader from 'webfontloader';
7
+ // 为了避免加载全量的字体导致打包后体积太大,目前只选择了 MUI 默认的 Roboto 字体
8
+ // eslint-disable-next-line import/no-unresolved
9
+ import '@fontsource/roboto/400';
10
+ // eslint-disable-next-line import/no-unresolved
11
+ import '@fontsource/roboto/500';
12
+ // eslint-disable-next-line import/no-unresolved
13
+ import '@fontsource/roboto/700';
14
+
15
15
  import colors from '../Colors';
16
16
  import { ThemeMode } from '../type';
17
17
  import { cleanedObj } from '../Util';
@@ -48,29 +48,64 @@ declare module '@mui/material/styles/createTypography' {
48
48
  interface TypographyOptions {
49
49
  useNextVariants?: boolean;
50
50
  color?: Record<string, string>;
51
- button?: {
52
- fontWeight?: number;
53
- };
54
51
  }
55
52
  }
56
53
 
57
- const muiDarkTheme = _createTheme({ palette: { mode: 'dark' } });
58
-
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(',');
54
+ // 默认深色主题
55
+ const defaultDarkTheme = _createTheme({ palette: { mode: 'dark' } });
56
+
57
+ // 收集字体配置
58
+ export function collectFontFamilies(obj?: { fontFamily?: string }, fontSet: Set<string> = new Set()): Set<string> {
59
+ if (!obj || typeof obj !== 'object') return fontSet;
60
+
61
+ if (typeof obj.fontFamily === 'string') {
62
+ obj.fontFamily
63
+ .replace(/"/g, '')
64
+ .split(',')
65
+ .map((font: string) => font.trim())
66
+ .filter(Boolean)
67
+ .forEach((font: string) => fontSet.add(font));
68
+ }
69
+
70
+ Object.values(obj).forEach((value) => {
71
+ if (typeof value === 'object') {
72
+ collectFontFamilies(value, fontSet);
73
+ }
74
+ });
75
+
76
+ return fontSet;
77
+ }
78
+
79
+ // 动态加载字体
80
+ const prevFonts = new Set<string>(['Roboto', 'inherit']);
81
+ export function loadFonts(fonts: string[]) {
82
+ // 过滤出未加载的字体
83
+ const unloadedFonts = fonts.filter((font) => !prevFonts.has(font));
73
84
 
85
+ // 如果所有字体都已加载,直接返回
86
+ if (unloadedFonts.length === 0) {
87
+ return Promise.resolve(true);
88
+ }
89
+
90
+ // record
91
+ unloadedFonts.forEach((font) => prevFonts.add(font));
92
+
93
+ return new Promise<boolean>((resolve) => {
94
+ webfontloader.load({
95
+ google: {
96
+ families: unloadedFonts,
97
+ },
98
+ active: () => resolve(true),
99
+ inactive: () => resolve(true),
100
+ fontinactive: (familyName, fvd) => {
101
+ prevFonts.delete(familyName);
102
+ console.warn(`font ${familyName} ${fvd} download failed`);
103
+ },
104
+ });
105
+ });
106
+ }
107
+
108
+ // 创建默认主题配置
74
109
  export function createDefaultThemeOptions(mode: ThemeMode = 'light'): ThemeOptions {
75
110
  const result: ThemeOptions = {
76
111
  palette: {
@@ -91,7 +126,6 @@ export function createDefaultThemeOptions(mode: ThemeMode = 'light'): ThemeOptio
91
126
  main: mode === 'light' ? '#222222' : colors.common.white,
92
127
  gray: mode === 'light' ? colors.grey[500] : colors.grey[300],
93
128
  },
94
- fontFamily: DEFAULT_FONT_FAMILY,
95
129
  // button 默认使用粗体
96
130
  button: {
97
131
  fontWeight: 700,
@@ -142,10 +176,11 @@ export function createDefaultThemeOptions(mode: ThemeMode = 'light'): ThemeOptio
142
176
  },
143
177
  },
144
178
  };
179
+
145
180
  // 深色主题
146
181
  if (mode === 'dark') {
147
182
  result.palette = {
148
- ...muiDarkTheme.palette,
183
+ ...defaultDarkTheme.palette,
149
184
  background: {
150
185
  paper: colors.grey[900],
151
186
  default: colors.grey[900],
@@ -215,6 +250,10 @@ export const create = ({
215
250
 
216
251
  const theme = _createTheme(mergedThemeOptions);
217
252
 
253
+ // 异步加载字体
254
+ const fonts = collectFontFamilies(theme.typography);
255
+ loadFonts(Array.from(fonts));
256
+
218
257
  /**
219
258
  * 响应式字体,配置后,theme.typography 会变为下面的结构
220
259
  * {