@arcblock/did-connect-react 3.3.10 → 3.4.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.
@@ -0,0 +1,47 @@
1
+ import { DIDConnectFooter } from '@arcblock/ux/lib/DIDConnect';
2
+ import { DID_CONNECT_SMALL_WIDTH } from '@arcblock/ux/lib/Util/constant';
3
+ import { getCurrentApp } from '@arcblock/ux/lib/Util/federated';
4
+ import { Box, Skeleton } from '@mui/material';
5
+
6
+ export default function FallbackConnect(props) {
7
+ const currentAppInfo = globalThis.blocklet ? getCurrentApp(globalThis.blocklet) : globalThis.env;
8
+ return (
9
+ <Box
10
+ className="did-connect__root"
11
+ sx={{
12
+ backgroundColor: 'background.default',
13
+ display: 'flex',
14
+ flexDirection: 'column',
15
+ height: '100%',
16
+ position: 'relative',
17
+ maxWidth: '100%',
18
+ // eslint-disable-next-line react/prop-types
19
+ width: props.mode === 'drawer' ? '100%' : DID_CONNECT_SMALL_WIDTH - 20,
20
+ transition: 'width 0.2s ease-in-out',
21
+ margin: 'auto',
22
+ p: 3,
23
+ pb: 0,
24
+ gap: 2.5,
25
+ }}>
26
+ <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
27
+ <Skeleton variant="rounded" height={28} sx={{ width: '6rem' }} />
28
+ <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
29
+ <Skeleton variant="rounded" sx={{ fontSize: '13px', height: '15px' }} />
30
+ <Skeleton variant="rounded" sx={{ fontSize: '13px', height: '15px', width: '3rem' }} />
31
+ </Box>
32
+ </Box>
33
+ <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
34
+ <Skeleton variant="rounded" sx={{ height: '35px' }} />
35
+ <Skeleton variant="rounded" sx={{ height: '35px' }} />
36
+ <Skeleton variant="rounded" sx={{ height: '35px' }} />
37
+ <Box sx={{ display: 'flex', gap: 1.5, mt: 1 }}>
38
+ <Skeleton variant="rounded" sx={{ flex: 1, height: '32px' }} />
39
+ <Skeleton variant="rounded" sx={{ flex: 1, height: '32px' }} />
40
+ <Skeleton variant="rounded" sx={{ flex: 1, height: '32px' }} />
41
+ <Skeleton variant="rounded" sx={{ flex: 1, height: '32px' }} />
42
+ </Box>
43
+ </Box>
44
+ <DIDConnectFooter currentAppInfo={currentAppInfo} />
45
+ </Box>
46
+ );
47
+ }
@@ -3,6 +3,7 @@ import { useCreation, useRequest } from 'ahooks';
3
3
  import isNil from 'lodash/isNil';
4
4
  import { LOGIN_PROVIDER } from '@arcblock/ux/lib/Util/constant';
5
5
  import { getBlockletData, getFederatedEnabled, getMaster } from '@arcblock/ux/lib/Util/federated';
6
+ import { useState } from 'react';
6
7
 
7
8
  const getAuthenticationConfig = async ({ sourceAppPid }) => {
8
9
  const blocklet = globalThis?.blocklet;
@@ -56,12 +57,15 @@ export default function useProviderList({
56
57
  blocklet = globalThis.blocklet,
57
58
  isSmallView = false,
58
59
  }) {
60
+ const [loadingProviderList, setLoadingProviderList] = useState(false);
59
61
  const actionList = ['login', 'invite', 'connect-to-did-space', 'connect-to-did-domain', 'destroy-self'];
60
62
  const browser = useBrowser();
61
63
 
62
64
  const { data: loginProviderList = [] } = useRequest(
63
65
  async () => {
66
+ setLoadingProviderList(true);
64
67
  const data = await getLoginProviderList({ sourceAppPid });
68
+ setLoadingProviderList(false);
65
69
  return data;
66
70
  },
67
71
  { refreshDeps: [sourceAppPid] }
@@ -121,6 +125,7 @@ export default function useProviderList({
121
125
  hideChooseList,
122
126
  hideQRCode,
123
127
  providerList: showedLoginProviderList,
128
+ loadingProviderList,
124
129
  };
125
130
 
126
131
  return result;
@@ -1,618 +1,21 @@
1
- import { use, useEffect, useRef, useState } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { Box, Divider, Skeleton } from '@mui/material';
4
- import {
5
- useCreation,
6
- useDebounceFn,
7
- useMemoizedFn,
8
- useMount,
9
- usePrevious,
10
- useSize,
11
- useUpdate,
12
- useUpdateEffect,
13
- } from 'ahooks';
14
- import noop from 'lodash/noop';
15
- import isUndefined from 'lodash/isUndefined';
16
-
17
- import CloseButton from '@arcblock/ux/lib/CloseButton';
18
- import {
19
- LOGIN_PROVIDER,
20
- LOGIN_PROVIDER_NAME,
21
- OAUTH_PROVIDER,
22
- DID_CONNECT_MEDIUM_WIDTH,
23
- DID_CONNECT_SMALL_WIDTH,
24
- } from '@arcblock/ux/lib/Util/constant';
25
- import QRCode from '@arcblock/ux/lib/QRCode';
26
- import { DIDConnectFooter, withContainer, withUxTheme } from '@arcblock/ux/lib/DIDConnect';
27
- import { useTheme } from '@arcblock/ux/lib/Theme';
28
- import ProviderIcon from '@arcblock/ux/lib/DIDConnect/provider-icon';
29
-
30
- import '@fontsource/lexend/400.css';
31
- import '@fontsource/lexend/600.css';
1
+ import { lazy, Suspense } from 'react';
2
+ import { withContainer, withUxTheme } from '@arcblock/ux/lib/DIDConnect';
32
3
 
33
4
  import withBlocklet from './with-blocklet';
34
5
  import withBridgeCall from './with-bridge-call';
35
6
  import useSecurity from './hooks/security';
7
+ import FallbackConnect from './fallback-connect';
36
8
 
37
- import { SessionContext } from '../Session/context';
38
- import { StateProvider, useStateContext } from './contexts/state';
39
- import ConnectProviderList from './components/login-item/connect-provider-list';
40
- import AutoHeight from './components/auto-height';
41
- import useToken from './hooks/token';
42
- import { useOAuth } from '../OAuth';
43
- import ConnectStatus from './components/connect-status';
44
- import { usePasskey } from '../Passkey/context';
45
- import { API_DID_PREFIX, DEFAULT_TIMEOUT, BUSY_STATUS, CHECK_STATUS_INTERVAL } from '../constant';
46
- import { getWebWalletUrl } from '../utils';
47
- import DIDConnectTitle from './components/did-connect-title';
48
- import DownloadTips from './components/download-tips';
49
- import useProviderList from './hooks/provider-list';
50
- import useAuthUrl from './hooks/auth-url';
51
- import { getWalletDid } from '../User/use-did';
52
-
53
- function Connect({
54
- hideCloseButton = false,
55
- mode = 'dialog',
56
- action,
57
- baseUrl = '',
58
- checkFn,
59
- checkInterval = CHECK_STATUS_INTERVAL,
60
- checkTimeout = DEFAULT_TIMEOUT * 1000,
61
- prefix = API_DID_PREFIX,
62
- tokenKey = '_t_',
63
- locale = 'en',
64
- encKey = '_ek_',
65
- autoConnect = true,
66
- forceConnected = true,
67
- saveConnect = true,
68
- useSocket = true,
69
- allowWallet = true,
70
- provider = '',
71
- messages = {},
72
- passkeyBehavior = 'none',
73
- webWalletUrl = getWebWalletUrl(),
74
- enabledConnectTypes = ['web', 'mobile', ...Object.keys(OAUTH_PROVIDER)],
75
- extraContent = null,
76
- disableSwitchApp = false,
77
- magicToken = undefined,
78
- customItems = [],
79
- onClose = noop,
80
- onError = noop,
81
- onSuccess = noop,
82
- onRecreateSession = noop,
83
- setColor = noop,
84
- }) {
85
- const theme = useTheme();
86
- const forceUpdate = useUpdate();
87
- const sessionCtx = use(SessionContext);
88
- const currentUserDid = getWalletDid(sessionCtx?.session?.user);
89
-
90
- const {
91
- t,
92
- staticState,
93
- connectState,
94
- extraParams,
95
- currentAppInfo,
96
- currentAppColor,
97
- // 插件相关
98
- selectedPlugin,
99
- blocklet,
100
- masterBlocklet,
101
- showWalletOptions,
102
- setShowWalletOptions,
103
- } = useStateContext();
104
- const { state, generate, cancelWhenScanned } = useToken({
105
- action,
106
- baseUrl,
107
- checkFn,
108
- checkInterval,
109
- checkTimeout,
110
- extraParams,
111
- prefix,
112
- onError,
113
- onSuccess,
114
- locale,
115
- tokenKey,
116
- encKey,
117
- autoConnect,
118
- forceConnected: forceConnected === true ? currentUserDid || true : forceConnected,
119
- saveConnect,
120
- useSocket,
121
- allowWallet,
122
- provider,
123
- });
124
- const refreshingToken = useRef(false);
125
- const rootRef = useRef(null);
126
- const size = useSize(rootRef);
127
- const isSmallView = useCreation(() => {
128
- if (size) {
129
- return size.width < DID_CONNECT_MEDIUM_WIDTH - 50;
130
- }
131
- return true;
132
- }, [size, size?.width]);
133
-
134
- const [isInitSmallView, setIsInitSmallView] = useState(false);
135
-
136
- useMount(() => {
137
- setIsInitSmallView(size?.width < DID_CONNECT_MEDIUM_WIDTH - 50);
138
- });
139
-
140
- const { oauthState, setBaseUrl } = useOAuth();
141
- const { passkeyState, setTargetAppPid } = usePasskey();
142
-
143
- useMount(() => {
144
- setBaseUrl(baseUrl);
145
- setTargetAppPid(blocklet?.appPid);
146
- // 每次打开 did-connect,都重置状态
147
- state.reset();
148
- oauthState.reset();
149
- passkeyState.reset();
150
- });
151
-
152
- useEffect(() => {
153
- setColor(currentAppColor);
154
- // eslint-disable-next-line react-hooks/exhaustive-deps
155
- }, [currentAppColor]);
156
-
157
- const statusMessages = useCreation(() => {
158
- return {
159
- confirm: messages.confirm,
160
- success: messages.success,
161
- error: selectedPlugin?.state?.error || state.error || passkeyState.error || oauthState.error || '',
162
- };
163
- }, [
164
- messages.confirm,
165
- messages.success,
166
- state.error,
167
- oauthState.error,
168
- passkeyState.error,
169
- selectedPlugin?.state?.error,
170
- ]);
171
-
172
- const showStatus = useCreation(() => {
173
- return (
174
- BUSY_STATUS.includes(passkeyState.status) ||
175
- BUSY_STATUS.includes(oauthState.status) ||
176
- BUSY_STATUS.includes(state.status) ||
177
- BUSY_STATUS.includes(selectedPlugin?.state?.computedStatus)
178
- );
179
- }, [state.status, oauthState.status, passkeyState.status, selectedPlugin?.state?.computedStatus]);
180
-
181
- const handleReset = useMemoizedFn(async () => {
182
- onRecreateSession();
183
- oauthState.reset();
184
- passkeyState.reset();
185
- await generate(false);
186
- });
187
- const handleRetry = useMemoizedFn(() => {
188
- connectState?.retryConnect();
189
- });
190
- const handleCancel = useMemoizedFn(() => {
191
- onRecreateSession();
192
- oauthState.reset();
193
- passkeyState.reset();
194
- selectedPlugin?.state?.reset();
195
- staticState.current.cancelCount++;
196
- cancelWhenScanned();
197
- });
198
-
199
- const { run: debounceHandleTimeout } = useDebounceFn(
200
- () => {
201
- if (refreshingToken.current) return;
202
- if (state.status === 'timeout') {
203
- refreshingToken.current = true;
204
- state.reset();
205
- handleReset();
206
- refreshingToken.current = false;
207
- }
208
- },
209
- { leading: true, trailing: false }
210
- );
211
- // eslint-disable-next-line react-hooks/exhaustive-deps
212
- useEffect(debounceHandleTimeout, [state.status]);
213
-
214
- const chooseMethod = useCreation(() => {
215
- return LOGIN_PROVIDER_NAME[connectState.chooseMethod] || 'DID Wallet';
216
- }, [connectState.chooseMethod]);
217
-
218
- const { providerList, hideQRCode, hideChooseList } = useProviderList({
219
- action: state.action,
220
- sourceAppPid: connectState?.sourceAppPid,
221
- allowWallet,
222
- passkeyBehavior,
223
- webWalletUrl,
224
- mode,
225
- blocklet: connectState?.sourceAppPid ? masterBlocklet : blocklet,
226
- isSmallView,
227
- });
228
-
229
- const prevSourceAppPid = usePrevious(connectState?.sourceAppPid);
230
-
231
- // 切换了当前展示的应用后,需要重新生成二维码
232
- useUpdateEffect(() => {
233
- // HACK: connectState.sourceAppPid 是用户在页面中执行操作修改的值,最开始的时候就是 undefined,并在 did-connect 页面加载后,会由 app-info 触发一次更新(无论如何都会触发,这一次更新不应该触发 generate)
234
- if (isUndefined(prevSourceAppPid)) {
235
- return;
236
- }
237
- generate();
238
- }, [connectState?.sourceAppPid]);
239
-
240
- const getSpacingNumber = (value) => {
241
- const spacingValue = theme.spacing(value);
242
- return parseInt(spacingValue, 10);
243
- };
244
- const closeButton = useCreation(() => {
245
- return hideCloseButton ? null : (
246
- <CloseButton
247
- onClose={onClose}
248
- sx={{
249
- position: 'absolute',
250
- right: 14,
251
- top: 14,
252
- }}
253
- />
254
- );
255
- }, [hideCloseButton, onClose]);
256
-
257
- let content = null;
258
- if (showStatus) {
259
- content = (
260
- <Box
261
- sx={{
262
- flex: 1,
263
- display: 'flex',
264
- alignItems: 'center',
265
- justifyContent: 'center',
266
- }}>
267
- <Box>
268
- <ConnectStatus
269
- status={selectedPlugin?.state?.computedStatus || oauthState.status || passkeyState.status || state.status}
270
- nextWorkflow={state.nextWorkflow}
271
- mfaCode={state.mfaCode}
272
- onCancel={handleCancel}
273
- onRetry={handleRetry}
274
- onClose={onClose}
275
- messages={statusMessages}
276
- locale={locale}
277
- className="did-connect__auth-status auth-status"
278
- loadingIcon={
279
- connectState.chooseMethod ? (
280
- <ProviderIcon provider={connectState.chooseMethod} sx={{ color: 'text.primary' }} />
281
- ) : null
282
- }
283
- chooseMethod={chooseMethod}
284
- hideRetry={connectState.chooseMethod === 'email'}
285
- hideBack={!!magicToken}
286
- />
287
- </Box>
288
- </Box>
289
- );
290
- }
291
-
292
- const urlWithParams = useAuthUrl({ disableSwitchApp, tokenState: state });
293
-
294
- // 防止二维码抖动,使用 useCreation 进行缓存
295
- const qrcode = useCreation(() => {
296
- const backgroundColor = theme.mode === 'dark' ? theme.palette.grey[600] : 'white';
297
-
298
- let qrcodeSize = hideChooseList ? 240 - getSpacingNumber(3) * 2 : 196 - getSpacingNumber(2) * 2;
299
- let padding = hideChooseList ? 3 : 2;
300
- // 如果显示钱包登录,将 download tips 移动到顶部,调整间距,增加二维码的尺寸和内边距
301
- if (showWalletOptions) {
302
- padding = 1;
303
- qrcodeSize += getSpacingNumber(padding) * 2;
304
- }
305
- return (
306
- <Box
307
- className="did-connect__qrcode"
308
- sx={{
309
- p: padding,
310
- width: (hideChooseList ? 240 : 196) + getSpacingNumber(1) * 2,
311
- height: (hideChooseList ? 240 : 196) + getSpacingNumber(1) * 2,
312
- }}>
313
- {state.url ? (
314
- <QRCode
315
- data={urlWithParams}
316
- size={qrcodeSize}
317
- sx={{
318
- width: qrcodeSize + getSpacingNumber(1) * 2,
319
- height: qrcodeSize + getSpacingNumber(1) * 2,
320
- flex: 1,
321
- backgroundColor,
322
- p: 1,
323
- fontSize: 0,
324
- textAlign: 'center',
325
- boxSizing: 'border-box',
326
- borderRadius: 1,
327
- border: '1px solid',
328
- borderColor: 'divider',
329
- }}
330
- config={{
331
- backgroundOptions: {
332
- color: backgroundColor,
333
- },
334
- }}
335
- />
336
- ) : (
337
- <Skeleton
338
- animation="wave"
339
- variant="rectangular"
340
- sx={{
341
- position: 'absolute',
342
- left: getSpacingNumber(2) + 1,
343
- right: getSpacingNumber(2) + 1,
344
- top: getSpacingNumber(2) + 1,
345
- bottom: getSpacingNumber(2) + 1,
346
- borderRadius: 1,
347
- zIndex: 1,
348
- width: 'auto',
349
- height: 'auto',
350
- }}
351
- />
352
- )}
353
- </Box>
354
- );
355
- }, [urlWithParams, hideChooseList, showWalletOptions]);
356
-
357
- const didConnectFlexDirection = useCreation(() => {
358
- if (hideChooseList) {
359
- return 'column-reverse';
360
- }
361
- if (!hideQRCode && isInitSmallView) {
362
- return 'column';
363
- }
364
- return 'row';
365
- }, [hideChooseList, isInitSmallView, hideQRCode]);
366
-
367
- const qrcodeContent = useCreation(() => {
368
- if (!qrcode) return null;
369
- return (
370
- <Box
371
- sx={{
372
- display: 'flex',
373
- alignItems: 'center',
374
- overflowX: 'auto',
375
- overflowY: 'visible',
376
- maxWidth: '100%',
377
- margin: 'auto',
378
- }}>
379
- <Box
380
- sx={{
381
- fontSize: 0,
382
- position: 'relative',
383
- ...(showWalletOptions
384
- ? {
385
- mt: hideChooseList ? 4 : 2.5,
386
- mb: hideChooseList ? 0 : 0,
387
- }
388
- : {
389
- mb: hideChooseList ? 4 : 2.5,
390
- mt: 0,
391
- }),
392
- }}>
393
- {qrcode}
394
- <Box
395
- sx={{
396
- position: 'absolute',
397
- color: 'text.secondary',
398
- fontSize: 12,
399
- zIndex: 1,
400
- whiteSpace: 'nowrap',
401
- ...(showWalletOptions
402
- ? {
403
- top: hideChooseList ? -8 : -4,
404
- transform: 'translateY(-100%)',
405
- }
406
- : {
407
- bottom: hideChooseList ? -8 : -4,
408
- transform: 'translateY(100%)',
409
- }),
410
- left: 0,
411
- right: 0,
412
- textAlign: 'center',
413
- }}>
414
- {t('scanWithWallet1')} <DownloadTips /> {t('scanWithWallet2')}
415
- </Box>
416
- </Box>
417
- </Box>
418
- );
419
- }, [qrcode, hideChooseList, showWalletOptions]);
420
-
421
- const fallbackContent = (
422
- <Box
423
- className="did-connect__body"
424
- sx={{
425
- display: 'flex',
426
- flexDirection: didConnectFlexDirection,
427
- justifyContent: 'center',
428
- alignItems: 'stretch',
429
- flex: 1,
430
- gap: !hideQRCode && isSmallView ? 0 : 1.5,
431
- overflow: 'visible',
432
- px: hideChooseList ? 2 : 0,
433
- }}>
434
- {!showStatus && !hideQRCode ? (
435
- <>
436
- {qrcodeContent}
437
- {hideChooseList ? null : (
438
- <Box>
439
- <Divider
440
- orientation="vertical"
441
- sx={{
442
- fontSize: 12,
443
- color: 'text.hint',
444
- '&::before, &::after': {
445
- borderColor: 'divider',
446
- },
447
- }}>
448
- or
449
- </Divider>
450
- </Box>
451
- )}
452
- </>
453
- ) : null}
454
- <Box
455
- sx={{
456
- display: 'flex',
457
- flex: 1,
458
- }}>
459
- {/* eslint-disable-next-line no-nested-ternary */}
460
- {content}
461
- <ConnectProviderList
462
- slotProps={{
463
- root: {
464
- sx: [showStatus ? { display: 'none' } : {}],
465
- },
466
- }}
467
- allowWallet={allowWallet}
468
- size={hideQRCode && mode !== 'dialog' ? 'normal' : 'small'}
469
- tokenState={state}
470
- hideQRCode={hideQRCode}
471
- messages={messages}
472
- tokenKey={tokenKey}
473
- onSuccess={onSuccess}
474
- passkeyBehavior={passkeyBehavior}
475
- webWalletUrl={webWalletUrl}
476
- extraContent={extraContent}
477
- enabledConnectTypes={enabledConnectTypes}
478
- onReset={handleReset}
479
- disableSwitchApp={disableSwitchApp}
480
- forceUpdate={forceUpdate}
481
- magicToken={magicToken}
482
- baseUrl={baseUrl}
483
- customItems={customItems}
484
- providerList={providerList}
485
- qrcode={qrcodeContent}
486
- />
487
- </Box>
488
- </Box>
489
- );
490
- let contentResult = fallbackContent;
491
- if (selectedPlugin) {
492
- contentResult = selectedPlugin.renderPlaceholder({
493
- fallback: fallbackContent,
494
- forceUpdate,
495
- onSuccess,
496
- onError,
497
- });
498
- } else {
499
- contentResult = fallbackContent;
500
- }
501
-
502
- const containerWidth = hideQRCode || showStatus ? DID_CONNECT_SMALL_WIDTH : DID_CONNECT_MEDIUM_WIDTH;
9
+ const LazyConnect = lazy(() => import('./connect'));
503
10
 
11
+ function WrapConnect(props) {
504
12
  return (
505
- <Box
506
- ref={rootRef}
507
- className="did-connect__root"
508
- sx={{
509
- backgroundColor: 'background.default',
510
- display: 'flex',
511
- flexDirection: 'column',
512
- height: '100%',
513
- position: 'relative',
514
- maxWidth: '100%',
515
- width:
516
- // eslint-disable-next-line no-nested-ternary
517
- mode === 'drawer' ? '100%' : showWalletOptions ? containerWidth - 20 : containerWidth,
518
- transition: 'width 0.2s ease-in-out',
519
- margin: 'auto',
520
- p: 3,
521
- pb: 0,
522
- gap: 2.5,
523
- }}>
524
- <Box data-did-auth-url={state.url} sx={{ display: 'none' }} />
525
- <DIDConnectTitle
526
- title={messages.title}
527
- description={messages.scan}
528
- extraContent={extraContent}
529
- disableSwitchApp={disableSwitchApp}
530
- showWalletOptions={showWalletOptions}
531
- onBack={() => setShowWalletOptions(false)}
532
- />
533
- <AutoHeight initHeight={24 + 16 + 32}>{contentResult}</AutoHeight>
534
- <DIDConnectFooter currentAppInfo={currentAppInfo} currentAppColor={currentAppColor} />
535
- {closeButton}
536
- </Box>
13
+ <Suspense fallback={<FallbackConnect />}>
14
+ <LazyConnect {...props} />
15
+ </Suspense>
537
16
  );
538
17
  }
539
18
 
540
- Connect.propTypes = {
541
- mode: PropTypes.oneOf(['dialog', 'drawer', 'page']),
542
-
543
- action: PropTypes.string.isRequired,
544
- baseUrl: PropTypes.string,
545
- checkFn: PropTypes.func.isRequired,
546
- checkInterval: PropTypes.number,
547
- checkTimeout: PropTypes.number,
548
- // extraParams: PropTypes.object, // 需要使用 useStateContext 中导出的
549
- prefix: PropTypes.string,
550
- messages: PropTypes.object,
551
- tokenKey: PropTypes.string,
552
- locale: PropTypes.oneOf(['en', 'zh', '']),
553
- encKey: PropTypes.string,
554
- autoConnect: PropTypes.bool,
555
- forceConnected: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
556
- saveConnect: PropTypes.bool,
557
- useSocket: PropTypes.bool,
558
- extraContent: PropTypes.any,
559
- passkeyBehavior: PropTypes.oneOf(['none', 'both', 'only-existing', 'only-new']),
560
- enabledConnectTypes: PropTypes.arrayOf(PropTypes.oneOf(['web', 'mobile', ...Object.keys(OAUTH_PROVIDER)])),
561
- webWalletUrl: PropTypes.string,
562
-
563
- allowWallet: PropTypes.bool,
564
- provider: PropTypes.oneOf([LOGIN_PROVIDER.WALLET, ...Object.keys(OAUTH_PROVIDER), '']),
565
- hideCloseButton: PropTypes.bool,
566
- disableSwitchApp: PropTypes.bool,
567
- onClose: PropTypes.func,
568
- onError: PropTypes.func,
569
- onSuccess: PropTypes.func,
570
- onRecreateSession: PropTypes.func,
571
- setColor: PropTypes.func,
572
- magicToken: PropTypes.string,
573
- customItems: PropTypes.arrayOf(PropTypes.node),
574
- };
575
-
576
- function WrapConnect({ testOnlyBorderColor = undefined, ...props }) {
577
- const { checkFn, extraParams = {}, blocklet, masterBlocklet, action, locale = 'en' } = props;
578
- if (typeof checkFn !== 'function') {
579
- throw new Error('Cannot initialize did connect component without a fetchFn');
580
- }
581
-
582
- return (
583
- <StateProvider
584
- blocklet={blocklet}
585
- masterBlocklet={masterBlocklet}
586
- action={action}
587
- locale={locale}
588
- extraParams={extraParams}
589
- testOnlyBorderColor={testOnlyBorderColor}
590
- sx={{
591
- position: 'relative',
592
- width: '100%',
593
- height: '100%',
594
- lineHeight: 1.2,
595
- color: 'grey.700',
596
- '&, & *, & *:before, & *:after': {
597
- fontFamily: 'Lexend', // 保持跟 DID Wallet 一致
598
- boxSizing: 'border-box',
599
- },
600
- }}>
601
- <Connect {...props} />
602
- </StateProvider>
603
- );
604
- }
605
-
606
- WrapConnect.propTypes = {
607
- checkFn: PropTypes.func.isRequired,
608
- extraParams: PropTypes.object,
609
- blocklet: PropTypes.object.isRequired,
610
- masterBlocklet: PropTypes.object,
611
- action: PropTypes.string.isRequired,
612
- locale: PropTypes.string,
613
- testOnlyBorderColor: PropTypes.string,
614
- };
615
-
616
19
  export default withUxTheme(withBridgeCall(withBlocklet(withContainer(WrapConnect))));
617
20
 
618
21
  export { useSecurity };