@arcblock/ux 3.0.32 → 3.0.34
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/Img/index.d.ts +9 -1
- package/lib/Img/index.js +83 -64
- package/lib/LoadingMask/index.js +27 -17
- package/lib/UserCard/components.js +15 -14
- package/lib/UserCard/index.js +41 -31
- 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/Img/index.jsx +62 -7
- package/src/LoadingMask/index.tsx +12 -1
- package/src/UserCard/components.tsx +1 -0
- package/src/UserCard/index.tsx +23 -6
package/lib/Avatar/index.d.ts
CHANGED
@@ -21,6 +21,7 @@ export type AvatarProps = {
|
|
21
21
|
shape?: "" | "rectangle" | "square" | "hexagon" | "circle";
|
22
22
|
blockiesPadding?: true | false;
|
23
23
|
responsive?: false | true;
|
24
|
+
useProxyFallback?: boolean;
|
24
25
|
} & Omit<import('../Img').ImgProps, "size" | "src">;
|
25
26
|
export { Avatar as AvatarProps };
|
26
27
|
/**
|
@@ -34,6 +35,7 @@ export { Avatar as AvatarProps };
|
|
34
35
|
* shape?: '' | 'rectangle' | 'square' | 'hexagon' | 'circle';
|
35
36
|
* blockiesPadding?: true | false;
|
36
37
|
* responsive?: false | true;
|
38
|
+
* useProxyFallback?: boolean;
|
37
39
|
* } & Omit<import('../Img').ImgProps, 'size' | 'src'>} AvatarProps
|
38
40
|
*/
|
39
41
|
/**
|
@@ -51,6 +53,7 @@ declare namespace Avatar {
|
|
51
53
|
let shape: PropTypes.Requireable<string>;
|
52
54
|
let blockiesPadding: PropTypes.Requireable<boolean>;
|
53
55
|
let responsive: PropTypes.Requireable<boolean>;
|
56
|
+
let useProxyFallback: PropTypes.Requireable<boolean>;
|
54
57
|
}
|
55
58
|
export { propTypes_1 as propTypes };
|
56
59
|
}
|
package/lib/Avatar/index.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { jsx as o } from "react/jsx-runtime";
|
2
|
-
import { useState as
|
3
|
-
import
|
2
|
+
import { useState as I, useMemo as P } from "react";
|
3
|
+
import a from "prop-types";
|
4
4
|
import { ErrorBoundary as z } from "react-error-boundary";
|
5
5
|
import { Shape as D } from "@arcblock/did-motif";
|
6
6
|
import { Box as u } from "@mui/material";
|
@@ -13,12 +13,12 @@ import { DID_PREFIX as f } from "../Util/constant.js";
|
|
13
13
|
function d({ ...s }) {
|
14
14
|
const r = Object.assign({}, s);
|
15
15
|
n(r.did) && (r.did = ""), n(r.size) && (r.size = 36), n(r.variant) && (r.variant = "default"), n(r.animation) && (r.animation = !1), n(r.shape) && (r.shape = ""), n(r.blockiesPadding) && (r.blockiesPadding = !0), n(r.responsive) && (r.responsive = !1);
|
16
|
-
const [
|
16
|
+
const [l, h] = I(!1), g = E(r, d, []), { did: i = "", size: e, src: p, variant: b, animation: v, shape: x, blockiesPadding: y, responsive: k, ...t } = g, c = P(() => R(i) ? T.createIcon({
|
17
17
|
seed: i.replace(f, "").toLowerCase(),
|
18
18
|
size: 8,
|
19
19
|
scale: 16
|
20
20
|
}).toDataURL() : null, [i]);
|
21
|
-
if (p && !
|
21
|
+
if (p && !l)
|
22
22
|
return /* @__PURE__ */ o(
|
23
23
|
m,
|
24
24
|
{
|
@@ -26,8 +26,9 @@ function d({ ...s }) {
|
|
26
26
|
src: p,
|
27
27
|
alt: i,
|
28
28
|
onError: () => h(!0),
|
29
|
-
...
|
30
|
-
className: `avatar-img--${b} ${
|
29
|
+
...t,
|
30
|
+
className: `avatar-img--${b} ${t?.className || ""}`,
|
31
|
+
useProxyFallback: !0,
|
31
32
|
sx: {
|
32
33
|
"& .avatar-img--rounded": {
|
33
34
|
borderRadius: "4px",
|
@@ -37,17 +38,17 @@ function d({ ...s }) {
|
|
37
38
|
borderRadius: "100%",
|
38
39
|
overflow: "hidden"
|
39
40
|
},
|
40
|
-
...
|
41
|
+
...t.sx
|
41
42
|
}
|
42
43
|
}
|
43
44
|
);
|
44
|
-
if (
|
45
|
+
if (c) {
|
45
46
|
if (y) {
|
46
|
-
const
|
47
|
+
const w = e > 24 ? 4 : 2;
|
47
48
|
return /* @__PURE__ */ o(
|
48
49
|
u,
|
49
50
|
{
|
50
|
-
...
|
51
|
+
...t,
|
51
52
|
sx: {
|
52
53
|
display: "flex",
|
53
54
|
alignItems: "center",
|
@@ -63,13 +64,13 @@ function d({ ...s }) {
|
|
63
64
|
borderRadius: `${Math.min(10, Math.floor(0.1 * e + 2))}px`,
|
64
65
|
background: "#ddd"
|
65
66
|
},
|
66
|
-
...
|
67
|
+
...t.sx
|
67
68
|
},
|
68
|
-
children: /* @__PURE__ */ o("div", { className: "blocky-icon-inner", children: /* @__PURE__ */ o(m, { width: e * 0.7 -
|
69
|
+
children: /* @__PURE__ */ o("div", { className: "blocky-icon-inner", children: /* @__PURE__ */ o(m, { width: e * 0.7 - w * 2, src: c, alt: i }) })
|
69
70
|
}
|
70
71
|
);
|
71
72
|
}
|
72
|
-
return /* @__PURE__ */ o(m, { ...
|
73
|
+
return /* @__PURE__ */ o(m, { ...t, width: e, src: c, alt: i, style: { marginRight: 4 } });
|
73
74
|
}
|
74
75
|
if (i)
|
75
76
|
return /* @__PURE__ */ o(
|
@@ -79,25 +80,26 @@ function d({ ...s }) {
|
|
79
80
|
size: e,
|
80
81
|
animation: v,
|
81
82
|
shape: D[(x || "").toUpperCase()],
|
82
|
-
responsive:
|
83
|
-
...
|
83
|
+
responsive: k,
|
84
|
+
...t
|
84
85
|
}
|
85
86
|
);
|
86
87
|
throw new Error(`Invalid DID: ${i}`);
|
87
88
|
}
|
88
89
|
d.propTypes = {
|
89
|
-
did:
|
90
|
-
size:
|
91
|
-
variant:
|
90
|
+
did: a.string,
|
91
|
+
size: a.number,
|
92
|
+
variant: a.oneOf(["circle", "rounded", "default"]),
|
92
93
|
// animation 仅对 did motif 有效
|
93
|
-
animation:
|
94
|
+
animation: a.bool,
|
94
95
|
// shape 仅对 did motif 有效, 明确指定 motif shape, 而非由 did role type 自动推断 shape
|
95
|
-
shape:
|
96
|
-
blockiesPadding:
|
97
|
-
responsive:
|
96
|
+
shape: a.oneOf(["", "rectangle", "square", "hexagon", "circle"]),
|
97
|
+
blockiesPadding: a.bool,
|
98
|
+
responsive: a.bool,
|
99
|
+
useProxyFallback: a.bool
|
98
100
|
};
|
99
101
|
function $(s) {
|
100
|
-
const r = s.size || 36,
|
102
|
+
const r = s.size || 36, l = { rounded: "4px", circle: "100%" }[s.variant] || 0;
|
101
103
|
return /* @__PURE__ */ o(
|
102
104
|
z,
|
103
105
|
{
|
@@ -108,7 +110,7 @@ function $(s) {
|
|
108
110
|
width: r,
|
109
111
|
height: r,
|
110
112
|
bgcolor: "grey.300",
|
111
|
-
borderRadius:
|
113
|
+
borderRadius: l
|
112
114
|
}
|
113
115
|
}
|
114
116
|
),
|
@@ -1,21 +1,12 @@
|
|
1
|
-
import { jsxs as
|
2
|
-
import { Box as
|
1
|
+
import { jsxs as r, jsx as t } from "react/jsx-runtime";
|
2
|
+
import { Box as e, Typography as l } from "@mui/material";
|
3
3
|
import i from "../../Img/index.js";
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
try {
|
8
|
-
return new URL(e).protocol !== "https:" ? (console.warn("Image URL must use HTTPS protocol:", e), "") : `${s}/proxy?url=${e}`;
|
9
|
-
} catch (t) {
|
10
|
-
return console.warn("Invalid image URL format:", e, t), "";
|
11
|
-
}
|
12
|
-
};
|
13
|
-
function g({
|
14
|
-
requestAppInfo: e,
|
15
|
-
currentAppInfo: t
|
4
|
+
function m({
|
5
|
+
requestAppInfo: a,
|
6
|
+
currentAppInfo: o
|
16
7
|
}) {
|
17
|
-
return /* @__PURE__ */
|
18
|
-
|
8
|
+
return /* @__PURE__ */ r(
|
9
|
+
e,
|
19
10
|
{
|
20
11
|
sx: {
|
21
12
|
textAlign: "center",
|
@@ -25,8 +16,8 @@ function g({
|
|
25
16
|
gap: 2
|
26
17
|
},
|
27
18
|
children: [
|
28
|
-
/* @__PURE__ */
|
29
|
-
|
19
|
+
/* @__PURE__ */ r(
|
20
|
+
e,
|
30
21
|
{
|
31
22
|
sx: {
|
32
23
|
display: "flex",
|
@@ -34,18 +25,9 @@ function g({
|
|
34
25
|
justifyContent: "center"
|
35
26
|
},
|
36
27
|
children: [
|
37
|
-
/* @__PURE__ */ o
|
38
|
-
|
39
|
-
|
40
|
-
src: t.appLogo,
|
41
|
-
alt: "Server",
|
42
|
-
width: 48,
|
43
|
-
height: 48,
|
44
|
-
fallback: l(t.appLogo)
|
45
|
-
}
|
46
|
-
),
|
47
|
-
/* @__PURE__ */ a(
|
48
|
-
r,
|
28
|
+
/* @__PURE__ */ t(i, { src: o.appLogo, alt: "Server", width: 48, height: 48, useProxyFallback: !0 }),
|
29
|
+
/* @__PURE__ */ r(
|
30
|
+
e,
|
49
31
|
{
|
50
32
|
sx: {
|
51
33
|
mx: 2,
|
@@ -60,27 +42,18 @@ function g({
|
|
60
42
|
}
|
61
43
|
},
|
62
44
|
children: [
|
63
|
-
/* @__PURE__ */
|
64
|
-
/* @__PURE__ */
|
65
|
-
/* @__PURE__ */
|
45
|
+
/* @__PURE__ */ t(e, { className: "dot" }),
|
46
|
+
/* @__PURE__ */ t(e, { className: "dot" }),
|
47
|
+
/* @__PURE__ */ t(e, { className: "dot" })
|
66
48
|
]
|
67
49
|
}
|
68
50
|
),
|
69
|
-
/* @__PURE__ */
|
70
|
-
i,
|
71
|
-
{
|
72
|
-
src: e.appLogo,
|
73
|
-
alt: e.appName,
|
74
|
-
width: 48,
|
75
|
-
height: 48,
|
76
|
-
fallback: l(e.appLogo)
|
77
|
-
}
|
78
|
-
)
|
51
|
+
/* @__PURE__ */ t(i, { src: a.appLogo, alt: a.appName, width: 48, height: 48, useProxyFallback: !0 })
|
79
52
|
]
|
80
53
|
}
|
81
54
|
),
|
82
|
-
/* @__PURE__ */
|
83
|
-
|
55
|
+
/* @__PURE__ */ r(
|
56
|
+
l,
|
84
57
|
{
|
85
58
|
sx: {
|
86
59
|
mb: 1,
|
@@ -89,7 +62,7 @@ function g({
|
|
89
62
|
children: [
|
90
63
|
"Authorize",
|
91
64
|
" ",
|
92
|
-
/* @__PURE__ */
|
65
|
+
/* @__PURE__ */ t(e, { component: "span", sx: { color: "primary.main" }, children: a.appName })
|
93
66
|
]
|
94
67
|
}
|
95
68
|
)
|
@@ -98,5 +71,5 @@ function g({
|
|
98
71
|
);
|
99
72
|
}
|
100
73
|
export {
|
101
|
-
|
74
|
+
m as default
|
102
75
|
};
|
package/lib/Img/index.d.ts
CHANGED
@@ -19,6 +19,13 @@ export type ImgExProps = {
|
|
19
19
|
lazy?: boolean | undefined;
|
20
20
|
placeholder?: string | undefined;
|
21
21
|
fallback?: string | undefined;
|
22
|
+
/**
|
23
|
+
* - 是否使用代理 fallback, 用于解决 CSP 的问题
|
24
|
+
*/
|
25
|
+
/**
|
26
|
+
* - 是否使用代理 fallback, 用于解决 CSP 的问题
|
27
|
+
*/
|
28
|
+
useProxyFallback?: boolean | undefined;
|
22
29
|
className?: string | undefined;
|
23
30
|
onError?: Function | undefined;
|
24
31
|
onSuccess?: Function | undefined;
|
@@ -29,7 +36,7 @@ export type ImgProps = ImgExProps & import('@mui/material').BoxProps;
|
|
29
36
|
* @param {ImgProps} props
|
30
37
|
* @returns {React.ReactComponentElement}
|
31
38
|
*/
|
32
|
-
declare function Img({ lazy, width, height, repeat, ratio, alt, size, position, src, placeholder, fallback, style, className, onError, onSuccess, ...rest }: ImgProps): import('react').ReactComponentElement<any, Pick<any, string | number | symbol>>;
|
39
|
+
declare function Img({ lazy, width, height, repeat, ratio, alt, size, position, src, useProxyFallback, placeholder, fallback, style, className, onError, onSuccess, ...rest }: ImgProps): import('react').ReactComponentElement<any, Pick<any, string | number | symbol>>;
|
33
40
|
declare namespace Img {
|
34
41
|
namespace propTypes {
|
35
42
|
let src: PropTypes.Validator<string>;
|
@@ -47,5 +54,6 @@ declare namespace Img {
|
|
47
54
|
let className: PropTypes.Requireable<string>;
|
48
55
|
let onError: PropTypes.Requireable<(...args: any[]) => any>;
|
49
56
|
let onSuccess: PropTypes.Requireable<(...args: any[]) => any>;
|
57
|
+
let useProxyFallback: PropTypes.Requireable<boolean>;
|
50
58
|
}
|
51
59
|
}
|
package/lib/Img/index.js
CHANGED
@@ -1,83 +1,101 @@
|
|
1
|
-
import { jsx as
|
2
|
-
import { useState as
|
1
|
+
import { jsx as s, jsxs as F } from "react/jsx-runtime";
|
2
|
+
import { useState as R, useMemo as d, useEffect as w } from "react";
|
3
3
|
import e from "prop-types";
|
4
|
-
import { useInView as
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import { Icon as
|
4
|
+
import { useInView as V } from "react-intersection-observer";
|
5
|
+
import W from "@iconify-icons/material-symbols/warning-rounded";
|
6
|
+
import X from "@iconify-icons/material-symbols/image-rounded";
|
7
|
+
import { Icon as k } from "@iconify/react";
|
8
8
|
import { Box as B } from "@mui/material";
|
9
|
-
import
|
10
|
-
import { mergeSx as
|
11
|
-
|
12
|
-
|
9
|
+
import $ from "lodash/noop";
|
10
|
+
import { mergeSx as q } from "../Util/style.js";
|
11
|
+
import { BLOCKLET_SERVICE_PATH_PREFIX as A } from "../Util/constant.js";
|
12
|
+
const D = (r) => {
|
13
|
+
if (!r) return "";
|
14
|
+
try {
|
15
|
+
return new URL(r).protocol !== "https:" ? (console.warn("Image URL must use HTTPS protocol:", r), "") : `${A}/proxy?url=${encodeURIComponent(r)}`;
|
16
|
+
} catch (t) {
|
17
|
+
return console.warn("Invalid image URL format:", r, t), "";
|
18
|
+
}
|
19
|
+
}, K = "Img", v = {
|
20
|
+
root: `${K}-root`
|
13
21
|
};
|
14
|
-
function
|
15
|
-
lazy:
|
16
|
-
width:
|
17
|
-
height:
|
18
|
-
repeat:
|
19
|
-
ratio:
|
20
|
-
alt:
|
21
|
-
size:
|
22
|
-
position:
|
23
|
-
src:
|
24
|
-
|
25
|
-
fallback
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
function M({
|
23
|
+
lazy: r = !0,
|
24
|
+
width: t = null,
|
25
|
+
height: f = null,
|
26
|
+
repeat: E = "no-repeat",
|
27
|
+
ratio: N = 1,
|
28
|
+
alt: P = null,
|
29
|
+
size: p = "cover",
|
30
|
+
position: I = "top center",
|
31
|
+
src: n,
|
32
|
+
useProxyFallback: b = !1,
|
33
|
+
// 是否使用代理 fallback, 用于解决 CSP 的问题
|
34
|
+
placeholder: c = null,
|
35
|
+
fallback: m = null,
|
36
|
+
style: T = null,
|
37
|
+
className: j = "",
|
38
|
+
onError: h = $,
|
39
|
+
onSuccess: L = $,
|
40
|
+
...y
|
31
41
|
}) {
|
32
|
-
const [
|
42
|
+
const [U, x] = r ? V({ threshold: 0, triggerOnce: !0 }) : [null, !0], [o, g] = R("init"), [l, S] = R(!1), a = d(() => m || (b && n ? D(n) : m), [n, b, m]), u = d(() => {
|
33
43
|
switch (o) {
|
34
44
|
case "init":
|
35
45
|
case "loading":
|
36
|
-
return
|
46
|
+
return c;
|
37
47
|
case "error":
|
38
|
-
return a;
|
48
|
+
return l ? null : a;
|
39
49
|
case "loaded":
|
40
|
-
return
|
50
|
+
return n;
|
41
51
|
default:
|
42
52
|
return null;
|
43
53
|
}
|
44
|
-
}, [
|
54
|
+
}, [c, a, n, o, l]), _ = t && f ? 100 * f / t : N * 100, C = d(
|
45
55
|
() => ({
|
46
|
-
backgroundImage:
|
47
|
-
backgroundPosition:
|
48
|
-
backgroundSize:
|
49
|
-
backgroundRepeat:
|
50
|
-
paddingTop: `${
|
56
|
+
backgroundImage: u ? `url(${u})` : "",
|
57
|
+
backgroundPosition: I,
|
58
|
+
backgroundSize: p,
|
59
|
+
backgroundRepeat: E,
|
60
|
+
paddingTop: `${_}%`
|
51
61
|
}),
|
52
62
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
53
|
-
[
|
54
|
-
),
|
55
|
-
...
|
63
|
+
[u, I, p, o]
|
64
|
+
), H = {
|
65
|
+
...T,
|
56
66
|
display: "inline-block",
|
57
|
-
width:
|
67
|
+
width: t ? `${t}px` : "100%"
|
58
68
|
};
|
59
|
-
function
|
60
|
-
const
|
61
|
-
|
62
|
-
|
63
|
-
},
|
64
|
-
|
69
|
+
function O() {
|
70
|
+
const i = new Image();
|
71
|
+
i.src = n, g("loading"), S(!1), i.onload = () => {
|
72
|
+
g("loaded"), L();
|
73
|
+
}, i.onerror = () => {
|
74
|
+
g("error");
|
65
75
|
};
|
66
76
|
}
|
67
|
-
return
|
68
|
-
|
69
|
-
}, [
|
70
|
-
|
77
|
+
return w(() => {
|
78
|
+
x && O();
|
79
|
+
}, [x]), w(() => {
|
80
|
+
if (o === "error" && a && !l) {
|
81
|
+
const i = new Image();
|
82
|
+
i.src = a, i.onload = () => {
|
83
|
+
}, i.onerror = (z) => {
|
84
|
+
S(!0), o === "error" && h(z);
|
85
|
+
};
|
86
|
+
}
|
87
|
+
}, [o, a, l, h]), // paddingTop 要求元素本身的宽度为 100%,所以只能加一个外层元素去限制宽度
|
88
|
+
/* @__PURE__ */ s(
|
71
89
|
B,
|
72
90
|
{
|
73
91
|
"data-id": "2",
|
74
|
-
ref:
|
75
|
-
style:
|
92
|
+
ref: U,
|
93
|
+
style: H,
|
76
94
|
className: "arcblock_ux_img-wrapper",
|
77
|
-
...
|
78
|
-
sx:
|
95
|
+
...y,
|
96
|
+
sx: q(
|
79
97
|
{
|
80
|
-
[`& .${
|
98
|
+
[`& .${v.root}`]: {
|
81
99
|
position: "relative",
|
82
100
|
overflow: "hidden",
|
83
101
|
"& .image--state, & .image--img": {
|
@@ -109,17 +127,17 @@ function F({
|
|
109
127
|
}
|
110
128
|
}
|
111
129
|
},
|
112
|
-
|
130
|
+
y.sx
|
113
131
|
),
|
114
|
-
children: /* @__PURE__ */
|
115
|
-
!a && o === "error" && /* @__PURE__ */
|
116
|
-
!
|
117
|
-
o === "loaded" && /* @__PURE__ */
|
132
|
+
children: /* @__PURE__ */ F("div", { className: `image ${j} ${v.root}`, style: C, children: [
|
133
|
+
(l || !a && o === "error") && /* @__PURE__ */ s("div", { className: "image--state", title: "Image load error", children: /* @__PURE__ */ s(k, { icon: W, className: "image--icon" }) }),
|
134
|
+
!c && o === "loading" && /* @__PURE__ */ s("div", { className: "image--state", title: "loading image", children: /* @__PURE__ */ s(k, { icon: X, className: "image--icon" }) }),
|
135
|
+
o === "loaded" && /* @__PURE__ */ s("img", { className: "image--img", src: n, alt: P })
|
118
136
|
] })
|
119
137
|
}
|
120
138
|
);
|
121
139
|
}
|
122
|
-
|
140
|
+
M.propTypes = {
|
123
141
|
src: e.string.isRequired,
|
124
142
|
alt: e.string,
|
125
143
|
size: e.string,
|
@@ -134,8 +152,9 @@ F.propTypes = {
|
|
134
152
|
fallback: e.string,
|
135
153
|
className: e.string,
|
136
154
|
onError: e.func,
|
137
|
-
onSuccess: e.func
|
155
|
+
onSuccess: e.func,
|
156
|
+
useProxyFallback: e.bool
|
138
157
|
};
|
139
158
|
export {
|
140
|
-
|
159
|
+
M as default
|
141
160
|
};
|
package/lib/LoadingMask/index.js
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
import { jsxs as
|
1
|
+
import { jsxs as g, jsx as i } from "react/jsx-runtime";
|
2
2
|
import { Box as n } from "@mui/material";
|
3
|
-
function
|
3
|
+
function x({
|
4
4
|
size: s = 64,
|
5
|
-
padding:
|
6
|
-
borderWidth:
|
7
|
-
borderRadius:
|
5
|
+
padding: l = void 0,
|
6
|
+
borderWidth: f = void 0,
|
7
|
+
borderRadius: d = void 0,
|
8
8
|
duration: c = void 0,
|
9
|
-
children:
|
9
|
+
children: m
|
10
10
|
}) {
|
11
|
-
const t = s,
|
12
|
-
return /* @__PURE__ */
|
11
|
+
const t = s, a = d ?? t / 8, e = f ?? t / 32, r = l ?? t * 0.35 - e, p = c ?? 2.5;
|
12
|
+
return /* @__PURE__ */ g(
|
13
13
|
n,
|
14
14
|
{
|
15
15
|
sx: {
|
@@ -21,7 +21,7 @@ function b({
|
|
21
21
|
position: "relative"
|
22
22
|
},
|
23
23
|
children: [
|
24
|
-
/* @__PURE__ */
|
24
|
+
/* @__PURE__ */ i(
|
25
25
|
n,
|
26
26
|
{
|
27
27
|
sx: {
|
@@ -37,7 +37,7 @@ function b({
|
|
37
37
|
width: t,
|
38
38
|
height: t,
|
39
39
|
overflow: "hidden",
|
40
|
-
borderRadius: `${
|
40
|
+
borderRadius: `${a}px`,
|
41
41
|
backgroundColor: "grey.200",
|
42
42
|
"&::before,&::after": {
|
43
43
|
content: '""',
|
@@ -50,7 +50,7 @@ function b({
|
|
50
50
|
top: e,
|
51
51
|
bottom: e,
|
52
52
|
backgroundColor: "background.default",
|
53
|
-
borderRadius: `${
|
53
|
+
borderRadius: `${a - e}px`
|
54
54
|
},
|
55
55
|
"&::before": {
|
56
56
|
width: t * 5,
|
@@ -58,7 +58,7 @@ function b({
|
|
58
58
|
top: "50%",
|
59
59
|
left: "50%",
|
60
60
|
transform: "translate(-50%, -50%)",
|
61
|
-
background: ({ palette:
|
61
|
+
background: ({ palette: o }) => `conic-gradient(from 45deg, transparent 0%, transparent 50%, ${o.secondary.main} 90%, ${o.secondary.main} 100%)`,
|
62
62
|
animation: `rotate ${p}s linear infinite`,
|
63
63
|
"@keyframes rotate": {
|
64
64
|
"0%": {
|
@@ -72,7 +72,7 @@ function b({
|
|
72
72
|
}
|
73
73
|
}
|
74
74
|
),
|
75
|
-
/* @__PURE__ */
|
75
|
+
/* @__PURE__ */ i(
|
76
76
|
n,
|
77
77
|
{
|
78
78
|
sx: {
|
@@ -80,10 +80,20 @@ function b({
|
|
80
80
|
display: "flex",
|
81
81
|
justifyContent: "center",
|
82
82
|
alignItems: "center",
|
83
|
-
width: t -
|
84
|
-
height: t -
|
83
|
+
width: t - r - e,
|
84
|
+
height: t - r - e,
|
85
|
+
animation: "wait-bounce 1.6s infinite",
|
86
|
+
transformOrigin: "center bottom",
|
87
|
+
"@keyframes wait-bounce": {
|
88
|
+
"0%": { transform: "scale(1) translateY(0)" },
|
89
|
+
"20%": { transform: "scale(1.03) translateY(-4px)" },
|
90
|
+
"40%": { transform: "scale(0.98) translateY(2px)" },
|
91
|
+
"60%": { transform: "scale(1.01) translateY(-2px)" },
|
92
|
+
"80%": { transform: "scale(0.99) translateY(1px)" },
|
93
|
+
"100%": { transform: "scale(1) translateY(0)" }
|
94
|
+
}
|
85
95
|
},
|
86
|
-
children:
|
96
|
+
children: m
|
87
97
|
}
|
88
98
|
)
|
89
99
|
]
|
@@ -91,5 +101,5 @@ function b({
|
|
91
101
|
);
|
92
102
|
}
|
93
103
|
export {
|
94
|
-
|
104
|
+
x as default
|
95
105
|
};
|
@@ -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/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.34",
|
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": "e2822eb021fb9aebfcf80f71dd4da4ca76b2372b",
|
64
64
|
"dependencies": {
|
65
|
-
"@arcblock/bridge": "3.0.
|
65
|
+
"@arcblock/bridge": "3.0.34",
|
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.34",
|
69
|
+
"@arcblock/nft-display": "3.0.34",
|
70
|
+
"@arcblock/react-hooks": "3.0.34",
|
71
71
|
"@blocklet/js-sdk": "^1.16.46",
|
72
|
-
"@blocklet/theme": "3.0.
|
72
|
+
"@blocklet/theme": "3.0.34",
|
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
|
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,
|
@@ -64,6 +89,17 @@ function Img({
|
|
64
89
|
const [ref, inView] = lazy ? useInView({ threshold: 0, triggerOnce: true }) : [null, true];
|
65
90
|
|
66
91
|
const [imgState, setImgState] = useState('init');
|
92
|
+
const [fallbackError, setFallbackError] = useState(false);
|
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]);
|
67
103
|
|
68
104
|
const actualSrc = useMemo(() => {
|
69
105
|
switch (imgState) {
|
@@ -71,13 +107,13 @@ function Img({
|
|
71
107
|
case 'loading':
|
72
108
|
return placeholder;
|
73
109
|
case 'error':
|
74
|
-
return
|
110
|
+
return fallbackError ? null : fallbackSrc;
|
75
111
|
case 'loaded':
|
76
112
|
return src;
|
77
113
|
default:
|
78
114
|
return null;
|
79
115
|
}
|
80
|
-
}, [placeholder,
|
116
|
+
}, [placeholder, fallbackSrc, src, imgState, fallbackError]);
|
81
117
|
|
82
118
|
const actualRatio = width && height ? (100 * height) / width : ratio * 100;
|
83
119
|
|
@@ -106,13 +142,13 @@ function Img({
|
|
106
142
|
const img = new Image();
|
107
143
|
img.src = src;
|
108
144
|
setImgState('loading');
|
145
|
+
setFallbackError(false);
|
109
146
|
img.onload = () => {
|
110
147
|
setImgState('loaded');
|
111
148
|
onSuccess();
|
112
149
|
};
|
113
|
-
img.onerror = (
|
150
|
+
img.onerror = () => {
|
114
151
|
setImgState('error');
|
115
|
-
onError(err);
|
116
152
|
};
|
117
153
|
}
|
118
154
|
|
@@ -121,6 +157,24 @@ function Img({
|
|
121
157
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
122
158
|
}, [inView]);
|
123
159
|
|
160
|
+
// 处理 fallback 加载
|
161
|
+
useEffect(() => {
|
162
|
+
if (imgState === 'error' && fallbackSrc && !fallbackError) {
|
163
|
+
const fallbackImg = new Image();
|
164
|
+
fallbackImg.src = fallbackSrc;
|
165
|
+
fallbackImg.onload = () => {
|
166
|
+
// fallback 加载成功,保持在 error 状态但显示 fallback
|
167
|
+
};
|
168
|
+
fallbackImg.onerror = (err) => {
|
169
|
+
// fallback 也加载失败
|
170
|
+
setFallbackError(true);
|
171
|
+
if (imgState === 'error') {
|
172
|
+
onError(err);
|
173
|
+
}
|
174
|
+
};
|
175
|
+
}
|
176
|
+
}, [imgState, fallbackSrc, fallbackError, onError]);
|
177
|
+
|
124
178
|
return (
|
125
179
|
// paddingTop 要求元素本身的宽度为 100%,所以只能加一个外层元素去限制宽度
|
126
180
|
<Box
|
@@ -166,13 +220,13 @@ function Img({
|
|
166
220
|
rest.sx
|
167
221
|
)}>
|
168
222
|
<div className={`image ${className} ${classes.root}`} style={mergedStyle}>
|
169
|
-
{!
|
170
|
-
<div className="image--state" title="
|
223
|
+
{(fallbackError || (!fallbackSrc && imgState === 'error')) && (
|
224
|
+
<div className="image--state" title="Image load error">
|
171
225
|
<Icon icon={WarningRoundedIcon} className="image--icon" />
|
172
226
|
</div>
|
173
227
|
)}
|
174
228
|
{!placeholder && imgState === 'loading' && (
|
175
|
-
<div className="image--state" title="
|
229
|
+
<div className="image--state" title="loading image">
|
176
230
|
<Icon icon={ImageRoundedIcon} className="image--icon" />
|
177
231
|
</div>
|
178
232
|
)}
|
@@ -198,6 +252,7 @@ Img.propTypes = {
|
|
198
252
|
className: PropTypes.string,
|
199
253
|
onError: PropTypes.func,
|
200
254
|
onSuccess: PropTypes.func,
|
255
|
+
useProxyFallback: PropTypes.bool,
|
201
256
|
};
|
202
257
|
|
203
258
|
export default Img;
|
@@ -20,7 +20,7 @@ export default function LoadingMask({
|
|
20
20
|
const finialSize = size;
|
21
21
|
const finialRadius = borderRadius ?? finialSize / 8;
|
22
22
|
const finialBorderWidth = borderWidth ?? finialSize / 32;
|
23
|
-
const finialPadding = padding ?? finialSize * 0.
|
23
|
+
const finialPadding = padding ?? finialSize * 0.35 - finialBorderWidth;
|
24
24
|
const finialDuration = duration ?? 2.5;
|
25
25
|
return (
|
26
26
|
<Box
|
@@ -89,6 +89,17 @@ export default function LoadingMask({
|
|
89
89
|
alignItems: 'center',
|
90
90
|
width: finialSize - finialPadding - finialBorderWidth,
|
91
91
|
height: finialSize - finialPadding - finialBorderWidth,
|
92
|
+
|
93
|
+
animation: 'wait-bounce 1.6s infinite',
|
94
|
+
transformOrigin: 'center bottom',
|
95
|
+
'@keyframes wait-bounce': {
|
96
|
+
'0%': { transform: 'scale(1) translateY(0)' },
|
97
|
+
'20%': { transform: 'scale(1.03) translateY(-4px)' },
|
98
|
+
'40%': { transform: 'scale(0.98) translateY(2px)' },
|
99
|
+
'60%': { transform: 'scale(1.01) translateY(-2px)' },
|
100
|
+
'80%': { transform: 'scale(0.99) translateY(1px)' },
|
101
|
+
'100%': { transform: 'scale(1) translateY(0)' },
|
102
|
+
},
|
92
103
|
}}>
|
93
104
|
{children}
|
94
105
|
</Box>
|
package/src/UserCard/index.tsx
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { useEffect, useRef, useState } from 'react';
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
2
2
|
import type { User } from './types';
|
3
3
|
import { UserCardProps, CardType } from './types';
|
4
4
|
import AvatarOnlyCard from './Cards/avatar-only';
|
@@ -55,9 +55,26 @@ function UserCard(props: UserCardProps) {
|
|
55
55
|
};
|
56
56
|
}, [props.did, props.user]);
|
57
57
|
|
58
|
+
// 补全 avatar 的 imageFilter 信息,以提高性能
|
59
|
+
const userInfo = useMemo(() => {
|
60
|
+
if (!user) {
|
61
|
+
return null;
|
62
|
+
}
|
63
|
+
|
64
|
+
const { avatar = '', ...rest } = user;
|
65
|
+
const avatarParam = avatar.split('?')[1];
|
66
|
+
if (avatar && !avatarParam) {
|
67
|
+
return {
|
68
|
+
...rest,
|
69
|
+
avatar: `${avatar}?imageFilter=resize&w=48&h=48`,
|
70
|
+
};
|
71
|
+
}
|
72
|
+
return user;
|
73
|
+
}, [user]);
|
74
|
+
|
58
75
|
// 如果不存在,则使用 did 渲染头像
|
59
|
-
if (!
|
60
|
-
return <Avatar did={props.did} size={props.avatarSize} {...props.avatarProps} />;
|
76
|
+
if (!userInfo) {
|
77
|
+
return <Avatar did={props.did} size={props.avatarSize} useProxyFallback {...props.avatarProps} />;
|
61
78
|
}
|
62
79
|
|
63
80
|
// user 存在,则使用 user 渲染头像
|
@@ -68,7 +85,7 @@ function UserCard(props: UserCardProps) {
|
|
68
85
|
<DetailedCard
|
69
86
|
{...props}
|
70
87
|
shouldShowHoverCard={false}
|
71
|
-
user={
|
88
|
+
user={userInfo!}
|
72
89
|
avatarProps={props.popupAvatarProps}
|
73
90
|
shortenLabelProps={props.popupShortenLabelProps || props.shortenLabelProps}
|
74
91
|
renderFields={props.popupRenderFields}
|
@@ -88,7 +105,7 @@ function UserCard(props: UserCardProps) {
|
|
88
105
|
{...props}
|
89
106
|
shouldShowHoverCard={shouldShowHoverCard}
|
90
107
|
renderCardContent={renderCardContent}
|
91
|
-
user={
|
108
|
+
user={userInfo!}
|
92
109
|
/>
|
93
110
|
);
|
94
111
|
}
|
@@ -100,7 +117,7 @@ function UserCard(props: UserCardProps) {
|
|
100
117
|
{...props}
|
101
118
|
shouldShowHoverCard={shouldShowHoverCard}
|
102
119
|
renderCardContent={renderCardContent}
|
103
|
-
user={
|
120
|
+
user={userInfo!}
|
104
121
|
/>
|
105
122
|
</CardContainer>
|
106
123
|
);
|