@arcblock/ux 3.0.33 → 3.0.35
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/Avatar/index.d.ts +3 -0
- package/lib/Avatar/index.js +26 -24
- package/lib/DIDConnect/auth-apps/auth-apps-info.js +20 -47
- package/lib/DIDConnect/icons/did-wallet-logo.d.ts +7 -0
- package/lib/DIDConnect/icons/did-wallet-logo.js +12 -0
- package/lib/DIDConnect/icons/github-logo.d.ts +7 -0
- package/lib/DIDConnect/icons/github-logo.js +11 -0
- package/lib/DIDConnect/provider-icon.d.ts +7 -0
- package/lib/DIDConnect/provider-icon.js +52 -0
- package/lib/Img/index.d.ts +9 -1
- package/lib/Img/index.js +83 -72
- package/lib/UserCard/components.js +15 -14
- package/lib/UserCard/index.js +41 -31
- package/lib/Util/constant.d.ts +2 -0
- package/lib/Util/constant.js +23 -20
- package/package.json +7 -7
- package/src/Avatar/index.jsx +3 -0
- package/src/DIDConnect/auth-apps/auth-apps-info.tsx +2 -37
- package/src/DIDConnect/icons/did-wallet-logo.tsx +18 -0
- package/src/DIDConnect/icons/github-logo.tsx +17 -0
- package/src/DIDConnect/provider-icon.tsx +62 -0
- package/src/Img/index.jsx +47 -9
- package/src/UserCard/components.tsx +1 -0
- package/src/UserCard/index.tsx +23 -6
- package/src/Util/constant.ts +3 -0
@@ -1,17 +1,17 @@
|
|
1
1
|
import { jsx as a } from "react/jsx-runtime";
|
2
|
-
import { Box as
|
3
|
-
import
|
4
|
-
import { createNameOnlyAvatar as
|
5
|
-
const N = (r, t = 48,
|
6
|
-
const
|
2
|
+
import { Box as o, Avatar as f } from "@mui/material";
|
3
|
+
import u from "../Avatar/index.js";
|
4
|
+
import { createNameOnlyAvatar as x } from "./utils.js";
|
5
|
+
const N = (r, t = 48, c = void 0, e = void 0, l = !1) => {
|
6
|
+
const n = (i) => {
|
7
7
|
e?.(r, i);
|
8
8
|
};
|
9
9
|
if (!r.avatar) {
|
10
|
-
const i =
|
10
|
+
const i = x(r), { className: s, style: d, alt: m } = c || {};
|
11
11
|
return /* @__PURE__ */ a(
|
12
12
|
f,
|
13
13
|
{
|
14
|
-
onClick:
|
14
|
+
onClick: n,
|
15
15
|
className: s,
|
16
16
|
style: d,
|
17
17
|
alt: m,
|
@@ -19,7 +19,7 @@ const N = (r, t = 48, n = void 0, e = void 0, c = !1) => {
|
|
19
19
|
width: t,
|
20
20
|
height: t,
|
21
21
|
fontSize: t * 0.4,
|
22
|
-
cursor:
|
22
|
+
cursor: l || e ? "pointer" : "default"
|
23
23
|
},
|
24
24
|
variant: "circular",
|
25
25
|
children: i
|
@@ -27,30 +27,31 @@ const N = (r, t = 48, n = void 0, e = void 0, c = !1) => {
|
|
27
27
|
);
|
28
28
|
}
|
29
29
|
return /* @__PURE__ */ a(
|
30
|
-
|
30
|
+
o,
|
31
31
|
{
|
32
32
|
className: "user-card__avatar",
|
33
33
|
sx: {
|
34
34
|
display: "flex"
|
35
35
|
},
|
36
36
|
children: /* @__PURE__ */ a(
|
37
|
-
|
37
|
+
u,
|
38
38
|
{
|
39
39
|
size: t,
|
40
40
|
did: r.did,
|
41
41
|
variant: "circle",
|
42
|
+
useProxyFallback: !0,
|
42
43
|
style: {
|
43
|
-
cursor:
|
44
|
+
cursor: l || e ? "pointer" : "default"
|
44
45
|
},
|
45
|
-
onClick:
|
46
|
+
onClick: n,
|
46
47
|
src: r.avatar,
|
47
48
|
alt: r.fullName || "",
|
48
|
-
...
|
49
|
+
...c || {}
|
49
50
|
}
|
50
51
|
)
|
51
52
|
}
|
52
53
|
);
|
53
|
-
}, _ = (r, t = 120) => r ? /* @__PURE__ */ a(
|
54
|
+
}, _ = (r, t = 120) => r ? /* @__PURE__ */ a(o, { sx: { maxWidth: t }, className: "user-card__top-right-content", children: r() }) : null;
|
54
55
|
export {
|
55
56
|
N as renderAvatar,
|
56
57
|
_ as renderTopRight
|
package/lib/UserCard/index.js
CHANGED
@@ -1,34 +1,44 @@
|
|
1
1
|
import { jsx as t } from "react/jsx-runtime";
|
2
|
-
import { useRef as
|
3
|
-
import { CardType as
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import
|
8
|
-
import
|
9
|
-
import { isUserDid as
|
2
|
+
import { useRef as v, useState as C, useEffect as y, useMemo as P } from "react";
|
3
|
+
import { CardType as o } from "./types.js";
|
4
|
+
import A from "./Cards/avatar-only.js";
|
5
|
+
import m from "./Cards/index.js";
|
6
|
+
import D from "./Container/dialog.js";
|
7
|
+
import S from "./Container/card.js";
|
8
|
+
import w from "../Avatar/index.js";
|
9
|
+
import { isUserDid as x, getUserByDid as U } from "./utils.js";
|
10
10
|
function L(e) {
|
11
11
|
if (!e) return null;
|
12
12
|
let r = "";
|
13
13
|
return e.fullName ? r = e.fullName.charAt(0).toUpperCase() : e.email ? r = e.email.split("@")[0].charAt(0).toUpperCase() : r = e.did ? e.did.charAt(0).toUpperCase() : "?", r;
|
14
14
|
}
|
15
|
-
function
|
16
|
-
const { cardType: r =
|
17
|
-
|
18
|
-
let
|
19
|
-
return e.user ?
|
20
|
-
|
15
|
+
function B(e) {
|
16
|
+
const { cardType: r = o.Detailed, showHoverCard: l } = e, u = l !== void 0 ? l : r === o.AvatarOnly, c = v(null), [i, f] = C(() => e.user || null);
|
17
|
+
y(() => {
|
18
|
+
let a = !0;
|
19
|
+
return e.user ? f(e.user) : e.did && x(e.did) && !e.user && U(e.did).then((d) => {
|
20
|
+
a && f(d || { fullName: "Anonymous", did: e.did, avatar: "" });
|
21
21
|
}), () => {
|
22
|
-
|
22
|
+
a = !1;
|
23
23
|
};
|
24
|
-
}, [e.did, e.user])
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
}, [e.did, e.user]);
|
25
|
+
const n = P(() => {
|
26
|
+
if (!i)
|
27
|
+
return null;
|
28
|
+
const { avatar: a = "", ...d } = i, h = a.split("?")[1];
|
29
|
+
return a && !h ? {
|
30
|
+
...d,
|
31
|
+
avatar: `${a}?imageFilter=resize&w=48&h=48`
|
32
|
+
} : i;
|
33
|
+
}, [i]);
|
34
|
+
if (!n)
|
35
|
+
return /* @__PURE__ */ t(w, { did: e.did, size: e.avatarSize, useProxyFallback: !0, ...e.avatarProps });
|
36
|
+
const s = () => /* @__PURE__ */ t(D, { sx: e.popupSx, children: /* @__PURE__ */ t(
|
37
|
+
m,
|
28
38
|
{
|
29
39
|
...e,
|
30
40
|
shouldShowHoverCard: !1,
|
31
|
-
user:
|
41
|
+
user: n,
|
32
42
|
avatarProps: e.popupAvatarProps,
|
33
43
|
shortenLabelProps: e.popupShortenLabelProps || e.shortenLabelProps,
|
34
44
|
renderFields: e.popupRenderFields,
|
@@ -38,25 +48,25 @@ function g(e) {
|
|
38
48
|
showDid: e.popupShowDid || e.showDid
|
39
49
|
}
|
40
50
|
) });
|
41
|
-
return r ===
|
42
|
-
|
51
|
+
return r === o.AvatarOnly ? /* @__PURE__ */ t(
|
52
|
+
A,
|
43
53
|
{
|
44
54
|
...e,
|
45
|
-
shouldShowHoverCard:
|
46
|
-
renderCardContent:
|
47
|
-
user:
|
55
|
+
shouldShowHoverCard: u,
|
56
|
+
renderCardContent: s,
|
57
|
+
user: n
|
48
58
|
}
|
49
|
-
) : /* @__PURE__ */ t(
|
50
|
-
|
59
|
+
) : /* @__PURE__ */ t(S, { containerRef: c, cardType: r, sx: e.sx, children: /* @__PURE__ */ t(
|
60
|
+
m,
|
51
61
|
{
|
52
62
|
...e,
|
53
|
-
shouldShowHoverCard:
|
54
|
-
renderCardContent:
|
55
|
-
user:
|
63
|
+
shouldShowHoverCard: u,
|
64
|
+
renderCardContent: s,
|
65
|
+
user: n
|
56
66
|
}
|
57
67
|
) });
|
58
68
|
}
|
59
69
|
export {
|
60
70
|
L as createNameOnlyAvatar,
|
61
|
-
|
71
|
+
B as default
|
62
72
|
};
|
package/lib/Util/constant.d.ts
CHANGED
@@ -23,6 +23,7 @@ export declare const LOGIN_PROVIDER: {
|
|
23
23
|
WALLET: string;
|
24
24
|
NFT: string;
|
25
25
|
PASSKEY: string;
|
26
|
+
TWITTER: string;
|
26
27
|
};
|
27
28
|
export declare const LOGIN_PROVIDER_NAME: {
|
28
29
|
[x: string]: string;
|
@@ -33,6 +34,7 @@ export declare const OAUTH_PROVIDER: {
|
|
33
34
|
apple: string;
|
34
35
|
github: string;
|
35
36
|
google: string;
|
37
|
+
twitter: string;
|
36
38
|
};
|
37
39
|
export declare const DID_CONNECT_SMALL_WIDTH = 360;
|
38
40
|
export declare const DID_CONNECT_MEDIUM_WIDTH = 576;
|
package/lib/Util/constant.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
const
|
1
|
+
const T = 300, _ = 1800, t = "/.well-known/service", o = "login_token", I = "refresh_token", e = "/.well-known/service", A = "/api/did", n = `${t}/admin`, s = `${t}/user`, O = `${t}/user/did-spaces`, R = `${t}/admin/navigation`, D = "did:abt:", L = {
|
2
2
|
VALID: "valid",
|
3
3
|
REVOKED: "revoked"
|
4
4
|
}, E = {
|
@@ -9,8 +9,9 @@ const o = 300, t = 1800, _ = "/.well-known/service", A = "login_token", I = "ref
|
|
9
9
|
GOOGLE: "google",
|
10
10
|
WALLET: "wallet",
|
11
11
|
NFT: "nft",
|
12
|
-
PASSKEY: "passkey"
|
13
|
-
|
12
|
+
PASSKEY: "passkey",
|
13
|
+
TWITTER: "twitter"
|
14
|
+
}, i = {
|
14
15
|
[E.EMAIL]: "Email",
|
15
16
|
[E.AUTH0]: "Auth0",
|
16
17
|
[E.APPLE]: "Apple",
|
@@ -18,31 +19,33 @@ const o = 300, t = 1800, _ = "/.well-known/service", A = "login_token", I = "ref
|
|
18
19
|
[E.GOOGLE]: "Google",
|
19
20
|
[E.WALLET]: "DID Wallet",
|
20
21
|
[E.NFT]: "NFT",
|
21
|
-
[E.PASSKEY]: "Passkey"
|
22
|
-
|
22
|
+
[E.PASSKEY]: "Passkey",
|
23
|
+
[E.TWITTER]: "X"
|
24
|
+
}, l = {
|
23
25
|
email: "Email",
|
24
26
|
auth0: "Auth0",
|
25
27
|
apple: "Apple",
|
26
28
|
github: "Github",
|
27
|
-
google: "Google"
|
28
|
-
|
29
|
+
google: "Google",
|
30
|
+
twitter: "X"
|
31
|
+
}, c = 360, a = 576;
|
29
32
|
export {
|
30
|
-
|
31
|
-
|
33
|
+
A as API_DID_PREFIX,
|
34
|
+
t as BLOCKLET_SERVICE_PATH_PREFIX,
|
32
35
|
n as DASHBOARD_URL,
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
T as DEFAULT_TIMEOUT,
|
37
|
+
_ as DEFAULT_WINDOW_TIMEOUT,
|
38
|
+
a as DID_CONNECT_MEDIUM_WIDTH,
|
39
|
+
c as DID_CONNECT_SMALL_WIDTH,
|
40
|
+
D as DID_PREFIX,
|
38
41
|
O as DID_SPACE_URL,
|
39
42
|
E as LOGIN_PROVIDER,
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
i as LOGIN_PROVIDER_NAME,
|
44
|
+
R as NAVIGATION_URL,
|
45
|
+
l as OAUTH_PROVIDER,
|
46
|
+
L as PASSPORT_STATUS,
|
44
47
|
s as PROFILE_URL,
|
45
48
|
I as REFRESH_TOKEN_STORAGE_KEY,
|
46
|
-
|
47
|
-
|
49
|
+
e as RELAY_SOCKET_PREFIX,
|
50
|
+
o as SESSION_TOKEN_STORAGE_KEY
|
48
51
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.35",
|
4
4
|
"description": "Common used react components for arcblock products",
|
5
5
|
"keywords": [
|
6
6
|
"react",
|
@@ -60,16 +60,16 @@
|
|
60
60
|
"react": "^19.0.0",
|
61
61
|
"react-router-dom": "^6.22.3"
|
62
62
|
},
|
63
|
-
"gitHead": "
|
63
|
+
"gitHead": "96e21256a13c640548c59ccd807a61e6faae35f8",
|
64
64
|
"dependencies": {
|
65
|
-
"@arcblock/bridge": "3.0.
|
65
|
+
"@arcblock/bridge": "3.0.35",
|
66
66
|
"@arcblock/did": "^1.21.0",
|
67
67
|
"@arcblock/did-motif": "^1.1.14",
|
68
|
-
"@arcblock/icons": "3.0.
|
69
|
-
"@arcblock/nft-display": "3.0.
|
70
|
-
"@arcblock/react-hooks": "3.0.
|
68
|
+
"@arcblock/icons": "3.0.35",
|
69
|
+
"@arcblock/nft-display": "3.0.35",
|
70
|
+
"@arcblock/react-hooks": "3.0.35",
|
71
71
|
"@blocklet/js-sdk": "^1.16.46",
|
72
|
-
"@blocklet/theme": "3.0.
|
72
|
+
"@blocklet/theme": "3.0.35",
|
73
73
|
"@fontsource/roboto": "~5.1.1",
|
74
74
|
"@fontsource/ubuntu-mono": "^5.2.6",
|
75
75
|
"@iconify-icons/logos": "^1.2.36",
|
package/src/Avatar/index.jsx
CHANGED
@@ -23,6 +23,7 @@ import { DID_PREFIX } from '../Util/constant';
|
|
23
23
|
* shape?: '' | 'rectangle' | 'square' | 'hexagon' | 'circle';
|
24
24
|
* blockiesPadding?: true | false;
|
25
25
|
* responsive?: false | true;
|
26
|
+
* useProxyFallback?: boolean;
|
26
27
|
* } & Omit<import('../Img').ImgProps, 'size' | 'src'>} AvatarProps
|
27
28
|
*/
|
28
29
|
|
@@ -84,6 +85,7 @@ function Avatar({ ...rawProps }) {
|
|
84
85
|
{...rest}
|
85
86
|
// HACK: 这个 className 是传递给子元素的,所以下面的 sx 需要通过子元素选择器来写样式
|
86
87
|
className={`avatar-img--${variant} ${rest?.className || ''}`}
|
88
|
+
useProxyFallback
|
87
89
|
sx={{
|
88
90
|
'& .avatar-img--rounded': {
|
89
91
|
borderRadius: '4px',
|
@@ -159,6 +161,7 @@ Avatar.propTypes = {
|
|
159
161
|
shape: PropTypes.oneOf(['', 'rectangle', 'square', 'hexagon', 'circle']),
|
160
162
|
blockiesPadding: PropTypes.bool,
|
161
163
|
responsive: PropTypes.bool,
|
164
|
+
useProxyFallback: PropTypes.bool,
|
162
165
|
};
|
163
166
|
|
164
167
|
/**
|
@@ -1,28 +1,5 @@
|
|
1
1
|
import { Box, Typography } from '@mui/material';
|
2
2
|
import Img from '../../Img';
|
3
|
-
import { BLOCKLET_SERVICE_PATH_PREFIX } from '../../Util/constant';
|
4
|
-
|
5
|
-
const getProxyImageUrl = (url: string) => {
|
6
|
-
if (!url) return '';
|
7
|
-
|
8
|
-
try {
|
9
|
-
// 检查是否是一个有效的URL
|
10
|
-
const urlObj = new URL(url);
|
11
|
-
|
12
|
-
// 检查协议是否是https
|
13
|
-
if (urlObj.protocol !== 'https:') {
|
14
|
-
console.warn('Image URL must use HTTPS protocol:', url);
|
15
|
-
return '';
|
16
|
-
}
|
17
|
-
|
18
|
-
// 返回代理URL
|
19
|
-
return `${BLOCKLET_SERVICE_PATH_PREFIX}/proxy?url=${url}`;
|
20
|
-
} catch (error) {
|
21
|
-
// URL construction failed, indicating invalid URL format
|
22
|
-
console.warn('Invalid image URL format:', url, error);
|
23
|
-
return '';
|
24
|
-
}
|
25
|
-
};
|
26
3
|
|
27
4
|
export type RequestAppInfo = {
|
28
5
|
appLogo: string;
|
@@ -59,13 +36,7 @@ export default function AuthAppsInfo({
|
|
59
36
|
justifyContent: 'center',
|
60
37
|
}}>
|
61
38
|
{/* FIXME: @zhanghan 增加 hover 的效果 */}
|
62
|
-
<Img
|
63
|
-
src={currentAppInfo.appLogo}
|
64
|
-
alt="Server"
|
65
|
-
width={48}
|
66
|
-
height={48}
|
67
|
-
fallback={getProxyImageUrl(currentAppInfo.appLogo)}
|
68
|
-
/>
|
39
|
+
<Img src={currentAppInfo.appLogo} alt="Server" width={48} height={48} useProxyFallback />
|
69
40
|
|
70
41
|
<Box
|
71
42
|
sx={{
|
@@ -86,13 +57,7 @@ export default function AuthAppsInfo({
|
|
86
57
|
</Box>
|
87
58
|
|
88
59
|
{/* FIXME: @zhanghan 增加 hover 的效果 */}
|
89
|
-
<Img
|
90
|
-
src={requestAppInfo.appLogo}
|
91
|
-
alt={requestAppInfo.appName}
|
92
|
-
width={48}
|
93
|
-
height={48}
|
94
|
-
fallback={getProxyImageUrl(requestAppInfo.appLogo)}
|
95
|
-
/>
|
60
|
+
<Img src={requestAppInfo.appLogo} alt={requestAppInfo.appName} width={48} height={48} useProxyFallback />
|
96
61
|
</Box>
|
97
62
|
|
98
63
|
<Typography
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { Box } from '@mui/material';
|
2
|
+
|
3
|
+
type LogoSize = number | string;
|
4
|
+
|
5
|
+
export default function DIDWalletLogo({
|
6
|
+
width = '100%',
|
7
|
+
height = '100%',
|
8
|
+
...rest
|
9
|
+
}: {
|
10
|
+
width?: LogoSize;
|
11
|
+
height?: LogoSize;
|
12
|
+
[key: string]: any;
|
13
|
+
}) {
|
14
|
+
const didWalletLogo =
|
15
|
+
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI3ByZWZpeF9fY2xpcDApIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHJ4PSI2IiBmaWxsPSJ1cmwoI3ByZWZpeF9fcGFpbnQwX2xpbmVhcikiLz48ZyBmaWx0ZXI9InVybCgjcHJlZml4X19maWx0ZXIwX2kpIj48cGF0aCBkPSJNMy41MiA3LjM2QTIuNTYgMi41NiAwIDAxNi4wOCA0LjhoMTkuODRhMi41NiAyLjU2IDAgMDEyLjU2IDIuNTZ2MTIuMTZhMi41NiAyLjU2IDAgMDEtMi41NiAyLjU2SDYuMDhhMi41NiAyLjU2IDAgMDEtMi41Ni0yLjU2VjcuMzZ6IiBmaWxsPSIjOUZDQkZGIi8+PC9nPjxnIGZpbHRlcj0idXJsKCNwcmVmaXhfX2ZpbHRlcjFfZCkiPjxwYXRoIGQ9Ik0yLjU2IDkuMjhhMi41NiAyLjU2IDAgMDEyLjU2LTIuNTZoMjEuNzZhMi41NiAyLjU2IDAgMDEyLjU2IDIuNTZ2MTMuNmEyLjU2IDIuNTYgMCAwMS0yLjU2IDIuNTZINS4xMmEyLjU2IDIuNTYgMCAwMS0yLjU2LTIuNTZWOS4yOHoiIGZpbGw9InVybCgjcHJlZml4X19wYWludDFfbGluZWFyKSIvPjwvZz48ZyBmaWx0ZXI9InVybCgjcHJlZml4X19maWx0ZXIyX2QpIj48cGF0aCBkPSJNMCAyMi4zMmwzMi02LjE2VjMySDB2LTkuNjh6IiBmaWxsPSJ1cmwoI3ByZWZpeF9fcGFpbnQyX2xpbmVhcikiLz48L2c+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjUzNiA5LjI0OGg4LjI4OGMuNDA4IDAgLjc0LjMuNzQuNjcydjQuNjRjMCAuMzcxLS4zMzIuNjcyLS43NC42NzJINS41MzZjLS40MDggMC0uNzQtLjMtLjc0LS42NzJ2LS4wNGEuMTU4LjE1OCAwIDEwLS4zMTYgMHYuMDRjMCAuNTMuNDczLjk2IDEuMDU2Ljk2aDguMjg4Yy41ODMgMCAxLjA1Ni0uNDMgMS4wNTYtLjk2VjkuOTJjMC0uNTMtLjQ3My0uOTYtMS4wNTYtLjk2SDUuNTM2Yy0uNTgzIDAtMS4wNTYuNDMtMS4wNTYuOTZ2LjA0YS4xNTguMTU4IDAgMDAuMzE3IDB2LS4wNGMwLS4zNzEuMzMtLjY3Mi43MzktLjY3MnptLTEuMDIzIDQuNjM4YS4xMjcuMTI3IDAgMDAuMDg3LjAzNGgxLjI2N2MuNDcyIDAgLjgzLS4xMDcgMS4wNzYtLjMyMi4yNS0uMjE3LjM4MS0uNTQ4LjM5Ny0uOTkzYTExLjI4MSAxMS4yODEgMCAwMDAtLjczNGMtLjAxMi0uNDI2LS4xNDgtLjc1MS0uNDA2LS45NzUtLjI1OC0uMjI0LS42MjItLjMzNi0xLjA5LS4zMzZINC42YS4xMjcuMTI3IDAgMDAtLjA4Ny4wMzQuMTE3LjExNyAwIDAwLS4wMzMuMDg2djMuMTJjMCAuMDMyLjAxMS4wNi4wMzMuMDg2em0xLjc5NC0uODA2Yy0uMDk5LjEtLjI1My4xNDktLjQ2NC4xNDloLS41MDJWMTEuMjVoLjQ3OGMuMjEgMCAuMzY5LjA1MS40NzQuMTU0LjEwOC4xMDIuMTY2LjI2LjE3Mi40NzUuMDA2LjA5LjAxLjIwOC4wMS4zNTVzLS4wMDQuMjY3LS4wMS4zNmMtLjAwNi4yMjEtLjA1OS4zODMtLjE1OC40ODV6bTEuNjMuODA2YS4xMjcuMTI3IDAgMDAuMDg3LjAzNGguNjRhLjExNi4xMTYgMCAwMC4wODctLjAzNC4xMS4xMSAwIDAwLjAzOC0uMDg2di0zLjEyYS4xMS4xMSAwIDAwLS4wMzgtLjA4Ni4xMTYuMTE2IDAgMDAtLjA4Ni0uMDM0aC0uNjQxYS4xMjcuMTI3IDAgMDAtLjA4Ny4wMzQuMTE3LjExNyAwIDAwLS4wMzMuMDg2djMuMTJjMCAuMDMyLjAxMS4wNi4wMzMuMDg2em0xLjYzNy4wMzRhLjEyNy4xMjcgMCAwMS0uMDg2LS4wMzQuMTI4LjEyOCAwIDAxLS4wMzMtLjA4NnYtMy4xMmMwLS4wMzUuMDEtLjA2NC4wMzMtLjA4NmEuMTI3LjEyNyAwIDAxLjA4Ni0uMDM0aDEuMjQ0Yy40NjkgMCAuODMyLjExMiAxLjA5LjMzNi4yNTkuMjI0LjM5NC41NDkuNDA3Ljk3NGExMS4yNDQgMTEuMjQ0IDAgMDEwIC43MzVjLS4wMTYuNDQ1LS4xNDguNzc2LS4zOTcuOTkzLS4yNDUuMjE1LS42MDQuMzIyLTEuMDc2LjMyMkg5LjU3NHptMS4yNDQtLjY5MWMuMjEgMCAuMzY1LS4wNS40NjQtLjE0OS4wOTktLjEwMi4xNTItLjI2NC4xNTgtLjQ4NWE1LjUyIDUuNTIgMCAwMC4wMS0uMzZjMC0uMTQ3LS4wMDQtLjI2NS0uMDEtLjM1NS0uMDA2LS4yMTQtLjA2NC0uMzczLS4xNzItLjQ3NS0uMTA2LS4xMDMtLjI2My0uMTU0LS40NzQtLjE1NGgtLjQ3OHYxLjk3OGguNTAyem0yLjQ2OC0xLjM4MmEuMjg4LjI4OCAwIDAxLS4yODgtLjI4Ni4yODguMjg4IDAgMDEuNTc2IDBjMCAuMTU4LS4xMy4yODYtLjI4OC4yODZ6bTAgMS40OTVhLjI4OC4yODggMCAwMS0uMjg4LS4yODYuMjg4LjI4OCAwIDAxLjU3NiAwYzAgLjE1OC0uMTMuMjg3LS4yODguMjg3eiIgZmlsbD0iIzQ1OThGQSIvPjwvZz48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9InByZWZpeF9fcGFpbnQwX2xpbmVhciIgeDE9IjE2IiB5MT0iMCIgeDI9IjE2IiB5Mj0iMzIiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBzdG9wLWNvbG9yPSIjNEY5REY2Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMEE3OUY4Ii8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9InByZWZpeF9fcGFpbnQxX2xpbmVhciIgeDE9IjE2IiB5MT0iNi43MiIgeDI9IjE2IiB5Mj0iMjUuNDQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBzdG9wLWNvbG9yPSIjZmZmIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjRUNFRkZGIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9InByZWZpeF9fcGFpbnQyX2xpbmVhciIgeDE9IjE2IiB5MT0iMTkuMiIgeDI9IjE4LjQ4IiB5Mj0iMzIiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9Ii4wMDciIHN0b3AtY29sb3I9IiM3N0IyRjYiLz48c3RvcCBvZmZzZXQ9Ii4wNTUiIHN0b3AtY29sb3I9IiM0RjlERjYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM0NTk4RkEiLz48L2xpbmVhckdyYWRpZW50PjxmaWx0ZXIgaWQ9InByZWZpeF9fZmlsdGVyMF9pIiB4PSIzLjUyIiB5PSIxLjgiIHdpZHRoPSIyNC45NiIgaGVpZ2h0PSIyMC4yOCIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPjxmZUZsb29kIGZsb29kLW9wYWNpdHk9IjAiIHJlc3VsdD0iQmFja2dyb3VuZEltYWdlRml4Ii8+PGZlQmxlbmQgaW49IlNvdXJjZUdyYXBoaWMiIGluMj0iQmFja2dyb3VuZEltYWdlRml4IiByZXN1bHQ9InNoYXBlIi8+PGZlQ29sb3JNYXRyaXggaW49IlNvdXJjZUFscGhhIiB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDEyNyAwIiByZXN1bHQ9ImhhcmRBbHBoYSIvPjxmZU9mZnNldCBkeT0iLTMiLz48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIyIi8+PGZlQ29tcG9zaXRlIGluMj0iaGFyZEFscGhhIiBvcGVyYXRvcj0iYXJpdGhtZXRpYyIgazI9Ii0xIiBrMz0iMSIvPjxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAxIDAgMCAwIDAgMSAwIDAgMCAwIDEgMCAwIDAgMC4yIDAiLz48ZmVCbGVuZCBpbjI9InNoYXBlIiByZXN1bHQ9ImVmZmVjdDFfaW5uZXJTaGFkb3ciLz48L2ZpbHRlcj48ZmlsdGVyIGlkPSJwcmVmaXhfX2ZpbHRlcjFfZCIgeD0iLTEuNDQiIHk9IjEuNzIiIHdpZHRoPSIzNC44OCIgaGVpZ2h0PSIyNi43MiIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPjxmZUZsb29kIGZsb29kLW9wYWNpdHk9IjAiIHJlc3VsdD0iQmFja2dyb3VuZEltYWdlRml4Ii8+PGZlQ29sb3JNYXRyaXggaW49IlNvdXJjZUFscGhhIiB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDEyNyAwIiByZXN1bHQ9ImhhcmRBbHBoYSIvPjxmZU9mZnNldCBkeT0iLTEiLz48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIyIi8+PGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDAuMjIwNzY3IDAgMCAwIDAgMC40NzA4MDMgMCAwIDAgMCAwLjcwMTYwNSAwIDAgMCAwLjE4IDAiLz48ZmVCbGVuZCBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJlZmZlY3QxX2Ryb3BTaGFkb3ciLz48ZmVCbGVuZCBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJlZmZlY3QxX2Ryb3BTaGFkb3ciIHJlc3VsdD0ic2hhcGUiLz48L2ZpbHRlcj48ZmlsdGVyIGlkPSJwcmVmaXhfX2ZpbHRlcjJfZCIgeD0iLTUiIHk9IjExLjE2IiB3aWR0aD0iNDIiIGhlaWdodD0iMjUuODQiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj48ZmVGbG9vZCBmbG9vZC1vcGFjaXR5PSIwIiByZXN1bHQ9IkJhY2tncm91bmRJbWFnZUZpeCIvPjxmZUNvbG9yTWF0cml4IGluPSJTb3VyY2VBbHBoYSIgdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAxMjcgMCIgcmVzdWx0PSJoYXJkQWxwaGEiLz48ZmVPZmZzZXQvPjxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjIuNSIvPjxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAwLjE0MzgyIDAgMCAwIDAgMC4yMDUwNjUgMCAwIDAgMCAwLjUyMjYzNCAwIDAgMCAwLjI1IDAiLz48ZmVCbGVuZCBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJlZmZlY3QxX2Ryb3BTaGFkb3ciLz48ZmVCbGVuZCBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJlZmZlY3QxX2Ryb3BTaGFkb3ciIHJlc3VsdD0ic2hhcGUiLz48L2ZpbHRlcj48Y2xpcFBhdGggaWQ9InByZWZpeF9fY2xpcDAiPjxyZWN0IHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgcng9IjYiIGZpbGw9IiNmZmYiLz48L2NsaXBQYXRoPjwvZGVmcz48L3N2Zz4=';
|
16
|
+
|
17
|
+
return <Box component="img" width={width} height={height} alt="did-wallet-logo" {...rest} src={didWalletLogo} />;
|
18
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
type LogoSize = number | string;
|
2
|
+
|
3
|
+
export default function GithubLogo({
|
4
|
+
width = 24,
|
5
|
+
height = 24,
|
6
|
+
...props
|
7
|
+
}: {
|
8
|
+
width?: LogoSize;
|
9
|
+
height?: LogoSize;
|
10
|
+
[key: string]: any;
|
11
|
+
}) {
|
12
|
+
return (
|
13
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 250" width={width} height={height} {...props}>
|
14
|
+
<path d="M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46c6.397 1.185 8.746-2.777 8.746-6.158c0-3.052-.12-13.135-.174-23.83c-35.61 7.742-43.124-15.103-43.124-15.103c-5.823-14.795-14.213-18.73-14.213-18.73c-11.613-7.944.876-7.78.876-7.78c12.853.902 19.621 13.19 19.621 13.19c11.417 19.568 29.945 13.911 37.249 10.64c1.149-8.272 4.466-13.92 8.127-17.116c-28.431-3.236-58.318-14.212-58.318-63.258c0-13.975 5-25.394 13.188-34.358c-1.329-3.224-5.71-16.242 1.24-33.874c0 0 10.749-3.44 35.21 13.121c10.21-2.836 21.16-4.258 32.038-4.307c10.878.049 21.837 1.47 32.066 4.307c24.431-16.56 35.165-13.12 35.165-13.12c6.967 17.63 2.584 30.65 1.255 33.873c8.207 8.964 13.173 20.383 13.173 34.358c0 49.163-29.944 59.988-58.447 63.157c4.591 3.972 8.682 11.762 8.682 23.704c0 17.126-.148 30.91-.148 35.126c0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002C256 57.307 198.691 0 128.001 0m-80.06 182.34c-.282.636-1.283.827-2.194.39c-.929-.417-1.45-1.284-1.15-1.922c.276-.655 1.279-.838 2.205-.399c.93.418 1.46 1.293 1.139 1.931m6.296 5.618c-.61.566-1.804.303-2.614-.591c-.837-.892-.994-2.086-.375-2.66c.63-.566 1.787-.301 2.626.591c.838.903 1 2.088.363 2.66m4.32 7.188c-.785.545-2.067.034-2.86-1.104c-.784-1.138-.784-2.503.017-3.05c.795-.547 2.058-.055 2.861 1.075c.782 1.157.782 2.522-.019 3.08m7.304 8.325c-.701.774-2.196.566-3.29-.49c-1.119-1.032-1.43-2.496-.726-3.27c.71-.776 2.213-.558 3.315.49c1.11 1.03 1.45 2.505.701 3.27m9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033c-1.448-.439-2.395-1.613-2.103-2.626c.301-1.01 1.747-1.484 3.207-1.028c1.446.436 2.396 1.602 2.095 2.622m10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95c-1.53.034-2.769-.82-2.786-1.86c0-1.065 1.202-1.932 2.733-1.958c1.522-.03 2.768.818 2.768 1.868m10.555-.405c.182 1.03-.875 2.088-2.387 2.37c-1.485.271-2.861-.365-3.05-1.386c-.184-1.056.893-2.114 2.376-2.387c1.514-.263 2.868.356 3.061 1.403" />
|
15
|
+
</svg>
|
16
|
+
);
|
17
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import { memo } from 'react';
|
2
|
+
import mailOutlineRoundedIcon from '@iconify-icons/material-symbols/mail-outline-rounded';
|
3
|
+
import appleIcon from '@iconify-icons/logos/apple';
|
4
|
+
import googleIcon from '@iconify-icons/logos/google-icon';
|
5
|
+
import auth0Icon from '@iconify-icons/logos/auth0-icon';
|
6
|
+
import passKeyRoundedIcon from '@iconify-icons/material-symbols/passkey-rounded';
|
7
|
+
import { Icon } from '@iconify/react';
|
8
|
+
import { Box, BoxProps, SxProps } from '@mui/material';
|
9
|
+
|
10
|
+
import { LOGIN_PROVIDER } from '../Util/constant';
|
11
|
+
import { mergeSx } from '../Util/style';
|
12
|
+
import DIDWalletLogo from './icons/did-wallet-logo';
|
13
|
+
import GithubLogo from './icons/github-logo';
|
14
|
+
|
15
|
+
function ProviderIcon({
|
16
|
+
provider = 'wallet',
|
17
|
+
...rest
|
18
|
+
}: {
|
19
|
+
provider?: (typeof LOGIN_PROVIDER)[keyof typeof LOGIN_PROVIDER] | 'wallet-web';
|
20
|
+
} & BoxProps) {
|
21
|
+
if (['wallet', 'wallet-web'].includes(provider)) {
|
22
|
+
// @ts-ignore
|
23
|
+
return <DIDWalletLogo {...rest} />;
|
24
|
+
}
|
25
|
+
|
26
|
+
if (provider === LOGIN_PROVIDER.GITHUB) {
|
27
|
+
return (
|
28
|
+
<Box component="span" {...rest} sx={mergeSx({ display: 'inline-block' }, rest.sx as SxProps)}>
|
29
|
+
<GithubLogo width="100%" height="100%" fill="currentColor" />
|
30
|
+
</Box>
|
31
|
+
);
|
32
|
+
}
|
33
|
+
|
34
|
+
const iconMap = {
|
35
|
+
[LOGIN_PROVIDER.AUTH0]: auth0Icon,
|
36
|
+
[LOGIN_PROVIDER.EMAIL]: mailOutlineRoundedIcon,
|
37
|
+
[LOGIN_PROVIDER.APPLE]: appleIcon,
|
38
|
+
[LOGIN_PROVIDER.GOOGLE]: googleIcon,
|
39
|
+
[LOGIN_PROVIDER.PASSKEY]: passKeyRoundedIcon,
|
40
|
+
[LOGIN_PROVIDER.TWITTER]: {
|
41
|
+
body: '<path fill="currentColor" d="M149.079 108.399L242.33 0h-22.098l-80.97 94.12L74.59 0H0l97.796 142.328L0 256h22.1l85.507-99.395L175.905 256h74.59L149.073 108.399zM118.81 143.58l-9.909-14.172l-78.84-112.773h33.943l63.625 91.011l9.909 14.173l82.705 118.3H186.3l-67.49-96.533z"/>',
|
42
|
+
width: 251,
|
43
|
+
height: 251,
|
44
|
+
},
|
45
|
+
};
|
46
|
+
|
47
|
+
return iconMap[provider] ? (
|
48
|
+
<Box
|
49
|
+
component={Icon}
|
50
|
+
icon={iconMap[provider]}
|
51
|
+
fill="currentColor"
|
52
|
+
{...rest}
|
53
|
+
sx={mergeSx(
|
54
|
+
{ width: '100%', height: '100%' },
|
55
|
+
provider === LOGIN_PROVIDER.TWITTER ? { scale: '0.8' } : {},
|
56
|
+
rest.sx as SxProps
|
57
|
+
)}
|
58
|
+
/>
|
59
|
+
) : null;
|
60
|
+
}
|
61
|
+
|
62
|
+
export default memo(ProviderIcon);
|
package/src/Img/index.jsx
CHANGED
@@ -7,6 +7,29 @@ import { Icon } from '@iconify/react';
|
|
7
7
|
import { Box } from '@mui/material';
|
8
8
|
import noop from 'lodash/noop';
|
9
9
|
import { mergeSx } from '../Util/style';
|
10
|
+
import { BLOCKLET_SERVICE_PATH_PREFIX } from '../Util/constant';
|
11
|
+
|
12
|
+
const getProxyImageUrl = (url) => {
|
13
|
+
if (!url) return '';
|
14
|
+
|
15
|
+
try {
|
16
|
+
// 检查是否是一个有效的URL
|
17
|
+
const urlObj = new URL(url);
|
18
|
+
|
19
|
+
// 检查协议是否是https
|
20
|
+
if (urlObj.protocol !== 'https:') {
|
21
|
+
console.warn('Image URL must use HTTPS protocol:', url);
|
22
|
+
return '';
|
23
|
+
}
|
24
|
+
|
25
|
+
// 返回代理URL
|
26
|
+
return `${BLOCKLET_SERVICE_PATH_PREFIX}/proxy?url=${encodeURIComponent(url)}`;
|
27
|
+
} catch (error) {
|
28
|
+
// URL construction failed, indicating invalid URL format
|
29
|
+
console.warn('Invalid image URL format:', url, error);
|
30
|
+
return '';
|
31
|
+
}
|
32
|
+
};
|
10
33
|
|
11
34
|
/**
|
12
35
|
* @typedef {Object} ImgExProps
|
@@ -22,6 +45,7 @@ import { mergeSx } from '../Util/style';
|
|
22
45
|
* @property {boolean} [lazy=true]
|
23
46
|
* @property {string} [placeholder]
|
24
47
|
* @property {string} [fallback]
|
48
|
+
* @property {boolean} [useProxyFallback=false] - 是否使用代理 fallback, 用于解决 CSP 的问题
|
25
49
|
* @property {string} [className='']
|
26
50
|
* @property {function} [onError=() => {}]
|
27
51
|
* @property {function} [onSuccess=() => {}]
|
@@ -52,6 +76,7 @@ function Img({
|
|
52
76
|
size = 'cover',
|
53
77
|
position = 'top center',
|
54
78
|
src,
|
79
|
+
useProxyFallback = false, // 是否使用代理 fallback, 用于解决 CSP 的问题
|
55
80
|
placeholder = null,
|
56
81
|
fallback = null,
|
57
82
|
style = null,
|
@@ -66,19 +91,29 @@ function Img({
|
|
66
91
|
const [imgState, setImgState] = useState('init');
|
67
92
|
const [fallbackError, setFallbackError] = useState(false);
|
68
93
|
|
94
|
+
const fallbackSrc = useMemo(() => {
|
95
|
+
if (fallback) {
|
96
|
+
return fallback;
|
97
|
+
}
|
98
|
+
if (useProxyFallback && src) {
|
99
|
+
return getProxyImageUrl(src);
|
100
|
+
}
|
101
|
+
return fallback;
|
102
|
+
}, [src, useProxyFallback, fallback]);
|
103
|
+
|
69
104
|
const actualSrc = useMemo(() => {
|
70
105
|
switch (imgState) {
|
71
106
|
case 'init':
|
72
107
|
case 'loading':
|
73
108
|
return placeholder;
|
74
109
|
case 'error':
|
75
|
-
return fallbackError ? null :
|
110
|
+
return fallbackError ? null : fallbackSrc;
|
76
111
|
case 'loaded':
|
77
112
|
return src;
|
78
113
|
default:
|
79
114
|
return null;
|
80
115
|
}
|
81
|
-
}, [placeholder,
|
116
|
+
}, [placeholder, fallbackSrc, src, imgState, fallbackError]);
|
82
117
|
|
83
118
|
const actualRatio = width && height ? (100 * height) / width : ratio * 100;
|
84
119
|
|
@@ -112,9 +147,8 @@ function Img({
|
|
112
147
|
setImgState('loaded');
|
113
148
|
onSuccess();
|
114
149
|
};
|
115
|
-
img.onerror = (
|
150
|
+
img.onerror = () => {
|
116
151
|
setImgState('error');
|
117
|
-
onError(err);
|
118
152
|
};
|
119
153
|
}
|
120
154
|
|
@@ -125,18 +159,21 @@ function Img({
|
|
125
159
|
|
126
160
|
// 处理 fallback 加载
|
127
161
|
useEffect(() => {
|
128
|
-
if (imgState === 'error' &&
|
162
|
+
if (imgState === 'error' && fallbackSrc && !fallbackError) {
|
129
163
|
const fallbackImg = new Image();
|
130
|
-
fallbackImg.src =
|
164
|
+
fallbackImg.src = fallbackSrc;
|
131
165
|
fallbackImg.onload = () => {
|
132
166
|
// fallback 加载成功,保持在 error 状态但显示 fallback
|
133
167
|
};
|
134
|
-
fallbackImg.onerror = () => {
|
168
|
+
fallbackImg.onerror = (err) => {
|
135
169
|
// fallback 也加载失败
|
136
170
|
setFallbackError(true);
|
171
|
+
if (imgState === 'error') {
|
172
|
+
onError(err);
|
173
|
+
}
|
137
174
|
};
|
138
175
|
}
|
139
|
-
}, [imgState,
|
176
|
+
}, [imgState, fallbackSrc, fallbackError, onError]);
|
140
177
|
|
141
178
|
return (
|
142
179
|
// paddingTop 要求元素本身的宽度为 100%,所以只能加一个外层元素去限制宽度
|
@@ -183,7 +220,7 @@ function Img({
|
|
183
220
|
rest.sx
|
184
221
|
)}>
|
185
222
|
<div className={`image ${className} ${classes.root}`} style={mergedStyle}>
|
186
|
-
{(fallbackError || (!
|
223
|
+
{(fallbackError || (!fallbackSrc && imgState === 'error')) && (
|
187
224
|
<div className="image--state" title="Image load error">
|
188
225
|
<Icon icon={WarningRoundedIcon} className="image--icon" />
|
189
226
|
</div>
|
@@ -215,6 +252,7 @@ Img.propTypes = {
|
|
215
252
|
className: PropTypes.string,
|
216
253
|
onError: PropTypes.func,
|
217
254
|
onSuccess: PropTypes.func,
|
255
|
+
useProxyFallback: PropTypes.bool,
|
218
256
|
};
|
219
257
|
|
220
258
|
export default Img;
|