@arcblock/ux 2.13.27 → 2.13.29

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.
Files changed (33) hide show
  1. package/lib/Config/config-provider.d.ts +1 -0
  2. package/lib/DIDConnect/did-connect-container.d.ts +2 -1
  3. package/lib/DIDConnect/did-connect-container.js +4 -2
  4. package/lib/DIDConnect/index.d.ts +1 -0
  5. package/lib/DIDConnect/index.js +2 -1
  6. package/lib/DIDConnect/request-storage-access-api-dialog.d.ts +12 -0
  7. package/lib/DIDConnect/request-storage-access-api-dialog.js +325 -0
  8. package/lib/RelativeTime/index.d.ts +2 -1
  9. package/lib/RelativeTime/index.js +11 -5
  10. package/lib/SessionUser/components/un-login.js +29 -37
  11. package/lib/SharedBridge/index.d.ts +5 -6
  12. package/lib/SharedBridge/index.js +34 -48
  13. package/lib/Tabs/index.js +2 -2
  14. package/lib/Theme/theme-provider.d.ts +5 -2
  15. package/lib/Theme/theme-provider.js +28 -9
  16. package/lib/Theme/theme.d.ts +6 -4
  17. package/lib/Theme/theme.js +15 -9
  18. package/package.json +6 -6
  19. package/src/DIDConnect/did-connect-container.tsx +4 -1
  20. package/src/DIDConnect/index.ts +1 -0
  21. package/src/DIDConnect/request-storage-access-api-dialog.tsx +280 -0
  22. package/src/RelativeTime/index.tsx +25 -4
  23. package/src/SessionUser/components/un-login.tsx +21 -29
  24. package/src/SharedBridge/index.tsx +91 -97
  25. package/src/Tabs/index.tsx +2 -2
  26. package/src/Theme/theme-provider.tsx +36 -10
  27. package/src/Theme/theme.ts +21 -15
  28. package/lib/LoginButton/index.d.ts +0 -12
  29. package/lib/LoginButton/index.js +0 -74
  30. package/lib/SharedBridge/need-storage-access-api-dialog.d.ts +0 -6
  31. package/lib/SharedBridge/need-storage-access-api-dialog.js +0 -191
  32. package/src/LoginButton/index.tsx +0 -73
  33. package/src/SharedBridge/need-storage-access-api-dialog.tsx +0 -149
@@ -55,6 +55,7 @@ export interface RelativeTimeProps {
55
55
  tz?: string;
56
56
  relativeRange?: number;
57
57
  enableTooltip?: boolean;
58
+ showUTCPrefix?: boolean;
58
59
  }
59
60
 
60
61
  function useRelativeTime({
@@ -144,13 +145,17 @@ function UTCChip({
144
145
  sign,
145
146
  hoursOffset,
146
147
  setIsUtc,
148
+ showUTCPrefix = true,
147
149
  }: {
148
150
  locale: Locale;
149
151
  isUtc?: boolean;
150
152
  sign: string;
151
153
  hoursOffset: number;
152
154
  setIsUtc: (data: any) => void;
155
+ showUTCPrefix?: boolean;
153
156
  }) {
157
+ const prefix = showUTCPrefix ? `${translations[locale].utc}: ` : '';
158
+
154
159
  return (
155
160
  <Box
156
161
  component="span"
@@ -161,10 +166,11 @@ function UTCChip({
161
166
  fontSize: '0.8rem',
162
167
  borderColor: 'divider',
163
168
  borderRadius: '20px',
164
- padding: '0px 8px',
169
+ padding: '4px 8px',
170
+ lineHeight: 1,
165
171
  }}
166
172
  onClick={() => setIsUtc((r: any) => !r)}>
167
- {`${translations[locale].utc}: ${isUtc ? 'UTC' : `UTC${sign}${hoursOffset}`}`}
173
+ {`${prefix}${isUtc ? 'UTC' : `UTC${sign}${hoursOffset}`}`}
168
174
  </Box>
169
175
  );
170
176
  }
@@ -179,6 +185,7 @@ export default function RelativeTime({
179
185
  tz,
180
186
  relativeRange,
181
187
  enableTooltip = true,
188
+ showUTCPrefix = true,
182
189
  ...rest
183
190
  }: RelativeTimeProps) {
184
191
  const { innerContent, popContent, isUtc, setIsUtc, sign, hoursOffset, relativeString } = useRelativeTime({
@@ -212,7 +219,14 @@ export default function RelativeTime({
212
219
  ·
213
220
  </Box>
214
221
 
215
- <UTCChip locale={locale} isUtc={isUtc} sign={sign} hoursOffset={hoursOffset} setIsUtc={setIsUtc} />
222
+ <UTCChip
223
+ locale={locale}
224
+ isUtc={isUtc}
225
+ sign={sign}
226
+ hoursOffset={hoursOffset}
227
+ setIsUtc={setIsUtc}
228
+ showUTCPrefix={showUTCPrefix}
229
+ />
216
230
  </Box>
217
231
  </Tooltip>
218
232
  );
@@ -226,7 +240,14 @@ export default function RelativeTime({
226
240
  </Box>
227
241
 
228
242
  {type === 'utc' && (
229
- <UTCChip locale={locale} isUtc={isUtc} sign={sign} hoursOffset={hoursOffset} setIsUtc={setIsUtc} />
243
+ <UTCChip
244
+ locale={locale}
245
+ isUtc={isUtc}
246
+ sign={sign}
247
+ hoursOffset={hoursOffset}
248
+ setIsUtc={setIsUtc}
249
+ showUTCPrefix={showUTCPrefix}
250
+ />
230
251
  )}
231
252
  </Box>
232
253
  </Tooltip>
@@ -27,7 +27,7 @@ import { translations } from '../libs/translation';
27
27
  import Typography from '../../Typography';
28
28
  import QuickLoginItem from './quick-login-item';
29
29
  import { getFederatedEnabled, getMaster } from '../../Util/federated';
30
- import LoginButton from '../../LoginButton';
30
+ import { BLOCKLET_SERVICE_PATH_PREFIX } from '../../Util/constant';
31
31
 
32
32
  export interface UnLoginProps {
33
33
  session: Session;
@@ -70,7 +70,7 @@ export default function UnLogin({ session, onLogin = noop, size = 24, dark = fal
70
70
  const loginAppName = loginApp?.appName || 'DID Connect';
71
71
  const loginAppLogo = joinURL(
72
72
  loginApp?.appUrl || '/',
73
- loginApp?.appLogo || '/.well-known/service/blocklet/logo?imageFilter=convert&f=png&h=80'
73
+ loginApp?.appLogo || `${BLOCKLET_SERVICE_PATH_PREFIX}/blocklet/logo?imageFilter=convert&f=png&h=80`
74
74
  );
75
75
 
76
76
  useEffect(() => {
@@ -105,34 +105,26 @@ export default function UnLogin({ session, onLogin = noop, size = 24, dark = fal
105
105
 
106
106
  return (
107
107
  <>
108
- <LoginButton
109
- locale={locale}
108
+ <IconButton
109
+ ref={userAnchorRef}
110
+ data-cy="sessionManager-login"
111
+ className="arc-session-user-unlogin"
112
+ size="medium"
110
113
  onClick={_onLogin}
111
- render={({ onClick }) => {
112
- return (
113
- <IconButton
114
- ref={userAnchorRef}
115
- data-cy="sessionManager-login"
116
- className="arc-session-user-unlogin"
117
- size="medium"
118
- onClick={onClick}
119
- aria-label="Login button">
120
- {isFirstLoading ? (
121
- <Box width={size} height={size} display="flex" justifyContent="center" alignItems="center">
122
- <CircularProgress style={{ width: size - 4, height: size - 4, color: dark ? '#fff' : '' }} />
123
- </Box>
124
- ) : (
125
- <Icon
126
- icon={UserIcon}
127
- fontSize={size}
128
- color={dark ? '#fff' : 'inherit'}
129
- style={{ transform: 'scale(1.25)' }}
130
- />
131
- )}
132
- </IconButton>
133
- );
134
- }}
135
- />
114
+ aria-label="Login button">
115
+ {isFirstLoading ? (
116
+ <Box width={size} height={size} display="flex" justifyContent="center" alignItems="center">
117
+ <CircularProgress style={{ width: size - 4, height: size - 4, color: dark ? '#fff' : '' }} />
118
+ </Box>
119
+ ) : (
120
+ <Icon
121
+ icon={UserIcon}
122
+ fontSize={size}
123
+ color={dark ? '#fff' : 'inherit'}
124
+ style={{ transform: 'scale(1.25)' }}
125
+ />
126
+ )}
127
+ </IconButton>
136
128
  <Popper
137
129
  open={currentState.open}
138
130
  anchorEl={userAnchorRef.current}
@@ -1,119 +1,113 @@
1
1
  import { Box } from '@mui/material';
2
2
  import type { SxProps } from '@mui/material';
3
- import React, { memo, useEffect, useId, useRef } from 'react';
3
+ import { forwardRef, memo, useEffect, useId, useImperativeHandle, useRef } from 'react';
4
4
  import { withQuery } from 'ufo';
5
5
  import { useMemoizedFn, useReactive } from 'ahooks';
6
+ import noop from 'lodash/noop';
6
7
 
7
8
  import { mergeSx } from '../Util/style';
8
9
  import { callIframe, getCallbackAction } from '../Util/iframe';
9
10
  import { Locale } from '../type';
10
- import NeedStorageAccessApiDialog from './need-storage-access-api-dialog';
11
- import { DIDConnectContainer } from '../DIDConnect';
12
11
 
13
- const SharedBridge = memo(function SharedBridge({
14
- src,
15
- onClick,
16
- onLoad,
17
- sx,
18
- iframeRef,
19
- locale = 'en',
20
- ...rest
21
- }: {
22
- src: string;
23
- onClick: (data: { action: string; value: boolean; visitorId?: string }) => void;
24
- onLoad: () => void;
25
- sx?: SxProps;
26
- iframeRef?: React.RefObject<HTMLIFrameElement>;
27
- locale?: Locale;
28
- }) {
29
- const _iframeRef = useRef<HTMLIFrameElement>(null);
30
- const refId = useId();
31
- const dataId = `shared-bridge_${refId}`;
32
- const currentState = useReactive<{
33
- hasInited?: boolean;
34
- open: boolean;
35
- hasStorageAccess: boolean;
36
- origin: string;
37
- host: string;
38
- }>({
39
- hasInited: undefined,
40
- open: false,
41
- hasStorageAccess: false,
42
- get origin() {
43
- try {
44
- return new URL(src).origin;
45
- } catch (error) {
46
- return src;
47
- }
48
- },
49
- get host() {
50
- try {
51
- return new URL(src).host;
52
- } catch (error) {
53
- return src;
54
- }
12
+ const SharedBridge = forwardRef(
13
+ (
14
+ {
15
+ src,
16
+ onClick,
17
+ onLoad = noop,
18
+ sx,
19
+ locale = 'en',
20
+ ...rest
21
+ }: {
22
+ src: string;
23
+ onClick: (data: { action: string; value: boolean; visitorId?: string; error?: Error }) => void;
24
+ onLoad?: () => void;
25
+ sx?: SxProps;
26
+ locale?: Locale;
55
27
  },
56
- });
28
+ ref
29
+ ) => {
30
+ const targetIframeRef = useRef<HTMLIFrameElement>(null);
31
+ const refId = useId();
32
+ const dataId = `shared-bridge_${refId}`;
33
+ const currentState = useReactive<{
34
+ hasInited?: boolean;
35
+ open: boolean;
36
+ hasStorageAccess: boolean;
37
+ origin: string;
38
+ host: string;
39
+ containerEl: HTMLDivElement | null;
40
+ }>({
41
+ hasInited: undefined,
42
+ open: false,
43
+ hasStorageAccess: false,
44
+ containerEl: null,
45
+ get origin() {
46
+ try {
47
+ return new URL(src).origin;
48
+ } catch (error) {
49
+ return src;
50
+ }
51
+ },
52
+ get host() {
53
+ try {
54
+ return new URL(src).host;
55
+ } catch (error) {
56
+ return src;
57
+ }
58
+ },
59
+ });
57
60
 
58
- const targetIframeRef = iframeRef ?? _iframeRef;
61
+ useEffect(() => {
62
+ async function handleMessage(event: MessageEvent) {
63
+ const { data } = event;
64
+ if (data.action === getCallbackAction(dataId, 'requestStorageAccess')) {
65
+ currentState.open = false;
59
66
 
60
- useEffect(() => {
61
- async function handleMessage(event: MessageEvent) {
62
- const { data } = event;
63
- if (data.action === getCallbackAction(dataId, 'requestStorageAccess')) {
64
- currentState.open = false;
67
+ if (!data.value) {
68
+ onClick(data);
69
+ return;
70
+ }
65
71
 
66
- if (!data.value) {
67
- onClick(data);
68
- return;
72
+ const { value: visitorId } = await callIframe(targetIframeRef.current as HTMLIFrameElement, 'getVisitorId');
73
+ onClick({ ...data, visitorId });
74
+ } else if (data.action === getCallbackAction(dataId, 'preRequestStorageAccess')) {
75
+ currentState.open = true;
69
76
  }
70
-
71
- const { value: visitorId } = await callIframe(targetIframeRef.current as HTMLIFrameElement, 'getVisitorId');
72
- onClick({ ...data, visitorId });
73
- } else if (data.action === getCallbackAction(dataId, 'preRequestStorageAccess')) {
74
- currentState.open = true;
75
77
  }
76
- }
77
78
 
78
- window.addEventListener('message', handleMessage);
79
- return () => {
80
- window.removeEventListener('message', handleMessage);
81
- };
82
- // eslint-disable-next-line react-hooks/exhaustive-deps
83
- }, [onClick, dataId, targetIframeRef?.current]);
79
+ window.addEventListener('message', handleMessage);
80
+ return () => {
81
+ window.removeEventListener('message', handleMessage);
82
+ };
83
+ // eslint-disable-next-line react-hooks/exhaustive-deps
84
+ }, [onClick, dataId, targetIframeRef?.current]);
84
85
 
85
- const handleLoad = useMemoizedFn(() => {
86
- callIframe(targetIframeRef.current as HTMLIFrameElement, 'hasStorageAccess').then(({ value }) => {
87
- currentState.hasStorageAccess = value;
88
- currentState.hasInited = true;
86
+ const handleLoad = useMemoizedFn(() => {
87
+ callIframe(targetIframeRef.current as HTMLIFrameElement, 'hasStorageAccess').then(({ value }) => {
88
+ currentState.hasStorageAccess = value;
89
+ currentState.hasInited = true;
90
+ });
91
+ // HACK: 如果目标 bridge 1s 内没有初始化,则认为目标 bridge 不兼容,不进行后续内容的加载
92
+ setTimeout(() => {
93
+ if (currentState.hasInited === undefined) {
94
+ currentState.hasInited = false;
95
+ }
96
+ }, 1000);
97
+ onLoad();
89
98
  });
90
- setTimeout(() => {
91
- if (currentState.hasInited === undefined) {
92
- currentState.hasInited = false;
93
- }
94
- }, 1000);
95
- onLoad();
96
- });
97
-
98
- if (currentState.hasInited === false) {
99
- return null;
100
- }
101
99
 
102
- if (currentState.hasStorageAccess) {
103
- return null;
104
- }
105
-
106
- return (
107
- <>
108
- <DIDConnectContainer popup hideCloseButton open={currentState.open}>
109
- <NeedStorageAccessApiDialog locale={locale} origin={currentState.origin} host={currentState.host} />
110
- </DIDConnectContainer>
100
+ useImperativeHandle(ref, () => ({
101
+ callIframe(action: string) {
102
+ return callIframe(targetIframeRef.current as HTMLIFrameElement, action);
103
+ },
104
+ }));
105
+ return (
111
106
  <Box
112
107
  {...rest}
113
108
  component="iframe"
114
109
  ref={targetIframeRef}
115
110
  onLoad={handleLoad}
116
- title="shared-bridge"
117
111
  data-id={dataId}
118
112
  src={withQuery(src, { id: dataId })}
119
113
  sx={mergeSx(
@@ -125,13 +119,13 @@ const SharedBridge = memo(function SharedBridge({
125
119
  width: '100%',
126
120
  height: '100%',
127
121
  cursor: 'pointer',
128
- opacity: 0,
122
+ backgroundColor: 'transparent',
129
123
  },
130
124
  sx
131
125
  )}
132
126
  />
133
- </>
134
- );
135
- });
127
+ );
128
+ }
129
+ );
136
130
 
137
- export default SharedBridge;
131
+ export default memo(SharedBridge);
@@ -46,7 +46,7 @@ function CardTabs({ tabs, current, onChange, ...rest }: CardTabsProps) {
46
46
  },
47
47
  '.MuiTabs-flexContainer': {
48
48
  borderRadius: '100vw',
49
- backgroundColor: 'grey.200',
49
+ backgroundColor: 'grey.100',
50
50
  padding: 0.5,
51
51
  display: 'inline-flex',
52
52
  columnGap: 0.25,
@@ -65,7 +65,7 @@ function CardTabs({ tabs, current, onChange, ...rest }: CardTabsProps) {
65
65
  textTransform: 'capitalize',
66
66
  transition: 'background-color 0.2s ease',
67
67
  '&.Mui-selected, &:hover': {
68
- backgroundColor: 'white',
68
+ backgroundColor: 'action.selected',
69
69
  borderColor: 'grey.100',
70
70
  color: 'grey.A700',
71
71
  },
@@ -1,13 +1,20 @@
1
1
  import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { GlobalStyles, PaletteMode } from '@mui/material';
4
- import { ThemeProvider as MuiThemeProvider, Theme, useTheme } from '@mui/material/styles';
4
+ import { ThemeProvider as MuiThemeProvider, Theme, ThemeOptions, useTheme } from '@mui/material/styles';
5
5
  import StyledEngineProvider from '@mui/material/StyledEngineProvider';
6
6
  import CssBaseline from '@mui/material/CssBaseline';
7
7
  import set from 'lodash/set';
8
8
  import { BLOCKLET_THEME_PREFER_KEY } from '@blocklet/theme';
9
9
 
10
- import { createTheme, getDefaultThemePrefer, isTheme, lazyThemeConfig, type UserThemeOptions } from './theme';
10
+ import {
11
+ createTheme,
12
+ getDefaultThemePrefer,
13
+ isTheme,
14
+ isUxTheme,
15
+ lazyCreateDefaultTheme,
16
+ type UxThemeOptions,
17
+ } from './theme';
11
18
 
12
19
  const defaultTheme = createTheme();
13
20
 
@@ -15,6 +22,7 @@ const defaultTheme = createTheme();
15
22
  export interface ColorSchemeContextType {
16
23
  mode: PaletteMode;
17
24
  toggleMode: () => void;
25
+ changeMode: (mode: PaletteMode) => void;
18
26
  prefer?: Prefer;
19
27
  }
20
28
 
@@ -102,7 +110,7 @@ function DarkSchemeStyles({ className }: { className?: string }) {
102
110
  return null;
103
111
  }
104
112
 
105
- export type UxTheme = Partial<Theme> | ((outerTheme: Partial<Theme>) => Theme);
113
+ export type UxTheme = ThemeOptions | ((parentTheme: Theme, context?: { mode: PaletteMode }) => Theme);
106
114
  export type Prefer = 'light' | 'dark' | 'system';
107
115
 
108
116
  interface BaseThemeProviderProps {
@@ -113,7 +121,7 @@ interface BaseThemeProviderProps {
113
121
  darkSchemeClass?: string;
114
122
  }
115
123
 
116
- /** 基础的 theme provider, 可以为 webapp/blocklet 快捷的配置好 mui theme provider */
124
+ /** 快速配置 MUI 主题 */
117
125
  function BaseThemeProvider({
118
126
  children,
119
127
  theme = defaultTheme,
@@ -144,7 +152,7 @@ interface ColorSchemeProviderProps extends BaseThemeProviderProps {
144
152
  disableBlockletTheme?: boolean;
145
153
  }
146
154
 
147
- /** 带颜色模式切换功能的 theme provider */
155
+ /** 配置带颜色模式切换功能的 MUI 主题 */
148
156
  function ColorSchemeProvider({
149
157
  children,
150
158
  theme: themeInput,
@@ -153,14 +161,21 @@ function ColorSchemeProvider({
153
161
  ...rest
154
162
  }: ThemeProviderProps) {
155
163
  const [mode, setMode] = useState<PaletteMode>(() => resolveMode(prefer));
164
+ const parentTheme = useTheme();
156
165
 
157
166
  const _themeInput = useMemo(() => {
158
- let result: UserThemeOptions = {};
159
- const getThemeConfig = lazyThemeConfig(mode);
167
+ let result: UxThemeOptions = {};
168
+ const createBaseTheme = lazyCreateDefaultTheme(mode);
160
169
 
161
170
  if (themeInput) {
162
171
  if (typeof themeInput === 'function') {
163
- result = { ...themeInput(getThemeConfig()) };
172
+ const baseTheme = createBaseTheme();
173
+
174
+ if (isUxTheme(parentTheme)) {
175
+ result = { ...themeInput(parentTheme, { mode }) };
176
+ } else {
177
+ result = { ...themeInput(baseTheme, { mode }) };
178
+ }
164
179
  } else {
165
180
  result = { ...themeInput };
166
181
  }
@@ -170,7 +185,7 @@ function ColorSchemeProvider({
170
185
  set(result, 'mode', mode);
171
186
 
172
187
  return result;
173
- }, [mode, themeInput]);
188
+ }, [mode, themeInput, parentTheme]);
174
189
 
175
190
  const theme = useMemo(() => {
176
191
  return createTheme({ ..._themeInput, disableBlockletTheme });
@@ -183,13 +198,24 @@ function ColorSchemeProvider({
183
198
  localStorage.setItem(BLOCKLET_THEME_PREFER_KEY, newMode);
184
199
  }, [mode, setMode]);
185
200
 
201
+ const changeMode = useCallback(
202
+ (newMode: PaletteMode) => {
203
+ if (mode !== newMode) {
204
+ setMode(newMode);
205
+ localStorage.setItem(BLOCKLET_THEME_PREFER_KEY, newMode);
206
+ }
207
+ },
208
+ [mode, setMode]
209
+ );
210
+
186
211
  const colorSchemeValue = useMemo(
187
212
  () => ({
188
213
  mode,
189
214
  toggleMode,
215
+ changeMode,
190
216
  prefer,
191
217
  }),
192
- [mode, prefer, toggleMode]
218
+ [mode, prefer, toggleMode, changeMode]
193
219
  );
194
220
 
195
221
  useEffect(() => {
@@ -20,6 +20,11 @@ export function isTheme(obj: any): obj is Theme {
20
20
  return obj && typeof obj === 'object' && obj.palette && typeof obj.palette.getContrastText === 'function';
21
21
  }
22
22
 
23
+ /** 是否是 UX Theme 对象 */
24
+ export function isUxTheme(obj: any): obj is Theme {
25
+ return isTheme(obj) && obj.__isUxTheme__ === true;
26
+ }
27
+
23
28
  // 收集字体配置
24
29
  export function collectFontFamilies(obj?: { fontFamily?: string }, fontSet: Set<string> = new Set()): Set<string> {
25
30
  if (!obj || typeof obj !== 'object') return fontSet;
@@ -107,26 +112,26 @@ export function createDefaultThemeOptions(mode: PaletteMode = 'light') {
107
112
  return BLOCKLET_THEME_LIGHT;
108
113
  }
109
114
 
110
- export interface UserThemeOptions extends ThemeOptions {
115
+ export interface UxThemeOptions extends ThemeOptions {
111
116
  disableBlockletTheme?: boolean;
112
117
  }
113
118
 
114
- // 用于获取 Blocklet Theme 配置,便于用户创建自定义主题
115
- export function lazyThemeConfig(mode: PaletteMode) {
116
- let config: Partial<Theme> | null = null;
119
+ export function lazyCreateDefaultTheme(mode: PaletteMode) {
120
+ let theme: Theme | null = null;
117
121
 
118
122
  return () => {
119
- if (config) return config;
123
+ if (theme) return theme;
120
124
 
121
- config = deepmerge(createDefaultThemeOptions(mode), window.blocklet?.theme?.[mode] ?? {}) as Partial<Theme>;
125
+ const options = deepmerge(createDefaultThemeOptions(mode), window.blocklet?.theme?.[mode] ?? {});
122
126
 
123
- return config;
127
+ theme = _createTheme(options);
128
+ return theme;
124
129
  };
125
130
  }
126
131
 
127
132
  // 主要处理 overrides
128
- const normalizeUserThemeOptions = ({ palette, components, overrides, ...rest }: UserThemeOptions) => {
129
- const result: UserThemeOptions = {
133
+ const normalizeUserThemeOptions = ({ palette, components, overrides, ...rest }: UxThemeOptions) => {
134
+ const result: UxThemeOptions = {
130
135
  palette,
131
136
  components: {
132
137
  ...overrides,
@@ -138,7 +143,7 @@ const normalizeUserThemeOptions = ({ palette, components, overrides, ...rest }:
138
143
  return result;
139
144
  };
140
145
 
141
- const defaultUserThemeOptions: UserThemeOptions = {
146
+ const defaultUxThemeOptions: UxThemeOptions = {
142
147
  themeName: 'ArcBlock',
143
148
  pageWidth: 'md',
144
149
  disableBlockletTheme: false,
@@ -166,13 +171,13 @@ const defaultUserThemeOptions: UserThemeOptions = {
166
171
  };
167
172
 
168
173
  // https://material-ui.com/customization/default-theme/
169
- export const create = (...args: Array<UserThemeOptions | ((config: Partial<Theme>) => UserThemeOptions)>) => {
174
+ export const create = (...args: Array<UxThemeOptions | ((baseTheme: Theme) => UxThemeOptions)>) => {
170
175
  const defaultPrefer = getDefaultThemePrefer();
171
- const getThemeConfig = lazyThemeConfig(defaultPrefer);
172
- const userThemeOptions = args.reduce<UserThemeOptions>(
176
+ const createBaseTheme = lazyCreateDefaultTheme(defaultPrefer);
177
+ const userThemeOptions = args.reduce<UxThemeOptions>(
173
178
  (acc, curr) =>
174
- deepmerge(acc, normalizeUserThemeOptions(typeof curr === 'function' ? curr(getThemeConfig()) : curr)),
175
- normalizeUserThemeOptions(defaultUserThemeOptions)
179
+ deepmerge(acc, normalizeUserThemeOptions(typeof curr === 'function' ? curr(createBaseTheme()) : curr)),
180
+ normalizeUserThemeOptions(defaultUxThemeOptions)
176
181
  );
177
182
  const prefer = userThemeOptions.mode || userThemeOptions.palette?.mode || defaultPrefer;
178
183
  const blockletThemeOptions = window.blocklet?.theme?.[prefer] ?? {};
@@ -195,6 +200,7 @@ export const create = (...args: Array<UserThemeOptions | ((config: Partial<Theme
195
200
 
196
201
  // 创建主题
197
202
  const theme = _createTheme(mergedThemeOptions);
203
+ theme.__isUxTheme__ = true;
198
204
 
199
205
  // 异步加载字体
200
206
  const fonts = collectFontFamilies(theme.typography);
@@ -1,12 +0,0 @@
1
- import { Locale } from '../type';
2
- type LoginButtonProps = {
3
- onClick: (options?: {
4
- openMode?: 'popup' | 'window';
5
- }) => void;
6
- render: (options: {
7
- onClick: () => void;
8
- }) => React.ReactNode;
9
- locale?: Locale;
10
- };
11
- export default function LoginButton({ onClick, render, locale }: LoginButtonProps): string | number | boolean | Iterable<import("react").ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
12
- export {};
@@ -1,74 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box } from '@mui/material';
3
- import { joinURL } from 'ufo';
4
- import { useRef, useState } from 'react';
5
- import { useMemoizedFn } from 'ahooks';
6
- import { useBrowser } from '@arcblock/react-hooks';
7
- import SharedBridge from '../SharedBridge';
8
- import { setVisitorId } from '../Util';
9
- import { getFederatedEnabled, getMaster } from '../Util/federated';
10
- import { callIframe } from '../Util/iframe';
11
- export default function LoginButton({
12
- onClick,
13
- render,
14
- locale
15
- }) {
16
- const blocklet = window?.blocklet;
17
- const federatedEnabled = getFederatedEnabled(blocklet);
18
- const masterSite = getMaster(blocklet);
19
- const sharedBridgeRef = useRef(null);
20
- const [hasStorageAccess, setHasStorageAccess] = useState(false);
21
- const browser = useBrowser();
22
- const handleClick = useMemoizedFn(() => {
23
- if (hasStorageAccess) {
24
- onClick({
25
- openMode: 'popup'
26
- });
27
- } else {
28
- onClick();
29
- }
30
- });
31
- const handleLoad = useMemoizedFn(async () => {
32
- const {
33
- value: visitorId
34
- } = await callIframe(sharedBridgeRef.current, 'getVisitorId');
35
- if (visitorId) {
36
- setHasStorageAccess(true);
37
- setVisitorId(visitorId);
38
- }
39
- });
40
- const handleClickBridge = useMemoizedFn(({
41
- value,
42
- visitorId
43
- }) => {
44
- if (visitorId) {
45
- setVisitorId(visitorId);
46
- }
47
- if (value) {
48
- onClick({
49
- openMode: 'popup'
50
- });
51
- } else {
52
- onClick();
53
- }
54
- });
55
- if (browser.arcSphere || browser.wallet) {
56
- return render({
57
- onClick
58
- });
59
- }
60
- return /*#__PURE__*/_jsxs(Box, {
61
- sx: {
62
- position: 'relative'
63
- },
64
- children: [render({
65
- onClick: handleClick
66
- }), masterSite?.appUrl && federatedEnabled ? /*#__PURE__*/_jsx(SharedBridge, {
67
- locale: locale,
68
- iframeRef: sharedBridgeRef,
69
- onLoad: handleLoad,
70
- onClick: handleClickBridge,
71
- src: joinURL(masterSite.appUrl, '/.well-known/service/share/shared-bridge.html')
72
- }) : null]
73
- });
74
- }