@arcblock/did-connect-react 3.1.0

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 (183) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +134 -0
  3. package/lib/Address/index.js +4 -0
  4. package/lib/Avatar/index.js +4 -0
  5. package/lib/Button/index.js +17 -0
  6. package/lib/Connect/assets/locale.js +143 -0
  7. package/lib/Connect/assets/login-bg.png +0 -0
  8. package/lib/Connect/assets/login-slogan.js +9 -0
  9. package/lib/Connect/components/action-button.js +26 -0
  10. package/lib/Connect/components/app-tips.js +132 -0
  11. package/lib/Connect/components/auto-height.js +31 -0
  12. package/lib/Connect/components/back-button.js +24 -0
  13. package/lib/Connect/components/connect-status.js +263 -0
  14. package/lib/Connect/components/did-connect-title.js +126 -0
  15. package/lib/Connect/components/download-tips.js +52 -0
  16. package/lib/Connect/components/loading.js +26 -0
  17. package/lib/Connect/components/login-item/connect-choose-list.js +249 -0
  18. package/lib/Connect/components/login-item/login-method-item.js +129 -0
  19. package/lib/Connect/components/login-item/mobile-login-item.js +114 -0
  20. package/lib/Connect/components/login-item/passkey-login-item.js +44 -0
  21. package/lib/Connect/components/login-item/web-login-item.js +97 -0
  22. package/lib/Connect/components/mask-overlay.js +34 -0
  23. package/lib/Connect/components/refresh-overlay.js +57 -0
  24. package/lib/Connect/components/switch-app.js +70 -0
  25. package/lib/Connect/contexts/state.js +142 -0
  26. package/lib/Connect/fullpage.js +5 -0
  27. package/lib/Connect/hooks/auth-url.js +23 -0
  28. package/lib/Connect/hooks/method-list.js +46 -0
  29. package/lib/Connect/hooks/page-show.js +17 -0
  30. package/lib/Connect/hooks/security.js +27 -0
  31. package/lib/Connect/hooks/token.js +305 -0
  32. package/lib/Connect/hooks/use-apps.js +19 -0
  33. package/lib/Connect/hooks/use-quick-connect.js +97 -0
  34. package/lib/Connect/index.js +498 -0
  35. package/lib/Connect/landing-page.js +5 -0
  36. package/lib/Connect/plugins/email/index.js +62 -0
  37. package/lib/Connect/plugins/email/list-item.js +28 -0
  38. package/lib/Connect/plugins/email/placeholder.js +283 -0
  39. package/lib/Connect/plugins/index.js +4 -0
  40. package/lib/Connect/use-connect.js +164 -0
  41. package/lib/Connect/with-blocklet.js +15 -0
  42. package/lib/Connect/with-bridge-call.js +108 -0
  43. package/lib/Federated/context.js +61 -0
  44. package/lib/Federated/index.js +7 -0
  45. package/lib/Logo/index.js +4 -0
  46. package/lib/OAuth/context.js +234 -0
  47. package/lib/OAuth/guest.svg.js +5 -0
  48. package/lib/OAuth/index.js +7 -0
  49. package/lib/OAuth/passport-switcher.js +114 -0
  50. package/lib/Passkey/actions.js +165 -0
  51. package/lib/Passkey/constants.js +4 -0
  52. package/lib/Passkey/context.js +266 -0
  53. package/lib/Passkey/dialog.js +277 -0
  54. package/lib/Passkey/icon.js +13 -0
  55. package/lib/Passkey/index.js +9 -0
  56. package/lib/Service/index.js +62 -0
  57. package/lib/Session/assets/did-spaces-guide-cover.svg.js +135 -0
  58. package/lib/Session/assets/did-spaces-guide-icon.svg.js +9 -0
  59. package/lib/Session/context.js +5 -0
  60. package/lib/Session/did-spaces-guide.js +136 -0
  61. package/lib/Session/hooks/use-federated.js +64 -0
  62. package/lib/Session/hooks/use-mobile.js +8 -0
  63. package/lib/Session/hooks/use-protected-routes.js +11 -0
  64. package/lib/Session/hooks/use-session-token.js +169 -0
  65. package/lib/Session/hooks/use-verify.js +45 -0
  66. package/lib/Session/index.js +896 -0
  67. package/lib/Session/libs/constants.js +15 -0
  68. package/lib/Session/libs/did-spaces.js +10 -0
  69. package/lib/Session/libs/federated.js +42 -0
  70. package/lib/Session/libs/index.js +15 -0
  71. package/lib/Session/libs/locales.js +161 -0
  72. package/lib/Session/libs/login-mobile.js +55 -0
  73. package/lib/Session/window-focus-aware.js +17 -0
  74. package/lib/SessionManager/index.js +4 -0
  75. package/lib/Storage/engine/cookie.js +21 -0
  76. package/lib/Storage/engine/local-storage.js +36 -0
  77. package/lib/Storage/index.js +23 -0
  78. package/lib/User/index.js +6 -0
  79. package/lib/User/use-did.js +59 -0
  80. package/lib/User/wrap-did.js +13 -0
  81. package/lib/WebWalletSWKeeper/index.js +5 -0
  82. package/lib/constant.js +22 -0
  83. package/lib/error.js +8 -0
  84. package/lib/hooks/use-locale.js +7 -0
  85. package/lib/index.js +33 -0
  86. package/lib/locales/en.js +17 -0
  87. package/lib/locales/index.js +10 -0
  88. package/lib/locales/zh.js +17 -0
  89. package/lib/package.json.js +7 -0
  90. package/lib/types.d.ts +355 -0
  91. package/lib/utils.js +214 -0
  92. package/package.json +84 -0
  93. package/src/Address/index.jsx +2 -0
  94. package/src/Avatar/index.jsx +2 -0
  95. package/src/Button/Button.stories.jsx +7 -0
  96. package/src/Button/index.jsx +21 -0
  97. package/src/Connect/Connect.stories.jsx +34 -0
  98. package/src/Connect/assets/locale.js +145 -0
  99. package/src/Connect/assets/login-bg.png +0 -0
  100. package/src/Connect/assets/login-slogan.js +7 -0
  101. package/src/Connect/components/action-button.jsx +22 -0
  102. package/src/Connect/components/app-tips.jsx +156 -0
  103. package/src/Connect/components/auto-height.jsx +38 -0
  104. package/src/Connect/components/back-button.jsx +23 -0
  105. package/src/Connect/components/connect-status.jsx +259 -0
  106. package/src/Connect/components/did-connect-title.jsx +106 -0
  107. package/src/Connect/components/download-tips.jsx +55 -0
  108. package/src/Connect/components/loading.jsx +25 -0
  109. package/src/Connect/components/login-item/connect-choose-list.jsx +304 -0
  110. package/src/Connect/components/login-item/login-method-item.jsx +118 -0
  111. package/src/Connect/components/login-item/mobile-login-item.jsx +179 -0
  112. package/src/Connect/components/login-item/passkey-login-item.jsx +52 -0
  113. package/src/Connect/components/login-item/web-login-item.jsx +149 -0
  114. package/src/Connect/components/mask-overlay.jsx +32 -0
  115. package/src/Connect/components/refresh-overlay.jsx +52 -0
  116. package/src/Connect/components/switch-app.jsx +69 -0
  117. package/src/Connect/contexts/state.jsx +219 -0
  118. package/src/Connect/fullpage.jsx +3 -0
  119. package/src/Connect/hooks/auth-url.js +31 -0
  120. package/src/Connect/hooks/method-list.js +121 -0
  121. package/src/Connect/hooks/page-show.js +24 -0
  122. package/src/Connect/hooks/security.js +40 -0
  123. package/src/Connect/hooks/token.js +639 -0
  124. package/src/Connect/hooks/use-apps.js +69 -0
  125. package/src/Connect/hooks/use-quick-connect.js +130 -0
  126. package/src/Connect/index.jsx +600 -0
  127. package/src/Connect/landing-page.jsx +3 -0
  128. package/src/Connect/plugins/email/index.jsx +82 -0
  129. package/src/Connect/plugins/email/list-item.jsx +31 -0
  130. package/src/Connect/plugins/email/placeholder.jsx +365 -0
  131. package/src/Connect/plugins/index.js +2 -0
  132. package/src/Connect/use-connect.jsx +321 -0
  133. package/src/Connect/with-blocklet.jsx +26 -0
  134. package/src/Connect/with-bridge-call.jsx +138 -0
  135. package/src/Federated/context.jsx +93 -0
  136. package/src/Federated/index.jsx +1 -0
  137. package/src/Logo/index.jsx +2 -0
  138. package/src/OAuth/context.jsx +346 -0
  139. package/src/OAuth/guest.svg +20 -0
  140. package/src/OAuth/index.jsx +1 -0
  141. package/src/OAuth/passport-switcher.jsx +133 -0
  142. package/src/Passkey/actions.jsx +212 -0
  143. package/src/Passkey/constants.js +2 -0
  144. package/src/Passkey/context.jsx +381 -0
  145. package/src/Passkey/dialog.jsx +391 -0
  146. package/src/Passkey/icon.jsx +10 -0
  147. package/src/Passkey/index.jsx +2 -0
  148. package/src/Service/index.jsx +96 -0
  149. package/src/Session/assets/did-spaces-guide-cover.svg +128 -0
  150. package/src/Session/assets/did-spaces-guide-icon.svg +7 -0
  151. package/src/Session/context.jsx +7 -0
  152. package/src/Session/did-spaces-guide.jsx +173 -0
  153. package/src/Session/hooks/use-federated.js +88 -0
  154. package/src/Session/hooks/use-mobile.jsx +6 -0
  155. package/src/Session/hooks/use-protected-routes.js +16 -0
  156. package/src/Session/hooks/use-session-token.js +365 -0
  157. package/src/Session/hooks/use-verify.jsx +76 -0
  158. package/src/Session/index.jsx +1687 -0
  159. package/src/Session/libs/constants.js +14 -0
  160. package/src/Session/libs/did-spaces.js +38 -0
  161. package/src/Session/libs/federated.js +79 -0
  162. package/src/Session/libs/index.js +5 -0
  163. package/src/Session/libs/locales.js +160 -0
  164. package/src/Session/libs/login-mobile.js +80 -0
  165. package/src/Session/window-focus-aware.jsx +28 -0
  166. package/src/SessionManager/index.jsx +2 -0
  167. package/src/Storage/engine/cookie.js +23 -0
  168. package/src/Storage/engine/local-storage.js +55 -0
  169. package/src/Storage/index.js +25 -0
  170. package/src/User/index.js +4 -0
  171. package/src/User/use-did.js +80 -0
  172. package/src/User/wrap-did.jsx +18 -0
  173. package/src/WebWalletSWKeeper/index.jsx +3 -0
  174. package/src/constant.js +26 -0
  175. package/src/error.js +6 -0
  176. package/src/hooks/use-locale.jsx +6 -0
  177. package/src/index.js +43 -0
  178. package/src/locales/en.jsx +15 -0
  179. package/src/locales/index.jsx +13 -0
  180. package/src/locales/zh.jsx +15 -0
  181. package/src/types.d.ts +355 -0
  182. package/src/utils.js +395 -0
  183. package/vite.config.mjs +29 -0
@@ -0,0 +1,259 @@
1
+ import { isValidElement } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Box, Tooltip, Typography, useTheme } from '@mui/material';
4
+ import { Icon } from '@iconify/react';
5
+ import closeRoundedIcon from '@iconify-icons/material-symbols/close-rounded';
6
+ import hourglassEmptyRoundedIcon from '@iconify-icons/material-symbols/hourglass-empty-rounded';
7
+ import ruleSettingsRoundedIcon from '@iconify-icons/material-symbols/rule-settings-rounded';
8
+ import LoadingMask from '@arcblock/ux/lib/LoadingMask';
9
+ import Success from '@arcblock/ux/lib/Success';
10
+ import noop from 'lodash/noop';
11
+ import { useMemoizedFn } from 'ahooks';
12
+ import { translate } from '@arcblock/ux/lib/Locale/util';
13
+ import ProviderIcon from '@arcblock/ux/lib/DIDConnect/provider-icon';
14
+ import { LOGIN_PROVIDER } from '@arcblock/ux/lib/Util/constant';
15
+
16
+ import translations from '../assets/locale';
17
+ import ActionButton from './action-button';
18
+ import BackButton from './back-button';
19
+
20
+ function BaseStatus({ icon = null, title = '', color = '', description = '', extraContent = null, actions = null }) {
21
+ const { palette } = useTheme();
22
+ const fgColor = color || palette.grey[700];
23
+
24
+ return (
25
+ <Box
26
+ sx={{
27
+ display: 'flex',
28
+ flexDirection: 'column',
29
+ alignItems: 'center',
30
+ justifyContent: 'center',
31
+ gap: 1.5,
32
+ }}>
33
+ {isValidElement(icon) ? (
34
+ icon
35
+ ) : (
36
+ <Box
37
+ sx={{
38
+ backgroundColor: fgColor,
39
+ borderRadius: '100%',
40
+ fontSize: 0,
41
+ }}>
42
+ <Icon
43
+ icon={icon}
44
+ fontSize={52}
45
+ style={{
46
+ transform: 'scale(0.7)',
47
+ color: palette.primary.contrastText,
48
+ }}
49
+ />
50
+ </Box>
51
+ )}
52
+
53
+ <Box sx={{ textAlign: 'center' }}>
54
+ <Typography
55
+ variant="h6"
56
+ sx={{
57
+ fontWeight: 500,
58
+ color: fgColor,
59
+ }}>
60
+ {title}
61
+ </Typography>
62
+ <Tooltip title={description} placement="top">
63
+ <Typography
64
+ variant="body2"
65
+ sx={{
66
+ color: 'text.secondary',
67
+ overflow: 'hidden',
68
+ display: '-webkit-box',
69
+ '-webkit-box-orient': 'vertical',
70
+ '-webkit-line-clamp': '3',
71
+ whiteSpace: 'pre-wrap',
72
+ wordBreak: 'break-word',
73
+ }}>
74
+ {description}
75
+ </Typography>
76
+ </Tooltip>
77
+ </Box>
78
+ {extraContent}
79
+ <Box>{actions}</Box>
80
+ </Box>
81
+ );
82
+ }
83
+
84
+ BaseStatus.propTypes = {
85
+ icon: PropTypes.any,
86
+ title: PropTypes.string,
87
+ color: PropTypes.string,
88
+ description: PropTypes.string,
89
+ extraContent: PropTypes.node,
90
+ actions: PropTypes.node,
91
+ };
92
+
93
+ function MfaCode({ title = '', mfaCode = 0 }) {
94
+ return (
95
+ <Box
96
+ className="status-mfa"
97
+ sx={{
98
+ display: 'flex',
99
+ flexDirection: 'column',
100
+ justifyContent: 'center',
101
+ alignItems: 'center',
102
+ border: '1px solid',
103
+ borderColor: 'grey.200',
104
+ borderRadius: 1,
105
+ maxWidth: '360px',
106
+ backgroundColor: 'transparent',
107
+ p: 1,
108
+ }}>
109
+ <Box
110
+ className="status-mfa-tip"
111
+ sx={{
112
+ textAlign: 'center',
113
+ textWrap: 'balance',
114
+ }}>
115
+ {title}
116
+ </Box>
117
+ <Typography
118
+ className="status-mfa-code"
119
+ sx={{
120
+ mt: 1,
121
+ lineHeight: 1,
122
+ fontSize: '36px',
123
+ fontWeight: 700,
124
+ letterSpacing: 1,
125
+ }}>
126
+ {mfaCode}
127
+ </Typography>
128
+ </Box>
129
+ );
130
+ }
131
+ MfaCode.propTypes = {
132
+ title: PropTypes.string,
133
+ mfaCode: PropTypes.number,
134
+ };
135
+
136
+ /**
137
+ * Status (scanned/succeed/error/busy)
138
+ */
139
+ export default function ConnectStatus({
140
+ status = '',
141
+ nextWorkflow = '',
142
+ mfaCode = 0,
143
+ onCancel = noop,
144
+ onRetry = noop,
145
+ onClose = noop,
146
+ messages,
147
+ locale = 'en',
148
+ isFullScreen = false,
149
+ loadingIcon = null,
150
+ chooseMethod = 'DID Wallet',
151
+ hideRetry = false,
152
+ hideBack = false,
153
+ ...rest
154
+ }) {
155
+ const t = useMemoizedFn((key, data = {}) => {
156
+ return translate(translations, key, locale, 'en', data);
157
+ });
158
+ const { palette } = useTheme();
159
+ const closeButton = (
160
+ <ActionButton sx={{ color: 'text.secondary' }} onClick={onClose}>
161
+ {t('close')}
162
+ </ActionButton>
163
+ );
164
+
165
+ return (
166
+ <Box
167
+ {...rest}
168
+ sx={{
169
+ p: 2,
170
+ minHeight: 200,
171
+ ...rest.sx,
172
+ }}>
173
+ {status === 'scanned' && !nextWorkflow && (
174
+ <BaseStatus
175
+ icon={
176
+ <LoadingMask size={52} borderRadius={12}>
177
+ {loadingIcon || <ProviderIcon provider={LOGIN_PROVIDER.DID_WALLET} width="100%" height="100%" />}
178
+ </LoadingMask>
179
+ }
180
+ title={t('requestConnect')}
181
+ description={t('continueInWallet', { method: chooseMethod })}
182
+ extraContent={mfaCode > 0 && <MfaCode mfaCode={mfaCode} title={t('mfaCode')} />}
183
+ actions={hideBack ? closeButton : <BackButton onClick={onCancel} />}
184
+ />
185
+ )}
186
+ {status === 'scanned' && !!nextWorkflow && (
187
+ <BaseStatus
188
+ color={palette.secondary.main}
189
+ icon={hourglassEmptyRoundedIcon}
190
+ title={t('wait')}
191
+ description={t('waiting')}
192
+ extraContent={mfaCode > 0 && <MfaCode mfaCode={mfaCode} title={t('mfaCode')} />}
193
+ actions={hideBack ? closeButton : <BackButton onClick={onCancel} />}
194
+ />
195
+ )}
196
+ {status === 'succeed' && (
197
+ <BaseStatus
198
+ color="success.light"
199
+ icon={<Success size={52} borderWidth={3} />}
200
+ title={t('success')}
201
+ description={messages.success}
202
+ actions={isFullScreen ? null : closeButton}
203
+ />
204
+ )}
205
+ {status === 'error' && (
206
+ <BaseStatus
207
+ color={palette.error.main}
208
+ icon={closeRoundedIcon}
209
+ title={t('failed')}
210
+ description={messages.error || t('error')}
211
+ actions={
212
+ <Box sx={{ display: 'flex', gap: 1 }}>
213
+ {hideBack ? closeButton : <BackButton onClick={onCancel} />}
214
+ {hideRetry ? null : (
215
+ <ActionButton
216
+ onClick={onRetry}
217
+ sx={{
218
+ color: 'primary.main',
219
+ borderColor: 'primary.light',
220
+ }}>
221
+ {t('retry')}
222
+ </ActionButton>
223
+ )}
224
+ </Box>
225
+ }
226
+ />
227
+ )}
228
+ {status === 'busy' && (
229
+ <BaseStatus
230
+ color="warning.main"
231
+ icon={ruleSettingsRoundedIcon}
232
+ title={t('busyTitle')}
233
+ description={messages.error || t('busyDesc')}
234
+ actions={hideBack ? closeButton : <BackButton onClick={onCancel} />}
235
+ />
236
+ )}
237
+ </Box>
238
+ );
239
+ }
240
+
241
+ ConnectStatus.propTypes = {
242
+ status: PropTypes.string,
243
+ nextWorkflow: PropTypes.string,
244
+ mfaCode: PropTypes.number,
245
+ onCancel: PropTypes.func,
246
+ onRetry: PropTypes.func,
247
+ onClose: PropTypes.func,
248
+ messages: PropTypes.shape({
249
+ confirm: PropTypes.string.isRequired,
250
+ success: PropTypes.any.isRequired,
251
+ error: PropTypes.any.isRequired,
252
+ }).isRequired,
253
+ locale: PropTypes.oneOf(['en', 'zh']),
254
+ isFullScreen: PropTypes.bool,
255
+ loadingIcon: PropTypes.any,
256
+ chooseMethod: PropTypes.string,
257
+ hideRetry: PropTypes.bool,
258
+ hideBack: PropTypes.bool,
259
+ };
@@ -0,0 +1,106 @@
1
+ import { useState } from 'react';
2
+ import { Icon } from '@iconify/react';
3
+ import { Box, Tooltip, Typography } from '@mui/material';
4
+ import infoOutlineRoundedIcon from '@iconify-icons/material-symbols/info-outline-rounded';
5
+ import swapHorizRoundedIcon from '@iconify-icons/material-symbols/swap-horiz-rounded';
6
+ import PropTypes from 'prop-types';
7
+ import SwitchApp from './switch-app';
8
+
9
+ export default function DIDConnectTitle({ title, description, extraContent = null, disableSwitchApp = false }) {
10
+ const [showSwitch, setShowSwitch] = useState(false);
11
+
12
+ return (
13
+ <Box
14
+ sx={{
15
+ display: 'flex',
16
+ flexDirection: 'column',
17
+ gap: 0.5,
18
+ }}>
19
+ <Typography
20
+ component="h1"
21
+ variant="h4"
22
+ sx={{
23
+ color: 'text.primary',
24
+ fontWeight: 700,
25
+ fontFamily: 'Lexend',
26
+ display: 'flex',
27
+ alignItems: 'center',
28
+ gap: 0.5,
29
+ }}
30
+ onClick={(e) => {
31
+ if (disableSwitchApp) return;
32
+ // HACK: 连续点击三次才触发
33
+ if (e.detail > 2) {
34
+ setShowSwitch(true);
35
+ }
36
+ }}>
37
+ {title}
38
+ <SwitchApp
39
+ sx={{
40
+ fontSize: 0,
41
+ display: showSwitch ? 'block' : 'none',
42
+ }}>
43
+ <Icon
44
+ icon={swapHorizRoundedIcon}
45
+ style={{
46
+ fontSize: '14px',
47
+ }}
48
+ />
49
+ </SwitchApp>
50
+ </Typography>
51
+ <Typography
52
+ variant="body2"
53
+ sx={{
54
+ color: 'text.secondary',
55
+ fontFamily: 'Lexend',
56
+ }}>
57
+ {description}
58
+ {extraContent ? (
59
+ <Tooltip
60
+ title={extraContent}
61
+ arrow
62
+ slotProps={{
63
+ tooltip: {
64
+ sx: {
65
+ '&>.MuiTypography-root': {
66
+ color: 'primary.contrastText',
67
+ fontFamily: 'Lexend',
68
+ },
69
+ },
70
+ },
71
+ popper: {
72
+ modifiers: [
73
+ {
74
+ name: 'offset',
75
+ options: {
76
+ offset: [0, -8],
77
+ },
78
+ },
79
+ ],
80
+ },
81
+ }}>
82
+ <Box
83
+ component={Icon}
84
+ icon={infoOutlineRoundedIcon}
85
+ sx={{
86
+ fontSize: 14,
87
+ display: 'inline-block',
88
+ verticalAlign: 'middle',
89
+ ml: 0.5,
90
+ cursor: 'pointer',
91
+ transform: 'translateY(-1px)',
92
+ }}
93
+ />
94
+ </Tooltip>
95
+ ) : null}
96
+ </Typography>
97
+ </Box>
98
+ );
99
+ }
100
+
101
+ DIDConnectTitle.propTypes = {
102
+ title: PropTypes.string.isRequired,
103
+ description: PropTypes.string.isRequired,
104
+ extraContent: PropTypes.any,
105
+ disableSwitchApp: PropTypes.bool,
106
+ };
@@ -0,0 +1,55 @@
1
+ import { Box, Tooltip } from '@mui/material';
2
+ import { useCreation } from 'ahooks';
3
+ import { mergeSx } from '@arcblock/ux/lib/Util/style';
4
+
5
+ import { useStateContext } from '../contexts/state';
6
+
7
+ export default function DownloadTips({ ...rest }) {
8
+ const { t, locale } = useStateContext();
9
+ const downloadUrl = useCreation(() => {
10
+ if (['zh', 'en'].includes) {
11
+ return `https://www.didwallet.io/${locale}`;
12
+ }
13
+ return 'https://www.didwallet.io/en';
14
+ }, [locale]);
15
+
16
+ const tips = t('downloadTips');
17
+
18
+ return (
19
+ <Tooltip
20
+ title={tips}
21
+ arrow
22
+ placement="top"
23
+ slotProps={{
24
+ popper: {
25
+ modifiers: [
26
+ {
27
+ name: 'offset',
28
+ options: {
29
+ offset: [0, -8],
30
+ },
31
+ },
32
+ ],
33
+ },
34
+ }}>
35
+ <Box
36
+ component="a"
37
+ href={downloadUrl}
38
+ target="_blank"
39
+ rel="noopener"
40
+ {...rest}
41
+ sx={mergeSx(
42
+ {
43
+ color: 'primary.main',
44
+ textDecoration: 'none',
45
+ '&:hover': {
46
+ textDecoration: 'dashed underline',
47
+ },
48
+ },
49
+ rest?.sx
50
+ )}>
51
+ DID Wallet
52
+ </Box>
53
+ </Tooltip>
54
+ );
55
+ }
@@ -0,0 +1,25 @@
1
+ /* eslint-disable react/require-default-props */
2
+ import { Box, CircularProgress } from '@mui/material';
3
+ import PropTypes from 'prop-types';
4
+
5
+ // HACK: 默认的 size 是精心调整过的,不要随意更改
6
+ export default function Loading({ size = 92.5, loadingSize = 30 }) {
7
+ return (
8
+ <Box
9
+ sx={{
10
+ height: '100%',
11
+ minWidth: size,
12
+ minHeight: size,
13
+ display: 'flex',
14
+ justifyContent: 'center',
15
+ alignItems: 'center',
16
+ }}>
17
+ <CircularProgress size={loadingSize} sx={{ color: 'secondary.main' }} />
18
+ </Box>
19
+ );
20
+ }
21
+
22
+ Loading.propTypes = {
23
+ size: PropTypes.number,
24
+ loadingSize: PropTypes.number,
25
+ };