@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 CHANGED
@@ -1,83 +1,91 @@
1
- import { jsx as t, jsxs as W } from "react/jsx-runtime";
2
- import { useState as H, useMemo as f, useEffect as V } from "react";
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 X } from "react-intersection-observer";
5
- import _ from "@iconify-icons/material-symbols/warning-rounded";
6
- import q from "@iconify-icons/material-symbols/image-rounded";
7
- import { Icon as h } from "@iconify/react";
8
- import { Box as B } from "@mui/material";
9
- import I from "lodash/noop";
10
- import { mergeSx as C } from "../Util/style.js";
11
- const D = "Img", b = {
12
- root: `${D}-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 F({
15
- lazy: x = !0,
16
- width: i = null,
17
- height: c = null,
18
- repeat: y = "no-repeat",
19
- ratio: S = 1,
20
- alt: N = null,
21
- size: g = "cover",
22
- position: u = "top center",
23
- src: r,
24
- placeholder: n = null,
25
- fallback: a = null,
26
- style: v = null,
27
- className: $ = "",
28
- onError: k = I,
29
- onSuccess: w = I,
30
- ...d
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 [R, p] = x ? X({ threshold: 0, triggerOnce: !0 }) : [null, !0], [o, s] = H("init"), m = f(() => {
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 n;
36
+ return l;
37
37
  case "error":
38
- return a;
38
+ return n ? null : t;
39
39
  case "loaded":
40
- return r;
40
+ return s;
41
41
  default:
42
42
  return null;
43
43
  }
44
- }, [n, a, r, o]), j = i && c ? 100 * c / i : S * 100, z = f(
44
+ }, [l, t, s, o, n]), T = a && g ? 100 * g / a : $ * 100, W = b(
45
45
  () => ({
46
- backgroundImage: m ? `url(${m})` : "",
47
- backgroundPosition: u,
48
- backgroundSize: g,
49
- backgroundRepeat: y,
50
- paddingTop: `${j}%`
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
- [m, u, g, o]
54
- ), E = {
55
- ...v,
53
+ [c, d, u, o]
54
+ ), F = {
55
+ ...R,
56
56
  display: "inline-block",
57
- width: i ? `${i}px` : "100%"
57
+ width: a ? `${a}px` : "100%"
58
58
  };
59
- function P() {
60
- const l = new Image();
61
- l.src = r, s("loading"), l.onload = () => {
62
- s("loaded"), w();
63
- }, l.onerror = (T) => {
64
- s("error"), k(T);
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 V(() => {
68
- p && P();
69
- }, [p]), // paddingTop 要求元素本身的宽度为 100%,所以只能加一个外层元素去限制宽度
70
- /* @__PURE__ */ t(
71
- B,
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: R,
75
- style: E,
82
+ ref: P,
83
+ style: F,
76
84
  className: "arcblock_ux_img-wrapper",
77
- ...d,
78
- sx: C(
85
+ ...p,
86
+ sx: D(
79
87
  {
80
- [`& .${b.root}`]: {
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
- d.sx
120
+ p.sx
113
121
  ),
114
- children: /* @__PURE__ */ W("div", { className: `image ${$} ${b.root}`, style: z, children: [
115
- !a && o === "error" && /* @__PURE__ */ t("div", { className: "image--state", title: "loading image", children: /* @__PURE__ */ t(h, { icon: _, className: "image--icon" }) }),
116
- !n && o === "loading" && /* @__PURE__ */ t("div", { className: "image--state", title: "Image load error", children: /* @__PURE__ */ t(h, { icon: q, className: "image--icon" }) }),
117
- o === "loaded" && /* @__PURE__ */ t("img", { className: "image--img", src: r, alt: N })
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
- F.propTypes = {
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
- F as default
148
+ O as default
141
149
  };
@@ -1,15 +1,15 @@
1
- import { jsxs as h, jsx as a } from "react/jsx-runtime";
1
+ import { jsxs as g, jsx as i } from "react/jsx-runtime";
2
2
  import { Box as n } from "@mui/material";
3
- function b({
3
+ function x({
4
4
  size: s = 64,
5
- padding: d = void 0,
6
- borderWidth: l = void 0,
7
- borderRadius: f = void 0,
5
+ padding: l = void 0,
6
+ borderWidth: f = void 0,
7
+ borderRadius: d = void 0,
8
8
  duration: c = void 0,
9
- children: g
9
+ children: m
10
10
  }) {
11
- const t = s, i = f ?? t / 8, e = l ?? t / 32, o = d ?? t * 0.25 - e, p = c ?? 2.5;
12
- return /* @__PURE__ */ h(
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__ */ a(
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: `${i}px`,
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: `${i - e}px`
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: r }) => `conic-gradient(from 45deg, transparent 0%, transparent 50%, ${r.secondary.main} 90%, ${r.secondary.main} 100%)`,
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__ */ a(
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 - o - e,
84
- height: t - o - e
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: g
96
+ children: m
87
97
  }
88
98
  )
89
99
  ]
@@ -91,5 +101,5 @@ function b({
91
101
  );
92
102
  }
93
103
  export {
94
- b as default
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.32",
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": "c81f41bdecc9ffb41a2f8158fb7a557fae62666b",
63
+ "gitHead": "4b6fbddbcafd122684b82a0b452ca34fc6d1a6ab",
64
64
  "dependencies": {
65
- "@arcblock/bridge": "3.0.32",
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.32",
69
- "@arcblock/nft-display": "3.0.32",
70
- "@arcblock/react-hooks": "3.0.32",
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.32",
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="loading image">
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="Image load error">
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.25 - finialBorderWidth;
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>