@arcblock/ux 3.0.0 → 3.0.2
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/LoadingMask/index.js +15 -15
- package/lib/UserCard/Content/basic.js +113 -141
- package/package.json +7 -7
- package/src/LoadingMask/index.tsx +7 -7
- package/src/UserCard/Content/basic.tsx +4 -32
package/lib/LoadingMask/index.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { jsxs as
|
1
|
+
import { jsxs as h, jsx as a } from "react/jsx-runtime";
|
2
2
|
import { Box as n } from "@mui/material";
|
3
3
|
function b({
|
4
4
|
size: s = 64,
|
@@ -8,8 +8,8 @@ function b({
|
|
8
8
|
duration: c,
|
9
9
|
children: g
|
10
10
|
}) {
|
11
|
-
const t = s,
|
12
|
-
return /* @__PURE__ */
|
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(
|
13
13
|
n,
|
14
14
|
{
|
15
15
|
sx: {
|
@@ -37,15 +37,11 @@ function b({
|
|
37
37
|
width: t,
|
38
38
|
height: t,
|
39
39
|
overflow: "hidden",
|
40
|
-
borderRadius: `${
|
40
|
+
borderRadius: `${i}px`,
|
41
41
|
backgroundColor: "grey.200",
|
42
42
|
"&::before,&::after": {
|
43
43
|
content: '""',
|
44
44
|
position: "absolute",
|
45
|
-
top: 0,
|
46
|
-
bottom: 0,
|
47
|
-
left: 0,
|
48
|
-
right: 0,
|
49
45
|
pointerEvents: "none"
|
50
46
|
},
|
51
47
|
"&::after": {
|
@@ -54,18 +50,22 @@ function b({
|
|
54
50
|
top: e,
|
55
51
|
bottom: e,
|
56
52
|
backgroundColor: "background.default",
|
57
|
-
borderRadius: `${
|
53
|
+
borderRadius: `${i - e}px`
|
58
54
|
},
|
59
55
|
"&::before": {
|
56
|
+
width: t * 5,
|
57
|
+
height: t * 5,
|
58
|
+
top: "50%",
|
59
|
+
left: "50%",
|
60
|
+
transform: "translate(-50%, -50%)",
|
60
61
|
background: ({ palette: r }) => `conic-gradient(from 45deg, transparent 0%, transparent 50%, ${r.secondary.main} 90%, ${r.secondary.main} 100%)`,
|
61
|
-
|
62
|
-
animation: `rotate ${m}s linear infinite`,
|
62
|
+
animation: `rotate ${p}s linear infinite`,
|
63
63
|
"@keyframes rotate": {
|
64
64
|
"0%": {
|
65
|
-
transform: "
|
65
|
+
transform: "translate(-50%, -50%) rotate(0deg)"
|
66
66
|
},
|
67
67
|
"100%": {
|
68
|
-
transform: "
|
68
|
+
transform: "translate(-50%, -50%) rotate(360deg)"
|
69
69
|
}
|
70
70
|
}
|
71
71
|
}
|
@@ -80,8 +80,8 @@ function b({
|
|
80
80
|
display: "flex",
|
81
81
|
justifyContent: "center",
|
82
82
|
alignItems: "center",
|
83
|
-
width: t -
|
84
|
-
height: t -
|
83
|
+
width: t - o - e,
|
84
|
+
height: t - o - e
|
85
85
|
},
|
86
86
|
children: g
|
87
87
|
}
|
@@ -1,41 +1,41 @@
|
|
1
|
-
import { jsxs as
|
2
|
-
import { Typography as
|
3
|
-
import { useCreation as
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import { Icon as
|
7
|
-
import
|
8
|
-
import
|
9
|
-
import
|
10
|
-
import
|
11
|
-
import
|
12
|
-
import
|
13
|
-
import {
|
14
|
-
import { useCallback as G, useMemo as
|
15
|
-
import
|
16
|
-
const
|
17
|
-
timezone:
|
18
|
-
email:
|
19
|
-
phone:
|
20
|
-
location:
|
21
|
-
link:
|
1
|
+
import { jsxs as y, jsx as r } from "react/jsx-runtime";
|
2
|
+
import { Typography as g, Box as f, Grid as _, useTheme as k } from "@mui/material";
|
3
|
+
import { useCreation as p, useMemoizedFn as T } from "ahooks";
|
4
|
+
import $ from "@emotion/styled";
|
5
|
+
import D from "lodash/isArray";
|
6
|
+
import { Icon as j } from "@iconify/react";
|
7
|
+
import E from "@iconify-icons/tabler/info-circle";
|
8
|
+
import A from "@arcblock/icons/lib/Link";
|
9
|
+
import M from "@arcblock/icons/lib/Phone";
|
10
|
+
import P from "@arcblock/icons/lib/Location";
|
11
|
+
import V from "@arcblock/icons/lib/Email";
|
12
|
+
import B from "@arcblock/icons/lib/Timezone";
|
13
|
+
import { withoutProtocol as R } from "ufo";
|
14
|
+
import { useCallback as G, useMemo as N } from "react";
|
15
|
+
import Z from "./clock.js";
|
16
|
+
const q = {
|
17
|
+
timezone: B,
|
18
|
+
email: V,
|
19
|
+
phone: M,
|
20
|
+
location: P,
|
21
|
+
link: A
|
22
22
|
};
|
23
|
-
function
|
24
|
-
return
|
23
|
+
function H(e) {
|
24
|
+
return R(e);
|
25
25
|
}
|
26
|
-
function
|
26
|
+
function x(e) {
|
27
27
|
return e ? {
|
28
28
|
filter: "brightness(0) saturate(100%) invert(1)"
|
29
29
|
} : {};
|
30
30
|
}
|
31
|
-
const
|
31
|
+
const u = {
|
32
32
|
width: 16,
|
33
33
|
height: 16
|
34
34
|
};
|
35
|
-
function
|
36
|
-
const a =
|
37
|
-
return /* @__PURE__ */
|
38
|
-
|
35
|
+
function J({ value: e }) {
|
36
|
+
const a = k().palette.mode === "dark";
|
37
|
+
return /* @__PURE__ */ y(
|
38
|
+
f,
|
39
39
|
{
|
40
40
|
className: "user-card__timezone-field",
|
41
41
|
sx: {
|
@@ -44,65 +44,37 @@ function K({ value: e }) {
|
|
44
44
|
gap: 1
|
45
45
|
},
|
46
46
|
children: [
|
47
|
-
/* @__PURE__ */
|
48
|
-
/* @__PURE__ */
|
47
|
+
/* @__PURE__ */ r(B, { ...u, style: x(a) }),
|
48
|
+
/* @__PURE__ */ r(Z, { value: e, variant: "body2", color: "grey.800" })
|
49
49
|
]
|
50
50
|
}
|
51
51
|
);
|
52
52
|
}
|
53
|
-
function
|
54
|
-
const
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
}
|
71
|
-
|
72
|
-
|
73
|
-
"img",
|
74
|
-
{
|
75
|
-
src: l,
|
76
|
-
alt: "site icon",
|
77
|
-
style: { width: 16, height: 16, objectFit: "contain" },
|
78
|
-
onError: () => {
|
79
|
-
a(!0);
|
80
|
-
}
|
81
|
-
}
|
82
|
-
) : /* @__PURE__ */ o(S, { ...y, style: v(c) }),
|
83
|
-
/* @__PURE__ */ o(I, { variant: "body2", color: "grey.800", children: /* @__PURE__ */ o(
|
84
|
-
k,
|
85
|
-
{
|
86
|
-
component: "a",
|
87
|
-
href: e,
|
88
|
-
style: { textDecoration: "none", color: "inherit", fontSize: "inherit" },
|
89
|
-
target: "_blank",
|
90
|
-
variant: "body2",
|
91
|
-
rel: "noopener noreferrer",
|
92
|
-
sx: {
|
93
|
-
color: "grey.800"
|
94
|
-
},
|
95
|
-
children: J(e)
|
96
|
-
}
|
97
|
-
) })
|
98
|
-
]
|
99
|
-
}
|
100
|
-
);
|
53
|
+
function K({ value: e }) {
|
54
|
+
const a = k().palette.mode === "dark";
|
55
|
+
return /* @__PURE__ */ y(f, { display: "flex", alignItems: "center", gap: 1, className: "user-card__link-field", children: [
|
56
|
+
/* @__PURE__ */ r(A, { ...u, style: x(a) }),
|
57
|
+
/* @__PURE__ */ r(v, { variant: "body2", color: "grey.800", children: /* @__PURE__ */ r(
|
58
|
+
g,
|
59
|
+
{
|
60
|
+
component: "a",
|
61
|
+
href: e,
|
62
|
+
style: { textDecoration: "none", color: "inherit", fontSize: "inherit" },
|
63
|
+
target: "_blank",
|
64
|
+
variant: "body2",
|
65
|
+
rel: "noopener noreferrer",
|
66
|
+
sx: {
|
67
|
+
color: "grey.800"
|
68
|
+
},
|
69
|
+
children: H(e)
|
70
|
+
}
|
71
|
+
) })
|
72
|
+
] });
|
101
73
|
}
|
102
|
-
function
|
103
|
-
const
|
104
|
-
return /* @__PURE__ */
|
105
|
-
|
74
|
+
function S({ field: e, value: s, children: a }) {
|
75
|
+
const h = q[e], m = k().palette.mode === "dark", c = x(m);
|
76
|
+
return /* @__PURE__ */ y(
|
77
|
+
f,
|
106
78
|
{
|
107
79
|
className: `user-card__${e}-field`,
|
108
80
|
sx: {
|
@@ -111,94 +83,94 @@ function N({ field: e, value: m, children: a }) {
|
|
111
83
|
gap: 1
|
112
84
|
},
|
113
85
|
children: [
|
114
|
-
|
115
|
-
/* @__PURE__ */
|
86
|
+
h ? /* @__PURE__ */ r(h, { ...u, style: c }) : /* @__PURE__ */ r(j, { icon: E, ...u, ...c }),
|
87
|
+
/* @__PURE__ */ r(v, { variant: "body2", color: "grey.800", children: a ?? s })
|
116
88
|
]
|
117
89
|
},
|
118
90
|
e
|
119
91
|
);
|
120
92
|
}
|
121
|
-
function
|
122
|
-
var
|
123
|
-
const a =
|
93
|
+
function se({ user: e, renderFields: s }) {
|
94
|
+
var w;
|
95
|
+
const a = p(() => s ?? ["bio", "email", "phone", "location", "timezone", "link"], [s]), h = p(() => a.includes("bio"), [a]), l = p(() => e.metadata ?? {
|
124
96
|
joinedAt: e == null ? void 0 : e.createdAt,
|
125
97
|
email: e == null ? void 0 : e.email,
|
126
98
|
phone: {
|
127
99
|
country: "cn",
|
128
100
|
phoneNumber: (e == null ? void 0 : e.phone) ?? ""
|
129
101
|
}
|
130
|
-
}, [e]),
|
131
|
-
(
|
132
|
-
var i,
|
133
|
-
if (!
|
134
|
-
switch (
|
102
|
+
}, [e]), m = p(() => e.address, [e.address]), c = G(
|
103
|
+
(n) => {
|
104
|
+
var i, t, o;
|
105
|
+
if (!n) return "";
|
106
|
+
switch (n) {
|
135
107
|
case "bio":
|
136
108
|
return ((i = e.metadata) == null ? void 0 : i.bio) || "";
|
137
109
|
case "email":
|
138
|
-
return
|
110
|
+
return l.email || e.email || "";
|
139
111
|
case "phone":
|
140
|
-
return ((
|
112
|
+
return ((t = l.phone) == null ? void 0 : t.phoneNumber) || e.phone || "";
|
141
113
|
case "location":
|
142
|
-
return (
|
114
|
+
return (m == null ? void 0 : m.city) || l.location || "";
|
143
115
|
case "timezone":
|
144
|
-
return
|
116
|
+
return l.timezone || "";
|
145
117
|
case "link":
|
146
|
-
return ((
|
118
|
+
return ((o = l.links) == null ? void 0 : o.map((d) => d.url).filter(Boolean)) || [];
|
147
119
|
default:
|
148
|
-
return e[
|
120
|
+
return e[n] || "";
|
149
121
|
}
|
150
122
|
},
|
151
|
-
[e,
|
152
|
-
), { effectiveRenderCount:
|
153
|
-
const
|
154
|
-
if (
|
155
|
-
const
|
156
|
-
return
|
157
|
-
}), i =
|
158
|
-
const d =
|
159
|
-
return
|
123
|
+
[e, l, m]
|
124
|
+
), { effectiveRenderCount: F } = N(() => {
|
125
|
+
const n = a.filter((t) => {
|
126
|
+
if (t === "bio") return !1;
|
127
|
+
const o = c(t);
|
128
|
+
return o == null || o === "" ? !1 : D(o) ? o.length > 0 : String(o).trim().length > 0;
|
129
|
+
}), i = n.reduce((t, o) => {
|
130
|
+
const d = c(o);
|
131
|
+
return t + (Array.isArray(d) ? d.filter((C) => C && String(C).trim()).length : 1);
|
160
132
|
}, 0);
|
161
|
-
return { visibleFields:
|
162
|
-
}, [a,
|
163
|
-
(
|
164
|
-
),
|
165
|
-
const
|
133
|
+
return { visibleFields: n, effectiveRenderCount: i };
|
134
|
+
}, [a, c]), L = F > 4, b = T(
|
135
|
+
(n) => n != null && String(n).trim().length > 0
|
136
|
+
), I = N(() => {
|
137
|
+
const n = [];
|
166
138
|
return a.forEach((i) => {
|
167
139
|
if (i === "bio") return;
|
168
|
-
const
|
169
|
-
|
170
|
-
|
140
|
+
const t = c(i);
|
141
|
+
t && (D(t) ? t.forEach((o, d) => {
|
142
|
+
b(o) && n.push({
|
171
143
|
field: i,
|
172
|
-
value:
|
144
|
+
value: o,
|
173
145
|
key: `${i}-${d}`
|
174
146
|
});
|
175
|
-
}) :
|
147
|
+
}) : b(t) && n.push({
|
176
148
|
field: i,
|
177
|
-
value:
|
149
|
+
value: t,
|
178
150
|
key: i
|
179
151
|
}));
|
180
|
-
}),
|
181
|
-
}, [a,
|
152
|
+
}), n;
|
153
|
+
}, [a, c, b]);
|
182
154
|
if (a.length === 0)
|
183
155
|
return null;
|
184
|
-
const z = (
|
185
|
-
const { field: i, value:
|
156
|
+
const z = (n) => {
|
157
|
+
const { field: i, value: t, key: o } = n;
|
186
158
|
switch (i) {
|
187
159
|
case "link":
|
188
|
-
return /* @__PURE__ */
|
160
|
+
return /* @__PURE__ */ r(K, { value: t }, o);
|
189
161
|
case "timezone":
|
190
|
-
return /* @__PURE__ */
|
162
|
+
return /* @__PURE__ */ r(J, { value: t }, o);
|
191
163
|
case "email":
|
192
|
-
return /* @__PURE__ */
|
193
|
-
|
164
|
+
return /* @__PURE__ */ r(
|
165
|
+
S,
|
194
166
|
{
|
195
167
|
field: i,
|
196
|
-
value:
|
197
|
-
children: /* @__PURE__ */
|
198
|
-
|
168
|
+
value: t,
|
169
|
+
children: /* @__PURE__ */ r(
|
170
|
+
g,
|
199
171
|
{
|
200
172
|
component: "a",
|
201
|
-
href: `mailto:${
|
173
|
+
href: `mailto:${t}`,
|
202
174
|
rel: "noopener noreferrer",
|
203
175
|
referrerPolicy: "no-referrer",
|
204
176
|
style: {
|
@@ -206,17 +178,17 @@ function de({ user: e, renderFields: m }) {
|
|
206
178
|
textDecoration: "none",
|
207
179
|
fontSize: "inherit"
|
208
180
|
},
|
209
|
-
children:
|
181
|
+
children: t
|
210
182
|
}
|
211
183
|
)
|
212
184
|
}
|
213
185
|
);
|
214
186
|
default:
|
215
|
-
return /* @__PURE__ */
|
187
|
+
return /* @__PURE__ */ r(S, { field: i, value: t }, o);
|
216
188
|
}
|
217
189
|
};
|
218
|
-
return /* @__PURE__ */
|
219
|
-
|
190
|
+
return /* @__PURE__ */ y(
|
191
|
+
f,
|
220
192
|
{
|
221
193
|
className: "user-card__basic-content",
|
222
194
|
sx: {
|
@@ -226,23 +198,23 @@ function de({ user: e, renderFields: m }) {
|
|
226
198
|
gap: 1.5
|
227
199
|
},
|
228
200
|
children: [
|
229
|
-
|
230
|
-
|
231
|
-
|
201
|
+
h && ((w = e.metadata) == null ? void 0 : w.bio) && /* @__PURE__ */ r(v, { variant: "body2", color: "grey.800", className: "user-card__bio-field", children: e.metadata.bio }),
|
202
|
+
L ? /* @__PURE__ */ r(_, { container: !0, spacing: 0.5, children: I.map((n) => /* @__PURE__ */ r(_, { size: 6, children: z(n) }, n.key)) }) : /* @__PURE__ */ r(
|
203
|
+
f,
|
232
204
|
{
|
233
205
|
sx: {
|
234
206
|
display: "flex",
|
235
207
|
flexDirection: "column",
|
236
208
|
gap: 0.5
|
237
209
|
},
|
238
|
-
children:
|
210
|
+
children: I.map((n) => z(n))
|
239
211
|
}
|
240
212
|
)
|
241
213
|
]
|
242
214
|
}
|
243
215
|
);
|
244
216
|
}
|
245
|
-
const
|
217
|
+
const v = $(g)`
|
246
218
|
flex: 1;
|
247
219
|
display: -webkit-box;
|
248
220
|
line-height: 1.5;
|
@@ -253,5 +225,5 @@ const I = B(k)`
|
|
253
225
|
word-break: break-word;
|
254
226
|
`;
|
255
227
|
export {
|
256
|
-
|
228
|
+
se as default
|
257
229
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arcblock/ux",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.2",
|
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": "82d588535242081273ada50bca749f532689b785",
|
64
64
|
"dependencies": {
|
65
|
-
"@arcblock/bridge": "3.0.
|
65
|
+
"@arcblock/bridge": "3.0.2",
|
66
66
|
"@arcblock/did": "^1.20.14",
|
67
67
|
"@arcblock/did-motif": "^1.1.13",
|
68
|
-
"@arcblock/icons": "3.0.
|
69
|
-
"@arcblock/nft-display": "3.0.
|
70
|
-
"@arcblock/react-hooks": "3.0.
|
68
|
+
"@arcblock/icons": "3.0.2",
|
69
|
+
"@arcblock/nft-display": "3.0.2",
|
70
|
+
"@arcblock/react-hooks": "3.0.2",
|
71
71
|
"@blocklet/js-sdk": "^1.16.44",
|
72
|
-
"@blocklet/theme": "3.0.
|
72
|
+
"@blocklet/theme": "3.0.2",
|
73
73
|
"@fontsource/roboto": "~5.1.1",
|
74
74
|
"@fontsource/ubuntu-mono": "^5.2.6",
|
75
75
|
"@iconify-icons/logos": "^1.2.36",
|
@@ -51,10 +51,6 @@ export default function LoadingMask({
|
|
51
51
|
'&::before,&::after': {
|
52
52
|
content: '""',
|
53
53
|
position: 'absolute',
|
54
|
-
top: 0,
|
55
|
-
bottom: 0,
|
56
|
-
left: 0,
|
57
|
-
right: 0,
|
58
54
|
pointerEvents: 'none',
|
59
55
|
},
|
60
56
|
'&::after': {
|
@@ -66,16 +62,20 @@ export default function LoadingMask({
|
|
66
62
|
borderRadius: `${finialRadius - finialBorderWidth}px`,
|
67
63
|
},
|
68
64
|
'&::before': {
|
65
|
+
width: finialSize * 5,
|
66
|
+
height: finialSize * 5,
|
67
|
+
top: '50%',
|
68
|
+
left: '50%',
|
69
|
+
transform: 'translate(-50%, -50%)',
|
69
70
|
background: ({ palette }) =>
|
70
71
|
`conic-gradient(from 45deg, transparent 0%, transparent 50%, ${palette.secondary.main} 90%, ${palette.secondary.main} 100%)`,
|
71
|
-
transform: 'scale(100)',
|
72
72
|
animation: `rotate ${finialDuration}s linear infinite`,
|
73
73
|
'@keyframes rotate': {
|
74
74
|
'0%': {
|
75
|
-
transform: '
|
75
|
+
transform: 'translate(-50%, -50%) rotate(0deg)',
|
76
76
|
},
|
77
77
|
'100%': {
|
78
|
-
transform: '
|
78
|
+
transform: 'translate(-50%, -50%) rotate(360deg)',
|
79
79
|
},
|
80
80
|
},
|
81
81
|
},
|
@@ -9,8 +9,8 @@ import PhoneIcon from '@arcblock/icons/lib/Phone';
|
|
9
9
|
import LocationIcon from '@arcblock/icons/lib/Location';
|
10
10
|
import EmailIcon from '@arcblock/icons/lib/Email';
|
11
11
|
import TimezoneIcon from '@arcblock/icons/lib/Timezone';
|
12
|
-
import {
|
13
|
-
import {
|
12
|
+
import { withoutProtocol } from 'ufo';
|
13
|
+
import { useMemo, useCallback } from 'react';
|
14
14
|
|
15
15
|
import { User } from '../types';
|
16
16
|
import Clock from './clock';
|
@@ -75,40 +75,12 @@ function TimeZoneField({ value }: { value: string }) {
|
|
75
75
|
}
|
76
76
|
|
77
77
|
function LinkField({ value }: { value: string }) {
|
78
|
-
const [useFallback, setUseFallback] = useState(false);
|
79
78
|
const theme = useTheme();
|
80
79
|
const isDark = theme.palette.mode === 'dark';
|
81
|
-
const faviconUrl = useCreation(() => {
|
82
|
-
try {
|
83
|
-
const url = new URL(value);
|
84
|
-
return joinURL(url.origin, 'favicon.ico');
|
85
|
-
} catch (e) {
|
86
|
-
return '';
|
87
|
-
}
|
88
|
-
}, [value]);
|
89
|
-
|
90
|
-
const handleImageError = () => {
|
91
|
-
setUseFallback(true);
|
92
|
-
};
|
93
80
|
|
94
81
|
return (
|
95
|
-
<Box
|
96
|
-
|
97
|
-
sx={{
|
98
|
-
display: 'flex',
|
99
|
-
alignItems: 'center',
|
100
|
-
gap: 1,
|
101
|
-
}}>
|
102
|
-
{faviconUrl && !useFallback ? (
|
103
|
-
<img
|
104
|
-
src={faviconUrl}
|
105
|
-
alt="site icon"
|
106
|
-
style={{ width: 16, height: 16, objectFit: 'contain' }}
|
107
|
-
onError={handleImageError}
|
108
|
-
/>
|
109
|
-
) : (
|
110
|
-
<LinkIcon {...iconSize} style={convertIconColor(isDark)} />
|
111
|
-
)}
|
82
|
+
<Box display="flex" alignItems="center" gap={1} className="user-card__link-field">
|
83
|
+
<LinkIcon {...iconSize} style={convertIconColor(isDark)} />
|
112
84
|
<LineText variant="body2" color="grey.800">
|
113
85
|
<Typography
|
114
86
|
component="a"
|