@arcblock/ux 2.11.9 → 2.11.11
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/BlockletV2/blocklet.d.ts +8 -8
- package/lib/BlockletV2/blocklet.js +5 -3
- package/lib/BlockletV2/components/icon-text.d.ts +1 -1
- package/lib/BlockletV2/components/icon-text.js +14 -10
- package/lib/BlockletV2/{tooltip-icon.d.ts → components/tooltip-icon.d.ts} +1 -1
- package/lib/BlockletV2/components/tooltip-icon.js +38 -0
- package/lib/BlockletV2/index.d.ts +1 -1
- package/lib/BlockletV2/index.js +1 -1
- package/lib/ErrorBoundary/fallback.d.ts +1 -5
- package/lib/ErrorBoundary/fallback.js +51 -29
- package/lib/Util/index.d.ts +1 -0
- package/lib/Util/index.js +21 -1
- package/package.json +6 -5
- package/src/BlockletV2/blocklet.tsx +29 -27
- package/src/BlockletV2/components/icon-text.tsx +10 -8
- package/src/BlockletV2/components/tooltip-icon.tsx +51 -0
- package/src/BlockletV2/index.ts +1 -1
- package/src/ErrorBoundary/fallback.tsx +50 -29
- package/src/Util/index.ts +24 -0
- package/lib/BlockletV2/tooltip-icon.js +0 -33
- package/src/BlockletV2/tooltip-icon.tsx +0 -46
@@ -5,9 +5,9 @@ export interface IBlockletStore extends CardProps {
|
|
5
5
|
title: string;
|
6
6
|
description?: string;
|
7
7
|
cover?: string;
|
8
|
-
avatar
|
9
|
-
author
|
10
|
-
download
|
8
|
+
avatar?: string;
|
9
|
+
author?: string;
|
10
|
+
download?: string;
|
11
11
|
official?: {
|
12
12
|
tooltip: React.ReactNode;
|
13
13
|
size?: number;
|
@@ -15,16 +15,16 @@ export interface IBlockletStore extends CardProps {
|
|
15
15
|
};
|
16
16
|
button?: React.ReactNode;
|
17
17
|
buttonText?: string;
|
18
|
-
buttonDisabled?:
|
19
|
-
buttonLoading?:
|
18
|
+
buttonDisabled?: boolean;
|
19
|
+
buttonLoading?: boolean;
|
20
20
|
onButtonClick?: Function;
|
21
21
|
onMainClick?: Function;
|
22
22
|
className?: string;
|
23
23
|
status?: {
|
24
24
|
key: string;
|
25
25
|
icon: React.ReactNode;
|
26
|
-
text:
|
27
|
-
title?:
|
26
|
+
text: React.ReactNode;
|
27
|
+
title?: React.ReactNode;
|
28
28
|
maxWidth?: number;
|
29
29
|
color?: string;
|
30
30
|
align?: 'left' | 'right';
|
@@ -32,7 +32,7 @@ export interface IBlockletStore extends CardProps {
|
|
32
32
|
icons?: {
|
33
33
|
key: string;
|
34
34
|
icon: string | React.ReactElement;
|
35
|
-
title:
|
35
|
+
title: React.ReactNode;
|
36
36
|
color?: string;
|
37
37
|
}[];
|
38
38
|
}
|
@@ -8,7 +8,7 @@ import Avatar from '../Avatar';
|
|
8
8
|
import Button from '../Button';
|
9
9
|
import { useTheme } from '../Theme';
|
10
10
|
import IconText from './components/icon-text';
|
11
|
-
import TooltipIcon from './tooltip-icon';
|
11
|
+
import TooltipIcon from './components/tooltip-icon';
|
12
12
|
import { formatDownloadCount, strippedString } from './utils';
|
13
13
|
export default function BlockletStore(props) {
|
14
14
|
const {
|
@@ -104,6 +104,7 @@ export default function BlockletStore(props) {
|
|
104
104
|
textOverflow: 'ellipsis',
|
105
105
|
whiteSpace: 'nowrap',
|
106
106
|
overflow: 'hidden',
|
107
|
+
cursor: 'default',
|
107
108
|
pl: 0.5,
|
108
109
|
'&&': {
|
109
110
|
flexShrink: 1
|
@@ -133,7 +134,7 @@ export default function BlockletStore(props) {
|
|
133
134
|
}
|
134
135
|
}) : item.icon
|
135
136
|
}, item.key))]
|
136
|
-
}),
|
137
|
+
}), onButtonClick && /*#__PURE__*/_jsxs(Button, {
|
137
138
|
color: "reverse",
|
138
139
|
variant: "outlined",
|
139
140
|
size: "small",
|
@@ -152,7 +153,7 @@ export default function BlockletStore(props) {
|
|
152
153
|
color: 'inherit'
|
153
154
|
}
|
154
155
|
}), buttonText]
|
155
|
-
})]
|
156
|
+
}), button]
|
156
157
|
}), /*#__PURE__*/_jsx(Stack, {
|
157
158
|
py: 2,
|
158
159
|
children: /*#__PURE__*/_jsx(Typography, {
|
@@ -165,6 +166,7 @@ export default function BlockletStore(props) {
|
|
165
166
|
WebkitLineClamp: 2,
|
166
167
|
WebkitBoxOrient: 'vertical',
|
167
168
|
overflow: 'hidden',
|
169
|
+
cursor: 'default',
|
168
170
|
height: 40
|
169
171
|
},
|
170
172
|
...descriptionProps
|
@@ -4,6 +4,6 @@ export default function IconText({ icon, children, maxWidth, title, sx, }: {
|
|
4
4
|
icon?: React.ReactNode;
|
5
5
|
children?: React.ReactNode;
|
6
6
|
maxWidth?: number;
|
7
|
-
title?:
|
7
|
+
title?: React.ReactNode;
|
8
8
|
sx?: StackProps['sx'];
|
9
9
|
}): false | "" | 0 | import("react/jsx-runtime").JSX.Element | null | undefined;
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import { Stack, Typography } from '@mui/material';
|
3
3
|
import React from 'react';
|
4
|
+
import TooltipIcon from './tooltip-icon';
|
4
5
|
export default function IconText({
|
5
6
|
icon,
|
6
7
|
children,
|
@@ -16,16 +17,19 @@ export default function IconText({
|
|
16
17
|
maxWidth,
|
17
18
|
overflow: 'hidden'
|
18
19
|
}, ...(Array.isArray(sx) ? sx : [sx])],
|
19
|
-
children: [icon, /*#__PURE__*/_jsx(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
children: [icon, /*#__PURE__*/_jsx(TooltipIcon, {
|
21
|
+
title: title || (typeof children === 'string' ? children : ''),
|
22
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
23
|
+
flex: 1,
|
24
|
+
variant: "body2",
|
25
|
+
sx: {
|
26
|
+
overflow: 'hidden',
|
27
|
+
textOverflow: 'ellipsis',
|
28
|
+
whiteSpace: 'nowrap',
|
29
|
+
cursor: 'default'
|
30
|
+
},
|
31
|
+
children: children
|
32
|
+
})
|
29
33
|
})]
|
30
34
|
});
|
31
35
|
}
|
@@ -4,4 +4,4 @@ export interface TooltipIconProps extends TooltipProps {
|
|
4
4
|
fontWeight?: number | string;
|
5
5
|
color?: string;
|
6
6
|
}
|
7
|
-
export default function TooltipIcon({ title, sx, children,
|
7
|
+
export default function TooltipIcon({ title, sx, children, slotProps, fontSize, fontWeight, color, ...props }: TooltipIconProps): import("react/jsx-runtime").JSX.Element;
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import { Tooltip, tooltipClasses } from '@mui/material';
|
3
|
+
export default function TooltipIcon({
|
4
|
+
title,
|
5
|
+
sx,
|
6
|
+
children,
|
7
|
+
slotProps,
|
8
|
+
fontSize = 12,
|
9
|
+
fontWeight = 500,
|
10
|
+
color = 'text.secondary',
|
11
|
+
...props
|
12
|
+
}) {
|
13
|
+
return title ? /*#__PURE__*/_jsx(Tooltip, {
|
14
|
+
title: title,
|
15
|
+
placement: "top",
|
16
|
+
...props,
|
17
|
+
slotProps: {
|
18
|
+
popper: {
|
19
|
+
...slotProps?.popper,
|
20
|
+
sx: [{
|
21
|
+
[`& .${tooltipClasses.tooltip}`]: {
|
22
|
+
backgroundColor: 'common.white',
|
23
|
+
fontSize,
|
24
|
+
fontWeight,
|
25
|
+
boxShadow: '0px 4px 8px 0px #03071214, 0px 0px 0px 1px #03071214',
|
26
|
+
marginBottom: '6px !important',
|
27
|
+
borderRadius: '8px',
|
28
|
+
cursor: 'default',
|
29
|
+
color,
|
30
|
+
display: 'flex',
|
31
|
+
alignItems: 'center'
|
32
|
+
}
|
33
|
+
}, ...(Array.isArray(slotProps?.popper?.sx) ? slotProps.popper.sx : [slotProps?.popper?.sx])]
|
34
|
+
}
|
35
|
+
},
|
36
|
+
children: children
|
37
|
+
}) : children;
|
38
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import ActionButton, { strippedString } from './utils';
|
2
2
|
import Blocklet from './blocklet';
|
3
|
-
import TooltipIcon from './tooltip-icon';
|
3
|
+
import TooltipIcon from './components/tooltip-icon';
|
4
4
|
export { ActionButton, strippedString, TooltipIcon };
|
5
5
|
export default Blocklet;
|
package/lib/BlockletV2/index.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import ActionButton, { strippedString } from './utils';
|
2
2
|
import Blocklet from './blocklet';
|
3
|
-
import TooltipIcon from './tooltip-icon';
|
3
|
+
import TooltipIcon from './components/tooltip-icon';
|
4
4
|
export { ActionButton, strippedString, TooltipIcon };
|
5
5
|
export default Blocklet;
|
@@ -1,8 +1,3 @@
|
|
1
|
-
export interface InternalErrorFallbackProps {
|
2
|
-
title?: string;
|
3
|
-
desc: string;
|
4
|
-
retryFunc?: (() => void) | null;
|
5
|
-
}
|
6
1
|
export interface ErrorFallbackProps {
|
7
2
|
error: Error;
|
8
3
|
}
|
@@ -12,3 +7,4 @@ export interface ErrorFallbackRetryProps {
|
|
12
7
|
resetErrorBoundary: () => void;
|
13
8
|
}
|
14
9
|
export declare function ErrorFallbackRetry({ error, resetErrorBoundary }: ErrorFallbackRetryProps): import("react/jsx-runtime").JSX.Element;
|
10
|
+
export declare function ReactRouterErrorFallback(): import("react/jsx-runtime").JSX.Element;
|
@@ -1,24 +1,48 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
-
import {
|
2
|
+
import { Alert, AlertTitle, Box, Typography } from '@mui/material';
|
3
|
+
import { useRouteError } from 'react-router-dom';
|
3
4
|
import Button from '../Button';
|
4
|
-
import { styled } from '../Theme';
|
5
5
|
function InternalErrorFallback({
|
6
6
|
title = 'Something went wrong...',
|
7
7
|
desc,
|
8
|
-
|
8
|
+
extraContent = null,
|
9
|
+
severity = 'error'
|
9
10
|
}) {
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
const gotoHome = () => window.location.replace('/');
|
12
|
+
const refresh = () => window.location.reload();
|
13
|
+
return /*#__PURE__*/_jsxs(Alert, {
|
14
|
+
severity: severity,
|
15
|
+
variant: "outlined",
|
16
|
+
icon: false,
|
17
|
+
sx: {
|
18
|
+
justifyContent: 'center'
|
19
|
+
},
|
20
|
+
children: [title ? /*#__PURE__*/_jsx(AlertTitle, {
|
13
21
|
children: title
|
14
|
-
}), /*#__PURE__*/_jsx(
|
22
|
+
}) : null, desc ? /*#__PURE__*/_jsx(Typography, {
|
23
|
+
variant: "body2",
|
24
|
+
mb: 1,
|
15
25
|
children: desc
|
16
|
-
}),
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
}) : null, extraContent ?? /*#__PURE__*/_jsxs(Box, {
|
27
|
+
sx: {
|
28
|
+
display: 'flex',
|
29
|
+
gap: 1,
|
30
|
+
justifyContent: 'center',
|
31
|
+
alignItems: 'center'
|
32
|
+
},
|
33
|
+
children: [/*#__PURE__*/_jsx(Button, {
|
34
|
+
variant: "outlined",
|
35
|
+
color: severity,
|
36
|
+
size: "small",
|
37
|
+
onClick: gotoHome,
|
38
|
+
children: "Home"
|
39
|
+
}), /*#__PURE__*/_jsx(Button, {
|
40
|
+
variant: "contained",
|
41
|
+
color: severity,
|
42
|
+
size: "small",
|
43
|
+
onClick: refresh,
|
44
|
+
children: "Refresh"
|
45
|
+
})]
|
22
46
|
})]
|
23
47
|
});
|
24
48
|
}
|
@@ -35,21 +59,19 @@ export function ErrorFallbackRetry({
|
|
35
59
|
}) {
|
36
60
|
return /*#__PURE__*/_jsx(InternalErrorFallback, {
|
37
61
|
desc: error.message,
|
38
|
-
|
62
|
+
extraContent: /*#__PURE__*/_jsx(Button, {
|
63
|
+
variant: "contained",
|
64
|
+
color: "error",
|
65
|
+
size: "small",
|
66
|
+
onClick: resetErrorBoundary,
|
67
|
+
children: "Try again"
|
68
|
+
})
|
39
69
|
});
|
40
70
|
}
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
h3 {
|
49
|
-
margin: 0;
|
50
|
-
font-size: 16px;
|
51
|
-
}
|
52
|
-
pre {
|
53
|
-
white-space: normal;
|
54
|
-
}
|
55
|
-
`;
|
71
|
+
export function ReactRouterErrorFallback() {
|
72
|
+
const error = useRouteError();
|
73
|
+
return /*#__PURE__*/_jsx(InternalErrorFallback, {
|
74
|
+
title: "Current route occurred an error",
|
75
|
+
desc: error.message
|
76
|
+
});
|
77
|
+
}
|
package/lib/Util/index.d.ts
CHANGED
@@ -86,4 +86,5 @@ export declare const getTranslation: (translations: TranslationsObject, locale:
|
|
86
86
|
fallbackLocale?: Locale;
|
87
87
|
defaultValue?: string;
|
88
88
|
}) => string;
|
89
|
+
export declare const lazyRetry: (fn: () => Promise<any>) => import("react").LazyExoticComponent<import("react").ComponentType<any>>;
|
89
90
|
export {};
|
package/lib/Util/index.js
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
/* eslint-disable no-bitwise */
|
2
|
+
import { lazy } from 'react';
|
2
3
|
import padStart from 'lodash/padStart';
|
3
4
|
import { getDIDMotifInfo, colors } from '@arcblock/did-motif';
|
4
5
|
import isNil from 'lodash/isNil';
|
6
|
+
import pRetry from 'p-retry';
|
5
7
|
import { DID_PREFIX, WELLKNOWN_SERVICE_PATH_PREFIX } from './constant';
|
6
8
|
let dateTool = null;
|
7
9
|
export function parseQuery(str) {
|
@@ -356,4 +358,22 @@ export const getTranslation = (translations, locale, options = {}) => {
|
|
356
358
|
translation = defaultValue;
|
357
359
|
}
|
358
360
|
return translation;
|
359
|
-
};
|
361
|
+
};
|
362
|
+
export const lazyRetry = fn => /*#__PURE__*/lazy(() => pRetry(async () => {
|
363
|
+
try {
|
364
|
+
return await fn();
|
365
|
+
} catch (error) {
|
366
|
+
// HACK: pRetry 不会对 TypeError 的错误进行重试,手动放行了部分 network error 的错误,但此处的错误是经过 react-router 包装过的,不适用于上述的判断,所以这里需要特殊逻辑来进行处理
|
367
|
+
if (error instanceof TypeError && !error.message.includes('Failed to fetch')) {
|
368
|
+
throw error;
|
369
|
+
}
|
370
|
+
if (error instanceof Error) {
|
371
|
+
throw new Error(error.message);
|
372
|
+
}
|
373
|
+
throw new Error('Unknown error');
|
374
|
+
}
|
375
|
+
},
|
376
|
+
// 只需要重试两次,加上原本的一次,总共三次
|
377
|
+
{
|
378
|
+
retries: 2
|
379
|
+
}));
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "2.11.
|
3
|
+
"version": "2.11.11",
|
4
4
|
"description": "Common used react components for arcblock products",
|
5
5
|
"keywords": [
|
6
6
|
"react",
|
@@ -68,12 +68,12 @@
|
|
68
68
|
"react": ">=18.2.0",
|
69
69
|
"react-router-dom": ">=6.22.3"
|
70
70
|
},
|
71
|
-
"gitHead": "
|
71
|
+
"gitHead": "fc251e65f592a96d6fe876dda5d6158f7fbd2613",
|
72
72
|
"dependencies": {
|
73
73
|
"@arcblock/did-motif": "^1.1.13",
|
74
|
-
"@arcblock/icons": "^2.11.
|
75
|
-
"@arcblock/nft-display": "^2.11.
|
76
|
-
"@arcblock/react-hooks": "^2.11.
|
74
|
+
"@arcblock/icons": "^2.11.11",
|
75
|
+
"@arcblock/nft-display": "^2.11.11",
|
76
|
+
"@arcblock/react-hooks": "^2.11.11",
|
77
77
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
78
78
|
"@fontsource/inter": "^5.0.16",
|
79
79
|
"@fontsource/ubuntu-mono": "^5.0.18",
|
@@ -103,6 +103,7 @@
|
|
103
103
|
"lodash": "^4.17.21",
|
104
104
|
"mui-datatables": "^4.3.0",
|
105
105
|
"notistack": "^2.0.5",
|
106
|
+
"p-retry": "^6.2.1",
|
106
107
|
"pako": "^2.1.0",
|
107
108
|
"qrcode.react": "^3.1.0",
|
108
109
|
"react-cookie-consent": "^6.4.1",
|
@@ -8,7 +8,7 @@ import Avatar from '../Avatar';
|
|
8
8
|
import Button from '../Button';
|
9
9
|
import { useTheme } from '../Theme';
|
10
10
|
import IconText from './components/icon-text';
|
11
|
-
import TooltipIcon from './tooltip-icon';
|
11
|
+
import TooltipIcon from './components/tooltip-icon';
|
12
12
|
import { formatDownloadCount, strippedString } from './utils';
|
13
13
|
|
14
14
|
export interface IBlockletStore extends CardProps {
|
@@ -16,9 +16,9 @@ export interface IBlockletStore extends CardProps {
|
|
16
16
|
title: string;
|
17
17
|
description?: string;
|
18
18
|
cover?: string;
|
19
|
-
avatar
|
20
|
-
author
|
21
|
-
download
|
19
|
+
avatar?: string;
|
20
|
+
author?: string;
|
21
|
+
download?: string;
|
22
22
|
official?: {
|
23
23
|
tooltip: React.ReactNode;
|
24
24
|
size?: number;
|
@@ -26,16 +26,16 @@ export interface IBlockletStore extends CardProps {
|
|
26
26
|
};
|
27
27
|
button?: React.ReactNode;
|
28
28
|
buttonText?: string;
|
29
|
-
buttonDisabled?:
|
30
|
-
buttonLoading?:
|
29
|
+
buttonDisabled?: boolean;
|
30
|
+
buttonLoading?: boolean;
|
31
31
|
onButtonClick?: Function;
|
32
32
|
onMainClick?: Function;
|
33
33
|
className?: string;
|
34
34
|
status?: {
|
35
35
|
key: string;
|
36
36
|
icon: React.ReactNode;
|
37
|
-
text:
|
38
|
-
title?:
|
37
|
+
text: React.ReactNode;
|
38
|
+
title?: React.ReactNode;
|
39
39
|
maxWidth?: number;
|
40
40
|
color?: string;
|
41
41
|
align?: 'left' | 'right';
|
@@ -43,7 +43,7 @@ export interface IBlockletStore extends CardProps {
|
|
43
43
|
icons?: {
|
44
44
|
key: string;
|
45
45
|
icon: string | React.ReactElement;
|
46
|
-
title:
|
46
|
+
title: React.ReactNode;
|
47
47
|
color?: string;
|
48
48
|
}[];
|
49
49
|
}
|
@@ -116,6 +116,7 @@ export default function BlockletStore(props: IBlockletStore) {
|
|
116
116
|
textOverflow: 'ellipsis',
|
117
117
|
whiteSpace: 'nowrap',
|
118
118
|
overflow: 'hidden',
|
119
|
+
cursor: 'default',
|
119
120
|
pl: 0.5,
|
120
121
|
'&&': { flexShrink: 1 },
|
121
122
|
}}
|
@@ -133,24 +134,24 @@ export default function BlockletStore(props: IBlockletStore) {
|
|
133
134
|
</TooltipIcon>
|
134
135
|
))}
|
135
136
|
</Box>
|
136
|
-
{
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
137
|
+
{onButtonClick && (
|
138
|
+
<Button
|
139
|
+
color="reverse"
|
140
|
+
variant="outlined"
|
141
|
+
size="small"
|
142
|
+
disabled={buttonDisabled || buttonLoading}
|
143
|
+
style={{
|
144
|
+
borderColor: theme.palette.grey[300],
|
145
|
+
borderRadius: 8,
|
146
|
+
fontSize: 13,
|
147
|
+
fontWeight: theme.typography.fontWeightMedium,
|
148
|
+
}}
|
149
|
+
onClick={handleButtonClick}>
|
150
|
+
{buttonLoading && <CircularProgress size={15} style={{ marginRight: 3, color: 'inherit' }} />}
|
151
|
+
{buttonText}
|
152
|
+
</Button>
|
153
|
+
)}
|
154
|
+
{button}
|
154
155
|
</Stack>
|
155
156
|
<Stack py={2}>
|
156
157
|
<Typography
|
@@ -163,6 +164,7 @@ export default function BlockletStore(props: IBlockletStore) {
|
|
163
164
|
WebkitLineClamp: 2,
|
164
165
|
WebkitBoxOrient: 'vertical',
|
165
166
|
overflow: 'hidden',
|
167
|
+
cursor: 'default',
|
166
168
|
height: 40,
|
167
169
|
}}
|
168
170
|
{...descriptionProps}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { Stack, StackProps, Typography } from '@mui/material';
|
2
2
|
import React from 'react';
|
3
|
+
import TooltipIcon from './tooltip-icon';
|
3
4
|
|
4
5
|
export default function IconText({
|
5
6
|
icon,
|
@@ -11,7 +12,7 @@ export default function IconText({
|
|
11
12
|
icon?: React.ReactNode;
|
12
13
|
children?: React.ReactNode;
|
13
14
|
maxWidth?: number;
|
14
|
-
title?:
|
15
|
+
title?: React.ReactNode;
|
15
16
|
sx?: StackProps['sx'];
|
16
17
|
}) {
|
17
18
|
return (
|
@@ -22,13 +23,14 @@ export default function IconText({
|
|
22
23
|
gap={0.5}
|
23
24
|
sx={[{ maxWidth, overflow: 'hidden' }, ...(Array.isArray(sx) ? sx : [sx])]}>
|
24
25
|
{icon}
|
25
|
-
<
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
<TooltipIcon title={title || (typeof children === 'string' ? children : '')}>
|
27
|
+
<Typography
|
28
|
+
flex={1}
|
29
|
+
variant="body2"
|
30
|
+
sx={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', cursor: 'default' }}>
|
31
|
+
{children}
|
32
|
+
</Typography>
|
33
|
+
</TooltipIcon>
|
32
34
|
</Stack>
|
33
35
|
)
|
34
36
|
);
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import { Tooltip, TooltipProps, tooltipClasses } from '@mui/material';
|
2
|
+
|
3
|
+
export interface TooltipIconProps extends TooltipProps {
|
4
|
+
fontSize?: number | string;
|
5
|
+
fontWeight?: number | string;
|
6
|
+
color?: string;
|
7
|
+
}
|
8
|
+
|
9
|
+
export default function TooltipIcon({
|
10
|
+
title,
|
11
|
+
sx,
|
12
|
+
children,
|
13
|
+
slotProps,
|
14
|
+
fontSize = 12,
|
15
|
+
fontWeight = 500,
|
16
|
+
color = 'text.secondary',
|
17
|
+
...props
|
18
|
+
}: TooltipIconProps) {
|
19
|
+
return title ? (
|
20
|
+
<Tooltip
|
21
|
+
title={title}
|
22
|
+
placement="top"
|
23
|
+
{...props}
|
24
|
+
slotProps={{
|
25
|
+
popper: {
|
26
|
+
...slotProps?.popper,
|
27
|
+
sx: [
|
28
|
+
{
|
29
|
+
[`& .${tooltipClasses.tooltip}`]: {
|
30
|
+
backgroundColor: 'common.white',
|
31
|
+
fontSize,
|
32
|
+
fontWeight,
|
33
|
+
boxShadow: '0px 4px 8px 0px #03071214, 0px 0px 0px 1px #03071214',
|
34
|
+
marginBottom: '6px !important',
|
35
|
+
borderRadius: '8px',
|
36
|
+
cursor: 'default',
|
37
|
+
color,
|
38
|
+
display: 'flex',
|
39
|
+
alignItems: 'center',
|
40
|
+
},
|
41
|
+
},
|
42
|
+
...(Array.isArray(slotProps?.popper?.sx) ? slotProps.popper.sx : [slotProps?.popper?.sx]),
|
43
|
+
],
|
44
|
+
},
|
45
|
+
}}>
|
46
|
+
{children}
|
47
|
+
</Tooltip>
|
48
|
+
) : (
|
49
|
+
children
|
50
|
+
);
|
51
|
+
}
|
package/src/BlockletV2/index.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import ActionButton, { strippedString } from './utils';
|
2
2
|
import Blocklet from './blocklet';
|
3
|
-
import TooltipIcon from './tooltip-icon';
|
3
|
+
import TooltipIcon from './components/tooltip-icon';
|
4
4
|
|
5
5
|
export { ActionButton, strippedString, TooltipIcon };
|
6
6
|
export default Blocklet;
|
@@ -1,28 +1,51 @@
|
|
1
|
-
import {
|
1
|
+
import { Alert, AlertTitle, Box, Typography, type AlertProps } from '@mui/material';
|
2
|
+
import { ReactNode } from 'react';
|
3
|
+
import { useRouteError } from 'react-router-dom';
|
4
|
+
|
2
5
|
import Button from '../Button';
|
3
|
-
import { styled } from '../Theme';
|
4
6
|
|
5
|
-
|
7
|
+
interface InternalErrorFallbackProps {
|
6
8
|
title?: string;
|
7
9
|
desc: string;
|
8
|
-
|
10
|
+
extraContent?: ReactNode;
|
11
|
+
severity?: AlertProps['severity'];
|
9
12
|
}
|
10
13
|
|
11
14
|
function InternalErrorFallback({
|
12
15
|
title = 'Something went wrong...',
|
13
16
|
desc,
|
14
|
-
|
17
|
+
extraContent = null,
|
18
|
+
severity = 'error',
|
15
19
|
}: InternalErrorFallbackProps) {
|
20
|
+
const gotoHome = () => window.location.replace('/');
|
21
|
+
const refresh = () => window.location.reload();
|
22
|
+
|
16
23
|
return (
|
17
|
-
<
|
18
|
-
|
19
|
-
|
20
|
-
{
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
<Alert
|
25
|
+
severity={severity}
|
26
|
+
variant="outlined"
|
27
|
+
icon={false}
|
28
|
+
sx={{
|
29
|
+
justifyContent: 'center',
|
30
|
+
}}>
|
31
|
+
{title ? <AlertTitle>{title}</AlertTitle> : null}
|
32
|
+
{desc ? (
|
33
|
+
<Typography variant="body2" mb={1}>
|
34
|
+
{desc}
|
35
|
+
</Typography>
|
36
|
+
) : null}
|
37
|
+
{extraContent ?? (
|
38
|
+
<Box sx={{ display: 'flex', gap: 1, justifyContent: 'center', alignItems: 'center' }}>
|
39
|
+
<Button variant="outlined" color={severity} size="small" onClick={gotoHome}>
|
40
|
+
Home
|
41
|
+
</Button>
|
42
|
+
|
43
|
+
<Button variant="contained" color={severity} size="small" onClick={refresh}>
|
44
|
+
Refresh
|
45
|
+
</Button>
|
46
|
+
</Box>
|
24
47
|
)}
|
25
|
-
</
|
48
|
+
</Alert>
|
26
49
|
);
|
27
50
|
}
|
28
51
|
|
@@ -40,21 +63,19 @@ export interface ErrorFallbackRetryProps {
|
|
40
63
|
}
|
41
64
|
|
42
65
|
export function ErrorFallbackRetry({ error, resetErrorBoundary }: ErrorFallbackRetryProps) {
|
43
|
-
return
|
66
|
+
return (
|
67
|
+
<InternalErrorFallback
|
68
|
+
desc={error.message}
|
69
|
+
extraContent={
|
70
|
+
<Button variant="contained" color="error" size="small" onClick={resetErrorBoundary}>
|
71
|
+
Try again
|
72
|
+
</Button>
|
73
|
+
}
|
74
|
+
/>
|
75
|
+
);
|
44
76
|
}
|
45
77
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
color: ${(props) => props.theme.palette.error.main};
|
51
|
-
background-color: ${red[50]};
|
52
|
-
font-size: 14px;
|
53
|
-
h3 {
|
54
|
-
margin: 0;
|
55
|
-
font-size: 16px;
|
56
|
-
}
|
57
|
-
pre {
|
58
|
-
white-space: normal;
|
59
|
-
}
|
60
|
-
`;
|
78
|
+
export function ReactRouterErrorFallback() {
|
79
|
+
const error = useRouteError() as Error;
|
80
|
+
return <InternalErrorFallback title="Current route occurred an error" desc={error.message} />;
|
81
|
+
}
|
package/src/Util/index.ts
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
/* eslint-disable no-bitwise */
|
2
|
+
import { lazy } from 'react';
|
2
3
|
import padStart from 'lodash/padStart';
|
3
4
|
import { getDIDMotifInfo, colors } from '@arcblock/did-motif';
|
4
5
|
import isNil from 'lodash/isNil';
|
6
|
+
import pRetry from 'p-retry';
|
5
7
|
import { DID_PREFIX, WELLKNOWN_SERVICE_PATH_PREFIX } from './constant';
|
6
8
|
import type { $TSFixMe, Locale } from '../type';
|
7
9
|
|
@@ -456,3 +458,25 @@ export const getTranslation = (
|
|
456
458
|
|
457
459
|
return translation;
|
458
460
|
};
|
461
|
+
|
462
|
+
export const lazyRetry = (fn: () => Promise<any>) =>
|
463
|
+
lazy(() =>
|
464
|
+
pRetry(
|
465
|
+
async () => {
|
466
|
+
try {
|
467
|
+
return await fn();
|
468
|
+
} catch (error: unknown) {
|
469
|
+
// HACK: pRetry 不会对 TypeError 的错误进行重试,手动放行了部分 network error 的错误,但此处的错误是经过 react-router 包装过的,不适用于上述的判断,所以这里需要特殊逻辑来进行处理
|
470
|
+
if (error instanceof TypeError && !error.message.includes('Failed to fetch')) {
|
471
|
+
throw error;
|
472
|
+
}
|
473
|
+
if (error instanceof Error) {
|
474
|
+
throw new Error(error.message);
|
475
|
+
}
|
476
|
+
throw new Error('Unknown error');
|
477
|
+
}
|
478
|
+
},
|
479
|
+
// 只需要重试两次,加上原本的一次,总共三次
|
480
|
+
{ retries: 2 }
|
481
|
+
)
|
482
|
+
);
|
@@ -1,33 +0,0 @@
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
import { Tooltip, tooltipClasses } from '@mui/material';
|
3
|
-
export default function TooltipIcon({
|
4
|
-
title,
|
5
|
-
sx,
|
6
|
-
children,
|
7
|
-
PopperProps,
|
8
|
-
fontSize = 12,
|
9
|
-
fontWeight = 500,
|
10
|
-
color = 'text.secondary',
|
11
|
-
...props
|
12
|
-
}) {
|
13
|
-
return title ? /*#__PURE__*/_jsx(Tooltip, {
|
14
|
-
title: title,
|
15
|
-
placement: "top",
|
16
|
-
...props,
|
17
|
-
PopperProps: {
|
18
|
-
...PopperProps,
|
19
|
-
sx: [{
|
20
|
-
[`& .${tooltipClasses.tooltip}`]: {
|
21
|
-
backgroundColor: 'common.white',
|
22
|
-
boxShadow: 1,
|
23
|
-
fontSize,
|
24
|
-
fontWeight,
|
25
|
-
color,
|
26
|
-
display: 'flex',
|
27
|
-
alignItems: 'center'
|
28
|
-
}
|
29
|
-
}, ...(Array.isArray(PopperProps?.sx) ? PopperProps.sx : [PopperProps?.sx])]
|
30
|
-
},
|
31
|
-
children: children
|
32
|
-
}) : children;
|
33
|
-
}
|
@@ -1,46 +0,0 @@
|
|
1
|
-
import { Tooltip, TooltipProps, tooltipClasses } from '@mui/material';
|
2
|
-
|
3
|
-
export interface TooltipIconProps extends TooltipProps {
|
4
|
-
fontSize?: number | string;
|
5
|
-
fontWeight?: number | string;
|
6
|
-
color?: string;
|
7
|
-
}
|
8
|
-
|
9
|
-
export default function TooltipIcon({
|
10
|
-
title,
|
11
|
-
sx,
|
12
|
-
children,
|
13
|
-
PopperProps,
|
14
|
-
fontSize = 12,
|
15
|
-
fontWeight = 500,
|
16
|
-
color = 'text.secondary',
|
17
|
-
...props
|
18
|
-
}: TooltipIconProps) {
|
19
|
-
return title ? (
|
20
|
-
<Tooltip
|
21
|
-
title={title}
|
22
|
-
placement="top"
|
23
|
-
{...props}
|
24
|
-
PopperProps={{
|
25
|
-
...PopperProps,
|
26
|
-
sx: [
|
27
|
-
{
|
28
|
-
[`& .${tooltipClasses.tooltip}`]: {
|
29
|
-
backgroundColor: 'common.white',
|
30
|
-
boxShadow: 1,
|
31
|
-
fontSize,
|
32
|
-
fontWeight,
|
33
|
-
color,
|
34
|
-
display: 'flex',
|
35
|
-
alignItems: 'center',
|
36
|
-
},
|
37
|
-
},
|
38
|
-
...(Array.isArray(PopperProps?.sx) ? PopperProps.sx : [PopperProps?.sx]),
|
39
|
-
],
|
40
|
-
}}>
|
41
|
-
{children}
|
42
|
-
</Tooltip>
|
43
|
-
) : (
|
44
|
-
children
|
45
|
-
);
|
46
|
-
}
|