@arcblock/ux 3.0.32 → 3.0.33
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/Img/index.js +73 -65
- package/lib/LoadingMask/index.js +27 -17
- package/package.json +7 -7
- package/src/Img/index.jsx +22 -5
- package/src/LoadingMask/index.tsx +12 -1
package/lib/Img/index.js
CHANGED
@@ -1,83 +1,91 @@
|
|
1
|
-
import { jsx as
|
2
|
-
import { useState as
|
1
|
+
import { jsx as i, jsxs as X } from "react/jsx-runtime";
|
2
|
+
import { useState as h, useMemo as b, useEffect as x } from "react";
|
3
3
|
import e from "prop-types";
|
4
|
-
import { useInView as
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import { Icon as
|
8
|
-
import { Box as
|
9
|
-
import
|
10
|
-
import { mergeSx as
|
11
|
-
const
|
12
|
-
root: `${
|
4
|
+
import { useInView as _ } from "react-intersection-observer";
|
5
|
+
import q from "@iconify-icons/material-symbols/warning-rounded";
|
6
|
+
import B from "@iconify-icons/material-symbols/image-rounded";
|
7
|
+
import { Icon as y } from "@iconify/react";
|
8
|
+
import { Box as C } from "@mui/material";
|
9
|
+
import S from "lodash/noop";
|
10
|
+
import { mergeSx as D } from "../Util/style.js";
|
11
|
+
const M = "Img", N = {
|
12
|
+
root: `${M}-root`
|
13
13
|
};
|
14
|
-
function
|
15
|
-
lazy:
|
16
|
-
width:
|
17
|
-
height:
|
18
|
-
repeat:
|
19
|
-
ratio:
|
20
|
-
alt:
|
21
|
-
size:
|
22
|
-
position:
|
23
|
-
src:
|
24
|
-
placeholder:
|
25
|
-
fallback:
|
26
|
-
style:
|
27
|
-
className:
|
28
|
-
onError:
|
29
|
-
onSuccess:
|
30
|
-
...
|
14
|
+
function O({
|
15
|
+
lazy: v = !0,
|
16
|
+
width: a = null,
|
17
|
+
height: g = null,
|
18
|
+
repeat: w = "no-repeat",
|
19
|
+
ratio: $ = 1,
|
20
|
+
alt: k = null,
|
21
|
+
size: u = "cover",
|
22
|
+
position: d = "top center",
|
23
|
+
src: s,
|
24
|
+
placeholder: l = null,
|
25
|
+
fallback: t = null,
|
26
|
+
style: R = null,
|
27
|
+
className: E = "",
|
28
|
+
onError: j = S,
|
29
|
+
onSuccess: z = S,
|
30
|
+
...p
|
31
31
|
}) {
|
32
|
-
const [
|
32
|
+
const [P, f] = v ? _({ threshold: 0, triggerOnce: !0 }) : [null, !0], [o, m] = h("init"), [n, I] = h(!1), c = b(() => {
|
33
33
|
switch (o) {
|
34
34
|
case "init":
|
35
35
|
case "loading":
|
36
|
-
return
|
36
|
+
return l;
|
37
37
|
case "error":
|
38
|
-
return
|
38
|
+
return n ? null : t;
|
39
39
|
case "loaded":
|
40
|
-
return
|
40
|
+
return s;
|
41
41
|
default:
|
42
42
|
return null;
|
43
43
|
}
|
44
|
-
}, [
|
44
|
+
}, [l, t, s, o, n]), T = a && g ? 100 * g / a : $ * 100, W = b(
|
45
45
|
() => ({
|
46
|
-
backgroundImage:
|
47
|
-
backgroundPosition:
|
48
|
-
backgroundSize:
|
49
|
-
backgroundRepeat:
|
50
|
-
paddingTop: `${
|
46
|
+
backgroundImage: c ? `url(${c})` : "",
|
47
|
+
backgroundPosition: d,
|
48
|
+
backgroundSize: u,
|
49
|
+
backgroundRepeat: w,
|
50
|
+
paddingTop: `${T}%`
|
51
51
|
}),
|
52
52
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
53
|
-
[
|
54
|
-
),
|
55
|
-
...
|
53
|
+
[c, d, u, o]
|
54
|
+
), F = {
|
55
|
+
...R,
|
56
56
|
display: "inline-block",
|
57
|
-
width:
|
57
|
+
width: a ? `${a}px` : "100%"
|
58
58
|
};
|
59
|
-
function
|
60
|
-
const
|
61
|
-
|
62
|
-
|
63
|
-
},
|
64
|
-
|
59
|
+
function H() {
|
60
|
+
const r = new Image();
|
61
|
+
r.src = s, m("loading"), I(!1), r.onload = () => {
|
62
|
+
m("loaded"), z();
|
63
|
+
}, r.onerror = (V) => {
|
64
|
+
m("error"), j(V);
|
65
65
|
};
|
66
66
|
}
|
67
|
-
return
|
68
|
-
|
69
|
-
}, [
|
70
|
-
|
71
|
-
|
67
|
+
return x(() => {
|
68
|
+
f && H();
|
69
|
+
}, [f]), x(() => {
|
70
|
+
if (o === "error" && t && !n) {
|
71
|
+
const r = new Image();
|
72
|
+
r.src = t, r.onload = () => {
|
73
|
+
}, r.onerror = () => {
|
74
|
+
I(!0);
|
75
|
+
};
|
76
|
+
}
|
77
|
+
}, [o, t, n]), // paddingTop 要求元素本身的宽度为 100%,所以只能加一个外层元素去限制宽度
|
78
|
+
/* @__PURE__ */ i(
|
79
|
+
C,
|
72
80
|
{
|
73
81
|
"data-id": "2",
|
74
|
-
ref:
|
75
|
-
style:
|
82
|
+
ref: P,
|
83
|
+
style: F,
|
76
84
|
className: "arcblock_ux_img-wrapper",
|
77
|
-
...
|
78
|
-
sx:
|
85
|
+
...p,
|
86
|
+
sx: D(
|
79
87
|
{
|
80
|
-
[`& .${
|
88
|
+
[`& .${N.root}`]: {
|
81
89
|
position: "relative",
|
82
90
|
overflow: "hidden",
|
83
91
|
"& .image--state, & .image--img": {
|
@@ -109,17 +117,17 @@ function F({
|
|
109
117
|
}
|
110
118
|
}
|
111
119
|
},
|
112
|
-
|
120
|
+
p.sx
|
113
121
|
),
|
114
|
-
children: /* @__PURE__ */
|
115
|
-
!
|
116
|
-
!
|
117
|
-
o === "loaded" && /* @__PURE__ */
|
122
|
+
children: /* @__PURE__ */ X("div", { className: `image ${E} ${N.root}`, style: W, children: [
|
123
|
+
(n || !t && o === "error") && /* @__PURE__ */ i("div", { className: "image--state", title: "Image load error", children: /* @__PURE__ */ i(y, { icon: q, className: "image--icon" }) }),
|
124
|
+
!l && o === "loading" && /* @__PURE__ */ i("div", { className: "image--state", title: "loading image", children: /* @__PURE__ */ i(y, { icon: B, className: "image--icon" }) }),
|
125
|
+
o === "loaded" && /* @__PURE__ */ i("img", { className: "image--img", src: s, alt: k })
|
118
126
|
] })
|
119
127
|
}
|
120
128
|
);
|
121
129
|
}
|
122
|
-
|
130
|
+
O.propTypes = {
|
123
131
|
src: e.string.isRequired,
|
124
132
|
alt: e.string,
|
125
133
|
size: e.string,
|
@@ -137,5 +145,5 @@ F.propTypes = {
|
|
137
145
|
onSuccess: e.func
|
138
146
|
};
|
139
147
|
export {
|
140
|
-
|
148
|
+
O as default
|
141
149
|
};
|
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
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.33",
|
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": "4b6fbddbcafd122684b82a0b452ca34fc6d1a6ab",
|
64
64
|
"dependencies": {
|
65
|
-
"@arcblock/bridge": "3.0.
|
65
|
+
"@arcblock/bridge": "3.0.33",
|
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.33",
|
69
|
+
"@arcblock/nft-display": "3.0.33",
|
70
|
+
"@arcblock/react-hooks": "3.0.33",
|
71
71
|
"@blocklet/js-sdk": "^1.16.46",
|
72
|
-
"@blocklet/theme": "3.0.
|
72
|
+
"@blocklet/theme": "3.0.33",
|
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/Img/index.jsx
CHANGED
@@ -64,6 +64,7 @@ function Img({
|
|
64
64
|
const [ref, inView] = lazy ? useInView({ threshold: 0, triggerOnce: true }) : [null, true];
|
65
65
|
|
66
66
|
const [imgState, setImgState] = useState('init');
|
67
|
+
const [fallbackError, setFallbackError] = useState(false);
|
67
68
|
|
68
69
|
const actualSrc = useMemo(() => {
|
69
70
|
switch (imgState) {
|
@@ -71,13 +72,13 @@ function Img({
|
|
71
72
|
case 'loading':
|
72
73
|
return placeholder;
|
73
74
|
case 'error':
|
74
|
-
return fallback;
|
75
|
+
return fallbackError ? null : fallback;
|
75
76
|
case 'loaded':
|
76
77
|
return src;
|
77
78
|
default:
|
78
79
|
return null;
|
79
80
|
}
|
80
|
-
}, [placeholder, fallback, src, imgState]);
|
81
|
+
}, [placeholder, fallback, src, imgState, fallbackError]);
|
81
82
|
|
82
83
|
const actualRatio = width && height ? (100 * height) / width : ratio * 100;
|
83
84
|
|
@@ -106,6 +107,7 @@ function Img({
|
|
106
107
|
const img = new Image();
|
107
108
|
img.src = src;
|
108
109
|
setImgState('loading');
|
110
|
+
setFallbackError(false);
|
109
111
|
img.onload = () => {
|
110
112
|
setImgState('loaded');
|
111
113
|
onSuccess();
|
@@ -121,6 +123,21 @@ function Img({
|
|
121
123
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
122
124
|
}, [inView]);
|
123
125
|
|
126
|
+
// 处理 fallback 加载
|
127
|
+
useEffect(() => {
|
128
|
+
if (imgState === 'error' && fallback && !fallbackError) {
|
129
|
+
const fallbackImg = new Image();
|
130
|
+
fallbackImg.src = fallback;
|
131
|
+
fallbackImg.onload = () => {
|
132
|
+
// fallback 加载成功,保持在 error 状态但显示 fallback
|
133
|
+
};
|
134
|
+
fallbackImg.onerror = () => {
|
135
|
+
// fallback 也加载失败
|
136
|
+
setFallbackError(true);
|
137
|
+
};
|
138
|
+
}
|
139
|
+
}, [imgState, fallback, fallbackError]);
|
140
|
+
|
124
141
|
return (
|
125
142
|
// paddingTop 要求元素本身的宽度为 100%,所以只能加一个外层元素去限制宽度
|
126
143
|
<Box
|
@@ -166,13 +183,13 @@ function Img({
|
|
166
183
|
rest.sx
|
167
184
|
)}>
|
168
185
|
<div className={`image ${className} ${classes.root}`} style={mergedStyle}>
|
169
|
-
{!fallback && imgState === 'error' && (
|
170
|
-
<div className="image--state" title="
|
186
|
+
{(fallbackError || (!fallback && imgState === 'error')) && (
|
187
|
+
<div className="image--state" title="Image load error">
|
171
188
|
<Icon icon={WarningRoundedIcon} className="image--icon" />
|
172
189
|
</div>
|
173
190
|
)}
|
174
191
|
{!placeholder && imgState === 'loading' && (
|
175
|
-
<div className="image--state" title="
|
192
|
+
<div className="image--state" title="loading image">
|
176
193
|
<Icon icon={ImageRoundedIcon} className="image--icon" />
|
177
194
|
</div>
|
178
195
|
)}
|
@@ -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>
|