@blocklet/ui-react 3.2.8 → 3.2.10
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/UserCenter/components/user-info/link-preview-input.js +79 -63
- package/lib/UserCenter/components/user-info/metadata.js +89 -89
- package/lib/UserCenter/components/user-info/timezone-select.js +39 -33
- package/lib/UserCenter/components/user-info/utils.d.ts +4 -0
- package/lib/UserCenter/components/user-info/utils.js +116 -51
- package/package.json +6 -6
- package/src/UserCenter/components/user-info/link-preview-input.tsx +19 -1
- package/src/UserCenter/components/user-info/metadata.tsx +4 -4
- package/src/UserCenter/components/user-info/timezone-select.tsx +25 -18
- package/src/UserCenter/components/user-info/utils.ts +83 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { styled as
|
|
1
|
+
import { jsx as e, jsxs as f } from "react/jsx-runtime";
|
|
2
|
+
import { useState as I, useMemo as C } from "react";
|
|
3
|
+
import { styled as k, Box as p, Typography as y, IconButton as D, Button as U, useTheme as S, FormControl as B, TextField as F } from "@mui/material";
|
|
4
4
|
import { Remove as T, Add as _ } from "@mui/icons-material";
|
|
5
5
|
import { translate as z } from "@arcblock/ux/lib/Locale/util";
|
|
6
6
|
import { useMemoizedFn as E } from "ahooks";
|
|
@@ -8,48 +8,49 @@ import { useLocaleContext as M } from "@arcblock/ux/lib/Locale/context";
|
|
|
8
8
|
import R from "@arcblock/icons/lib/Link";
|
|
9
9
|
import { mergeSx as j } from "@arcblock/ux/lib/Util/style";
|
|
10
10
|
import { withoutProtocol as A } from "ufo";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
import { Icon as P } from "@iconify/react";
|
|
12
|
+
import { isValidUrl as h, getLogoByUrl as W, isDuplicateUrl as N } from "./utils.js";
|
|
13
|
+
import { translations as V } from "../../libs/locales.js";
|
|
14
|
+
import { inputFieldStyle as K, commonInputStyle as O } from "../editable-field.js";
|
|
15
|
+
const g = 10;
|
|
16
|
+
function X(t) {
|
|
17
|
+
return A(t);
|
|
17
18
|
}
|
|
18
|
-
function
|
|
19
|
-
value:
|
|
20
|
-
onChange:
|
|
21
|
-
errorMsg:
|
|
19
|
+
function $({
|
|
20
|
+
value: t,
|
|
21
|
+
onChange: s,
|
|
22
|
+
errorMsg: l
|
|
22
23
|
}) {
|
|
23
|
-
return /* @__PURE__ */
|
|
24
|
-
|
|
24
|
+
return /* @__PURE__ */ e(B, { fullWidth: !0, children: /* @__PURE__ */ e(
|
|
25
|
+
F,
|
|
25
26
|
{
|
|
26
27
|
variant: "outlined",
|
|
27
|
-
value:
|
|
28
|
+
value: t,
|
|
28
29
|
onChange: (i) => {
|
|
29
30
|
const u = i.target.value;
|
|
30
|
-
|
|
31
|
+
s(u);
|
|
31
32
|
},
|
|
32
33
|
fullWidth: !0,
|
|
33
|
-
error: !!
|
|
34
|
-
helperText:
|
|
35
|
-
sx: j(
|
|
34
|
+
error: !!l,
|
|
35
|
+
helperText: l,
|
|
36
|
+
sx: j(K, l ? {} : O)
|
|
36
37
|
}
|
|
37
38
|
) });
|
|
38
39
|
}
|
|
39
|
-
function
|
|
40
|
-
const { locale:
|
|
41
|
-
const
|
|
42
|
-
return !h(
|
|
43
|
-
}, [i,
|
|
44
|
-
(
|
|
45
|
-
},
|
|
46
|
-
const
|
|
47
|
-
u(
|
|
48
|
-
}, b = (
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const c = [...i], d = !!(
|
|
52
|
-
c[
|
|
40
|
+
function q({ links: t = [], onChange: s }) {
|
|
41
|
+
const { locale: l } = M(), r = E((o, n = {}) => z(V, o, l, "en", n)), [i, u] = I([""]), x = C(() => {
|
|
42
|
+
const o = t[t.length - 1];
|
|
43
|
+
return !h(o) || i.length > 0 && i[i.length - 1];
|
|
44
|
+
}, [i, t]), v = () => {
|
|
45
|
+
(t.length < g || !x) && s([...t, ""]);
|
|
46
|
+
}, L = (o) => {
|
|
47
|
+
const n = t.filter((c, d) => d !== o), a = i.filter((c, d) => d !== o);
|
|
48
|
+
u(a), s(n);
|
|
49
|
+
}, b = (o, n) => {
|
|
50
|
+
const a = [...t];
|
|
51
|
+
a[o] = n;
|
|
52
|
+
const c = [...i], d = !!(n && !h(n));
|
|
53
|
+
c[o] = !1, d ? c[o] = d : a.filter((m, w) => m && h(m) && w !== o).some((m) => N(m, n)) && (c[o] = "duplicate"), u(c), s(a);
|
|
53
54
|
};
|
|
54
55
|
return /* @__PURE__ */ f(
|
|
55
56
|
p,
|
|
@@ -58,7 +59,7 @@ function X({ links: e = [], onChange: a }) {
|
|
|
58
59
|
width: "100%"
|
|
59
60
|
},
|
|
60
61
|
children: [
|
|
61
|
-
/* @__PURE__ */
|
|
62
|
+
/* @__PURE__ */ e(
|
|
62
63
|
p,
|
|
63
64
|
{
|
|
64
65
|
sx: {
|
|
@@ -67,12 +68,12 @@ function X({ links: e = [], onChange: a }) {
|
|
|
67
68
|
alignItems: "center",
|
|
68
69
|
gap: 1
|
|
69
70
|
},
|
|
70
|
-
children: /* @__PURE__ */
|
|
71
|
+
children: /* @__PURE__ */ e(y, { variant: "subtitle1", gutterBottom: !0, sx: { mb: 0, fontSize: "12px", color: "text.primary" }, children: r("profile.socialMedia") })
|
|
71
72
|
}
|
|
72
73
|
),
|
|
73
|
-
|
|
74
|
-
let
|
|
75
|
-
return i[
|
|
74
|
+
t.map((o, n) => {
|
|
75
|
+
let a = "";
|
|
76
|
+
return i[n] === "duplicate" ? a = r("profile.duplicateURL") : i[n] === !0 ? a = r("profile.invalidURL") : a = "", /* @__PURE__ */ f(
|
|
76
77
|
p,
|
|
77
78
|
{
|
|
78
79
|
sx: {
|
|
@@ -81,20 +82,20 @@ function X({ links: e = [], onChange: a }) {
|
|
|
81
82
|
mb: 1
|
|
82
83
|
},
|
|
83
84
|
children: [
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
-
/* @__PURE__ */
|
|
85
|
+
/* @__PURE__ */ e($, { value: o, onChange: (c) => b(n, c), errorMsg: a }),
|
|
86
|
+
/* @__PURE__ */ e(D, { onClick: () => L(n), children: /* @__PURE__ */ e(T, { sx: { color: "text.secondary" } }) })
|
|
86
87
|
]
|
|
87
88
|
},
|
|
88
|
-
|
|
89
|
+
n
|
|
89
90
|
);
|
|
90
91
|
}),
|
|
91
|
-
|
|
92
|
+
t.length < g ? /* @__PURE__ */ f(
|
|
92
93
|
U,
|
|
93
94
|
{
|
|
94
95
|
fullWidth: !0,
|
|
95
96
|
variant: "outlined",
|
|
96
|
-
disabled: !!
|
|
97
|
-
onClick:
|
|
97
|
+
disabled: !!x,
|
|
98
|
+
onClick: v,
|
|
98
99
|
size: "small",
|
|
99
100
|
sx: {
|
|
100
101
|
height: "40px",
|
|
@@ -110,26 +111,41 @@ function X({ links: e = [], onChange: a }) {
|
|
|
110
111
|
}
|
|
111
112
|
},
|
|
112
113
|
children: [
|
|
113
|
-
/* @__PURE__ */
|
|
114
|
+
/* @__PURE__ */ e(_, {}),
|
|
114
115
|
" ",
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ e("span", { children: r("profile.addLink") })
|
|
116
117
|
]
|
|
117
118
|
}
|
|
118
|
-
) : /* @__PURE__ */
|
|
119
|
+
) : /* @__PURE__ */ e(y, { variant: "subtitle1", gutterBottom: !0, sx: { mb: 0, fontSize: "12px", color: "text.secondary" }, children: r("profile.maxLinkCount", { count: g }) })
|
|
119
120
|
]
|
|
120
121
|
}
|
|
121
122
|
);
|
|
122
123
|
}
|
|
123
|
-
function
|
|
124
|
-
const
|
|
125
|
-
|
|
124
|
+
function G({ link: t }) {
|
|
125
|
+
const l = S().palette.mode === "dark";
|
|
126
|
+
if (!t)
|
|
127
|
+
return null;
|
|
128
|
+
const { icon: r, options: i } = W(t) || {};
|
|
129
|
+
return r ? /* @__PURE__ */ e(
|
|
130
|
+
P,
|
|
131
|
+
{
|
|
132
|
+
icon: r,
|
|
133
|
+
width: 20,
|
|
134
|
+
height: 20,
|
|
135
|
+
style: {
|
|
136
|
+
filter: l && !i?.skipDarkInvert ? "brightness(0) saturate(100%) invert(1)" : "none",
|
|
137
|
+
transform: "scale(0.8)"
|
|
138
|
+
},
|
|
139
|
+
...i
|
|
140
|
+
}
|
|
141
|
+
) : /* @__PURE__ */ e(R, { width: 20, height: 20, style: { filter: l ? "brightness(0) saturate(100%) invert(1)" : "none" } });
|
|
126
142
|
}
|
|
127
|
-
function
|
|
128
|
-
editable:
|
|
129
|
-
links:
|
|
130
|
-
onChange:
|
|
143
|
+
function ut({
|
|
144
|
+
editable: t = !1,
|
|
145
|
+
links: s = [],
|
|
146
|
+
onChange: l
|
|
131
147
|
}) {
|
|
132
|
-
return
|
|
148
|
+
return t ? /* @__PURE__ */ e(q, { links: s, onChange: l }) : /* @__PURE__ */ e(
|
|
133
149
|
p,
|
|
134
150
|
{
|
|
135
151
|
sx: {
|
|
@@ -138,7 +154,7 @@ function ce({
|
|
|
138
154
|
flexDirection: "column",
|
|
139
155
|
gap: 2
|
|
140
156
|
},
|
|
141
|
-
children:
|
|
157
|
+
children: s.map((r) => /* @__PURE__ */ f(
|
|
142
158
|
p,
|
|
143
159
|
{
|
|
144
160
|
sx: {
|
|
@@ -149,23 +165,23 @@ function ce({
|
|
|
149
165
|
width: "100%"
|
|
150
166
|
},
|
|
151
167
|
children: [
|
|
152
|
-
/* @__PURE__ */
|
|
153
|
-
/* @__PURE__ */
|
|
168
|
+
/* @__PURE__ */ e(G, { link: r }),
|
|
169
|
+
/* @__PURE__ */ e(H, { children: /* @__PURE__ */ e(p, { component: "a", href: r, style: { textDecoration: "none" }, target: "_blank", rel: "noopener noreferrer", children: X(r) }) })
|
|
154
170
|
]
|
|
155
171
|
},
|
|
156
|
-
|
|
172
|
+
r
|
|
157
173
|
))
|
|
158
174
|
}
|
|
159
175
|
);
|
|
160
176
|
}
|
|
161
|
-
const
|
|
177
|
+
const H = k("span")`
|
|
162
178
|
flex: 1;
|
|
163
179
|
white-space: nowrap;
|
|
164
180
|
overflow: hidden;
|
|
165
181
|
text-overflow: ellipsis;
|
|
166
182
|
&,
|
|
167
183
|
& > * {
|
|
168
|
-
color: ${({ theme:
|
|
184
|
+
color: ${({ theme: t }) => t.palette.text.primary};
|
|
169
185
|
}
|
|
170
186
|
|
|
171
187
|
& > * {
|
|
@@ -177,5 +193,5 @@ const q = I("span")`
|
|
|
177
193
|
}
|
|
178
194
|
`;
|
|
179
195
|
export {
|
|
180
|
-
|
|
196
|
+
ut as LinkPreviewInput
|
|
181
197
|
};
|
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
import { jsxs as y, Fragment as L, jsx as t } from "react/jsx-runtime";
|
|
2
|
-
import { lazy as I, memo as
|
|
3
|
-
import { Icon as
|
|
4
|
-
import { Backdrop as
|
|
5
|
-
import
|
|
2
|
+
import { lazy as I, memo as re, createElement as ie, useState as D, useRef as ae, useEffect as le, useMemo as F } from "react";
|
|
3
|
+
import { Icon as de } from "@iconify/react";
|
|
4
|
+
import { Backdrop as ce, Box as m, useMediaQuery as se, SwipeableDrawer as pe, Typography as N, Tooltip as me } from "@mui/material";
|
|
5
|
+
import ue from "@emotion/styled";
|
|
6
6
|
import j from "@arcblock/ux/lib/Button";
|
|
7
|
-
import
|
|
7
|
+
import T, { detectCountryFromPhone as M, getCountryNameByCountry as he, validatePhoneNumber as fe, getDialCodeByCountry as ye } from "@arcblock/ux/lib/PhoneInput";
|
|
8
8
|
import v from "lodash/cloneDeep";
|
|
9
|
-
import
|
|
10
|
-
import { mergeSx as
|
|
11
|
-
import { LOGIN_PROVIDER as
|
|
12
|
-
import { useReactive as w, useCreation as k, useMemoizedFn as
|
|
13
|
-
import { translate as
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import { useLocaleContext as
|
|
17
|
-
import { useBrowser as
|
|
18
|
-
import
|
|
19
|
-
import { translations as
|
|
20
|
-
import g, { inputFieldStyle as
|
|
21
|
-
import { LinkPreviewInput as
|
|
22
|
-
import { defaultButtonStyle as
|
|
23
|
-
import { TimezoneSelect as
|
|
24
|
-
import
|
|
25
|
-
const
|
|
9
|
+
import xe from "lodash/omit";
|
|
10
|
+
import { mergeSx as be } from "@arcblock/ux/lib/Util/style";
|
|
11
|
+
import { LOGIN_PROVIDER as $ } from "@arcblock/ux/lib/Util/constant";
|
|
12
|
+
import { useReactive as w, useCreation as k, useMemoizedFn as ge } from "ahooks";
|
|
13
|
+
import { translate as Ce } from "@arcblock/ux/lib/Locale/util";
|
|
14
|
+
import ve from "validator/lib/isEmail";
|
|
15
|
+
import G from "validator/lib/isPostalCode";
|
|
16
|
+
import { useLocaleContext as we } from "@arcblock/ux/lib/Locale/context";
|
|
17
|
+
import { useBrowser as ke } from "@arcblock/react-hooks";
|
|
18
|
+
import Ee from "@arcblock/ux/lib/UserCard/Content/clock";
|
|
19
|
+
import { translations as Ie } from "../../libs/locales.js";
|
|
20
|
+
import g, { inputFieldStyle as ze, commonInputStyle as Pe } from "../editable-field.js";
|
|
21
|
+
import { LinkPreviewInput as Ve } from "./link-preview-input.js";
|
|
22
|
+
import { defaultButtonStyle as H, primaryButtonStyle as Be } from "./utils.js";
|
|
23
|
+
import { TimezoneSelect as Le } from "./timezone-select.js";
|
|
24
|
+
import Ne from "./address.js";
|
|
25
|
+
const je = I(() => import("@arcblock/icons/lib/Location")), Ae = I(() => import("@arcblock/icons/lib/Timezone")), Se = I(() => import("@arcblock/icons/lib/Email")), Oe = I(() => import("@arcblock/icons/lib/Phone")), E = {
|
|
26
26
|
width: 20,
|
|
27
27
|
height: 20
|
|
28
|
-
},
|
|
28
|
+
}, Q = 200, U = re(function({
|
|
29
29
|
ref: r,
|
|
30
30
|
...z
|
|
31
31
|
}) {
|
|
32
|
-
return /* @__PURE__ */
|
|
33
|
-
|
|
32
|
+
return /* @__PURE__ */ ie(
|
|
33
|
+
ce,
|
|
34
34
|
{
|
|
35
35
|
ref: r,
|
|
36
36
|
component: "div",
|
|
@@ -44,14 +44,14 @@ const Ae = I(() => import("@arcblock/icons/lib/Location")), Se = I(() => import(
|
|
|
44
44
|
}
|
|
45
45
|
);
|
|
46
46
|
});
|
|
47
|
-
|
|
48
|
-
function
|
|
47
|
+
U.displayName = "BackdropWrap";
|
|
48
|
+
function co({
|
|
49
49
|
isMyself: s,
|
|
50
50
|
user: r,
|
|
51
51
|
onSave: z,
|
|
52
52
|
isMobile: x
|
|
53
53
|
}) {
|
|
54
|
-
const [
|
|
54
|
+
const [Y, P] = D(!1), [_, C] = D(!1), q = ae(null), J = ke(), b = se("(max-width:640px)") || J.mobile.any, c = w({
|
|
55
55
|
email: "",
|
|
56
56
|
phone: ""
|
|
57
57
|
}), u = w({
|
|
@@ -62,10 +62,10 @@ function so({
|
|
|
62
62
|
line2: "",
|
|
63
63
|
postalCode: ""
|
|
64
64
|
});
|
|
65
|
-
|
|
65
|
+
le(() => {
|
|
66
66
|
b || C(!1);
|
|
67
67
|
}, [b]);
|
|
68
|
-
const
|
|
68
|
+
const A = k(() => r?.phoneVerified ?? !1, [r?.phoneVerified]), S = k(() => r?.emailVerified ?? !1, [r?.emailVerified]), { locale: V } = we(), d = ge((o, n = {}) => Ce(Ie, o, V, "en", n)), a = w(
|
|
69
69
|
r?.metadata ? v(r.metadata) : {
|
|
70
70
|
joinedAt: r?.createdAt,
|
|
71
71
|
email: r?.email,
|
|
@@ -83,20 +83,20 @@ function so({
|
|
|
83
83
|
line2: "",
|
|
84
84
|
postalCode: ""
|
|
85
85
|
}
|
|
86
|
-
),
|
|
86
|
+
), K = k(() => !!r?.address, [r?.address?.country]), h = F(() => r?.address?.country ? r.address.country : V === "zh" ? "cn" : "us", [r?.address?.country, V]), B = k(() => {
|
|
87
87
|
const o = a.phone ?? r?.phone ?? {
|
|
88
88
|
country: h,
|
|
89
89
|
phone: ""
|
|
90
90
|
};
|
|
91
91
|
if (o && typeof o == "string")
|
|
92
92
|
return {
|
|
93
|
-
country:
|
|
93
|
+
country: M(o) || h,
|
|
94
94
|
phone: o
|
|
95
95
|
};
|
|
96
96
|
if (o && typeof o == "object") {
|
|
97
97
|
const { country: n = "", phoneNumber: e = "" } = o;
|
|
98
98
|
return {
|
|
99
|
-
country: n ||
|
|
99
|
+
country: n || M(e) || "",
|
|
100
100
|
phone: e || ""
|
|
101
101
|
};
|
|
102
102
|
}
|
|
@@ -106,11 +106,11 @@ function so({
|
|
|
106
106
|
};
|
|
107
107
|
}, [a.phone, r?.phone, h]), p = (o, n) => {
|
|
108
108
|
a[n] = o;
|
|
109
|
-
},
|
|
110
|
-
l[o] = n, o === "city" && p(n, "location"), o === "postalCode" ? u.postalCode = n && !
|
|
111
|
-
},
|
|
109
|
+
}, X = (o, n) => {
|
|
110
|
+
l[o] = n, o === "city" && p(n, "location"), o === "postalCode" ? u.postalCode = n && !G(n, "any") ? d("profile.address.invalidPostalCode") : "" : u[o] = "";
|
|
111
|
+
}, O = () => {
|
|
112
112
|
b ? C(!0) : P(!0);
|
|
113
|
-
},
|
|
113
|
+
}, W = () => {
|
|
114
114
|
const o = v(r?.metadata) ?? {};
|
|
115
115
|
o && Object.keys(a).forEach((e) => {
|
|
116
116
|
const i = e;
|
|
@@ -125,10 +125,10 @@ function so({
|
|
|
125
125
|
e[i] = "";
|
|
126
126
|
});
|
|
127
127
|
}), b ? C(!1) : P(!1);
|
|
128
|
-
},
|
|
128
|
+
}, Z = F(() => {
|
|
129
129
|
const o = a?.links?.map((n) => n.url) || [""];
|
|
130
130
|
return o.length > 0 ? o : [""];
|
|
131
|
-
}, [a.links]),
|
|
131
|
+
}, [a.links]), ee = (o) => {
|
|
132
132
|
const n = o.map((e) => {
|
|
133
133
|
if (!e)
|
|
134
134
|
return {
|
|
@@ -144,22 +144,22 @@ function so({
|
|
|
144
144
|
};
|
|
145
145
|
});
|
|
146
146
|
p(n, "links");
|
|
147
|
-
},
|
|
147
|
+
}, oe = () => {
|
|
148
148
|
if (Object.keys(a).forEach((n) => {
|
|
149
149
|
const e = n, i = a[e];
|
|
150
|
-
if (i && typeof i == "string" && (a[e] = i.trim()), e === "bio" && (a[e] = a[e]?.slice(0,
|
|
151
|
-
const f = i,
|
|
150
|
+
if (i && typeof i == "string" && (a[e] = i.trim()), e === "bio" && (a[e] = a[e]?.slice(0, Q)), e === "timezone" && (a[e] = i || ""), e === "phone" && i && typeof i == "object") {
|
|
151
|
+
const f = i, ne = ye(f.country), te = (f.phoneNumber?.replace(new RegExp(`^\\+${ne}`), "") || "")?.trim().length > 0;
|
|
152
152
|
a[e] = {
|
|
153
153
|
country: f.country,
|
|
154
|
-
...
|
|
154
|
+
...te ? { phoneNumber: f.phoneNumber } : {}
|
|
155
155
|
};
|
|
156
156
|
}
|
|
157
|
-
}), l.postalCode && !
|
|
157
|
+
}), l.postalCode && !G(l.postalCode, "any") && (u.postalCode = d("profile.address.invalidPostalCode")), [c, u].some((n) => Object.values(n).some((e) => e)))
|
|
158
158
|
return;
|
|
159
|
-
const o =
|
|
159
|
+
const o = xe(l, "detailedAddress");
|
|
160
160
|
o.country || (o.country = h), z({ metadata: a, address: o }), P(!1), C(!1);
|
|
161
|
-
},
|
|
162
|
-
|
|
161
|
+
}, R = (o, n = "self") => /* @__PURE__ */ y(
|
|
162
|
+
We,
|
|
163
163
|
{
|
|
164
164
|
pt: 2,
|
|
165
165
|
display: "flex",
|
|
@@ -179,7 +179,7 @@ function so({
|
|
|
179
179
|
inline: !1,
|
|
180
180
|
rows: 3,
|
|
181
181
|
label: d("profile.bio"),
|
|
182
|
-
maxLength:
|
|
182
|
+
maxLength: Q,
|
|
183
183
|
style: {
|
|
184
184
|
...o ? { marginBottom: 8 } : {}
|
|
185
185
|
}
|
|
@@ -191,22 +191,22 @@ function so({
|
|
|
191
191
|
size: x ? "small" : "large",
|
|
192
192
|
variant: "outlined",
|
|
193
193
|
sx: {
|
|
194
|
-
...
|
|
194
|
+
...H,
|
|
195
195
|
mb: x ? "4px" : 2,
|
|
196
196
|
mt: x ? "4px" : 2,
|
|
197
197
|
height: x ? "32px" : "40px"
|
|
198
198
|
},
|
|
199
|
-
onClick:
|
|
199
|
+
onClick: O,
|
|
200
200
|
fullWidth: !0,
|
|
201
201
|
children: d("profile.editProfile")
|
|
202
202
|
}
|
|
203
203
|
) : null,
|
|
204
|
-
o && s &&
|
|
205
|
-
|
|
204
|
+
o && s && K ? /* @__PURE__ */ t(
|
|
205
|
+
Ne,
|
|
206
206
|
{
|
|
207
207
|
address: l,
|
|
208
208
|
errors: u,
|
|
209
|
-
handleChange:
|
|
209
|
+
handleChange: X,
|
|
210
210
|
defaultCountry: h
|
|
211
211
|
}
|
|
212
212
|
) : /* @__PURE__ */ t(
|
|
@@ -233,26 +233,26 @@ function so({
|
|
|
233
233
|
/* @__PURE__ */ t(N, { variant: "caption", component: "span", children: l[e] })
|
|
234
234
|
] }, e) : null) }) : null,
|
|
235
235
|
renderValue: () => {
|
|
236
|
-
const i = [l?.country ?
|
|
236
|
+
const i = [l?.country ? he(l?.country) : "", l.province, l.city || a.location || ""].filter(Boolean).join(" ");
|
|
237
237
|
return /* @__PURE__ */ t(N, { component: "span", children: i });
|
|
238
238
|
},
|
|
239
|
-
icon: /* @__PURE__ */ t(
|
|
239
|
+
icon: /* @__PURE__ */ t(je, { ...E })
|
|
240
240
|
}
|
|
241
241
|
),
|
|
242
242
|
/* @__PURE__ */ t(
|
|
243
243
|
g,
|
|
244
244
|
{
|
|
245
|
-
value: a.timezone ||
|
|
245
|
+
value: a.timezone || "",
|
|
246
246
|
onChange: (e) => p(e, "timezone"),
|
|
247
247
|
editable: o,
|
|
248
248
|
placeholder: "timezone",
|
|
249
|
-
icon: /* @__PURE__ */ t(
|
|
249
|
+
icon: /* @__PURE__ */ t(Ae, { ...E }),
|
|
250
250
|
label: d("profile.timezone"),
|
|
251
|
-
renderValue: (e) => /* @__PURE__ */ t(
|
|
251
|
+
renderValue: (e) => /* @__PURE__ */ t(Ee, { value: e }),
|
|
252
252
|
children: /* @__PURE__ */ t(
|
|
253
|
-
|
|
253
|
+
Le,
|
|
254
254
|
{
|
|
255
|
-
value: a.timezone
|
|
255
|
+
value: a.timezone ?? "",
|
|
256
256
|
onChange: (e) => p(e, "timezone"),
|
|
257
257
|
disabled: !o,
|
|
258
258
|
mode: n
|
|
@@ -266,17 +266,17 @@ function so({
|
|
|
266
266
|
value: a.email ?? r?.email ?? "",
|
|
267
267
|
editable: o,
|
|
268
268
|
hidePreview: !s,
|
|
269
|
-
disabled: r?.sourceProvider ===
|
|
270
|
-
canEdit: !
|
|
271
|
-
verified:
|
|
269
|
+
disabled: r?.sourceProvider === $.EMAIL,
|
|
270
|
+
canEdit: !S,
|
|
271
|
+
verified: S,
|
|
272
272
|
placeholder: "Email",
|
|
273
|
-
icon: /* @__PURE__ */ t(
|
|
273
|
+
icon: /* @__PURE__ */ t(Se, { ...E }),
|
|
274
274
|
label: /* @__PURE__ */ y(L, { children: [
|
|
275
275
|
d("profile.email"),
|
|
276
|
-
r?.sourceProvider ===
|
|
276
|
+
r?.sourceProvider === $.EMAIL ? /* @__PURE__ */ t(me, { title: d("profile.emailSourceProviderNotAllowEdit"), children: /* @__PURE__ */ t(
|
|
277
277
|
m,
|
|
278
278
|
{
|
|
279
|
-
component:
|
|
279
|
+
component: de,
|
|
280
280
|
icon: "mdi:info-outline",
|
|
281
281
|
sx: {
|
|
282
282
|
verticalAlign: "middle",
|
|
@@ -300,7 +300,7 @@ function so({
|
|
|
300
300
|
) : null,
|
|
301
301
|
onValueValidate: (e) => {
|
|
302
302
|
let i = "";
|
|
303
|
-
e && !
|
|
303
|
+
e && !ve(e) && (i = d("profile.emailInvalid")), c.email = i;
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
),
|
|
@@ -310,15 +310,15 @@ function so({
|
|
|
310
310
|
value: B.phone,
|
|
311
311
|
editable: o,
|
|
312
312
|
hidePreview: !s,
|
|
313
|
-
canEdit: !
|
|
314
|
-
verified:
|
|
313
|
+
canEdit: !A,
|
|
314
|
+
verified: A,
|
|
315
315
|
placeholder: "Phone",
|
|
316
|
-
icon: /* @__PURE__ */ t(
|
|
316
|
+
icon: /* @__PURE__ */ t(Oe, { ...E }),
|
|
317
317
|
onChange: (e) => p(e, "phone"),
|
|
318
318
|
label: d("profile.phone"),
|
|
319
|
-
renderValue: () => s ? /* @__PURE__ */ t(
|
|
319
|
+
renderValue: () => s ? /* @__PURE__ */ t(T, { value: B, preview: !0 }) : null,
|
|
320
320
|
children: /* @__PURE__ */ t(
|
|
321
|
-
|
|
321
|
+
T,
|
|
322
322
|
{
|
|
323
323
|
variant: "outlined",
|
|
324
324
|
className: "editable-field",
|
|
@@ -329,9 +329,9 @@ function so({
|
|
|
329
329
|
value: B,
|
|
330
330
|
error: !!c.phone,
|
|
331
331
|
helperText: c.phone,
|
|
332
|
-
sx:
|
|
332
|
+
sx: be(ze, c.phone ? {} : Pe),
|
|
333
333
|
onChange: (e) => {
|
|
334
|
-
|
|
334
|
+
fe(e.phone, e.country) ? c.phone = "" : c.phone = d("profile.phoneInvalid"), p(
|
|
335
335
|
{
|
|
336
336
|
country: e.country,
|
|
337
337
|
phoneNumber: e.phone
|
|
@@ -343,7 +343,7 @@ function so({
|
|
|
343
343
|
)
|
|
344
344
|
}
|
|
345
345
|
),
|
|
346
|
-
/* @__PURE__ */ t(
|
|
346
|
+
/* @__PURE__ */ t(Ve, { editable: o, links: Z, onChange: ee }),
|
|
347
347
|
o && s ? /* @__PURE__ */ y(
|
|
348
348
|
m,
|
|
349
349
|
{
|
|
@@ -361,8 +361,8 @@ function so({
|
|
|
361
361
|
fullWidth: n === "drawer",
|
|
362
362
|
size: "small",
|
|
363
363
|
variant: "outlined",
|
|
364
|
-
sx: { ...
|
|
365
|
-
onClick:
|
|
364
|
+
sx: { ...H, minWidth: "54px" },
|
|
365
|
+
onClick: W,
|
|
366
366
|
children: d("common.cancel")
|
|
367
367
|
}
|
|
368
368
|
),
|
|
@@ -374,13 +374,13 @@ function so({
|
|
|
374
374
|
disabled: !!c.email || !!c.phone,
|
|
375
375
|
variant: "outlined",
|
|
376
376
|
sx: {
|
|
377
|
-
...
|
|
377
|
+
...Be,
|
|
378
378
|
minWidth: "54px",
|
|
379
379
|
"&.Mui-disabled": {
|
|
380
380
|
backgroundColor: "rgba(0, 0, 0, 0.12)"
|
|
381
381
|
}
|
|
382
382
|
},
|
|
383
|
-
onClick:
|
|
383
|
+
onClick: oe,
|
|
384
384
|
children: d("common.save")
|
|
385
385
|
}
|
|
386
386
|
)
|
|
@@ -391,20 +391,20 @@ function so({
|
|
|
391
391
|
}
|
|
392
392
|
);
|
|
393
393
|
return /* @__PURE__ */ y(L, { children: [
|
|
394
|
-
|
|
394
|
+
R(Y),
|
|
395
395
|
b && /* @__PURE__ */ y(
|
|
396
|
-
|
|
396
|
+
pe,
|
|
397
397
|
{
|
|
398
398
|
sx: {
|
|
399
399
|
zIndex: 9999
|
|
400
400
|
},
|
|
401
401
|
disableSwipeToOpen: !0,
|
|
402
|
-
onOpen:
|
|
403
|
-
open:
|
|
402
|
+
onOpen: O,
|
|
403
|
+
open: _,
|
|
404
404
|
anchor: "bottom",
|
|
405
|
-
onClose:
|
|
405
|
+
onClose: W,
|
|
406
406
|
slots: {
|
|
407
|
-
backdrop:
|
|
407
|
+
backdrop: U
|
|
408
408
|
},
|
|
409
409
|
slotProps: {
|
|
410
410
|
paper: {
|
|
@@ -421,7 +421,7 @@ function so({
|
|
|
421
421
|
/* @__PURE__ */ t(
|
|
422
422
|
m,
|
|
423
423
|
{
|
|
424
|
-
ref:
|
|
424
|
+
ref: q,
|
|
425
425
|
sx: {
|
|
426
426
|
padding: "16px 32px",
|
|
427
427
|
margin: "-8px auto -16px",
|
|
@@ -448,7 +448,7 @@ function so({
|
|
|
448
448
|
maxHeight: "500px",
|
|
449
449
|
overflowY: "auto"
|
|
450
450
|
},
|
|
451
|
-
children:
|
|
451
|
+
children: R(!0, "drawer")
|
|
452
452
|
}
|
|
453
453
|
)
|
|
454
454
|
]
|
|
@@ -456,7 +456,7 @@ function so({
|
|
|
456
456
|
)
|
|
457
457
|
] });
|
|
458
458
|
}
|
|
459
|
-
const
|
|
459
|
+
const We = ue(m)`
|
|
460
460
|
width: 100%;
|
|
461
461
|
|
|
462
462
|
.MuiOutlinedInput-root {
|
|
@@ -495,5 +495,5 @@ const Re = he(m)`
|
|
|
495
495
|
}
|
|
496
496
|
`;
|
|
497
497
|
export {
|
|
498
|
-
|
|
498
|
+
co as default
|
|
499
499
|
};
|
|
@@ -1,45 +1,49 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { Select as
|
|
4
|
-
import
|
|
5
|
-
import { KeyboardArrowDown as
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { jsxs as b, jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import { useState as m, useRef as z, useEffect as g } from "react";
|
|
3
|
+
import { Select as y, ListSubheader as T, TextField as w, MenuItem as M } from "@mui/material";
|
|
4
|
+
import { useMemoizedFn as c, useDebounce as I } from "ahooks";
|
|
5
|
+
import { KeyboardArrowDown as S } from "@mui/icons-material";
|
|
6
|
+
import { useLocaleContext as D } from "@arcblock/ux/lib/Locale/context";
|
|
7
|
+
import { translate as O } from "@arcblock/ux/lib/Locale/util";
|
|
8
|
+
import P from "@arcblock/ux/lib/Empty";
|
|
9
|
+
import { getTimezones as F } from "./utils.js";
|
|
10
|
+
import { translations as L } from "../../libs/locales.js";
|
|
11
|
+
const r = F();
|
|
12
|
+
function V({ value: p, onChange: f, disabled: i = !1, mode: h = "self" }) {
|
|
13
|
+
const { locale: x } = D(), n = c((e, o = {}) => O(L, e, x, "en", o)), [l, v] = m(r), [s, C] = m(""), a = I(s, { wait: 500 }), u = z(null), d = c(
|
|
14
|
+
(e) => e ? r.filter((o) => o.value.toLowerCase().includes(e.toLowerCase())) : r
|
|
12
15
|
);
|
|
13
|
-
return
|
|
14
|
-
const e =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}, [
|
|
19
|
-
|
|
16
|
+
return g(() => {
|
|
17
|
+
const e = d(a);
|
|
18
|
+
v(e ?? r), setTimeout(() => {
|
|
19
|
+
u.current?.focus();
|
|
20
|
+
}, 0);
|
|
21
|
+
}, [a, d]), /* @__PURE__ */ b(
|
|
22
|
+
y,
|
|
20
23
|
{
|
|
21
|
-
className: `timezone-select ${
|
|
22
|
-
value:
|
|
23
|
-
onChange: (e) =>
|
|
24
|
-
disabled:
|
|
24
|
+
className: `timezone-select ${i ? "disabled" : ""}`,
|
|
25
|
+
value: p,
|
|
26
|
+
onChange: (e) => f(e.target.value),
|
|
27
|
+
disabled: i,
|
|
25
28
|
displayEmpty: !0,
|
|
26
29
|
variant: "outlined",
|
|
27
|
-
placeholder: "
|
|
30
|
+
placeholder: n("profile.timezone"),
|
|
28
31
|
IconComponent: (e) => /* @__PURE__ */ t(
|
|
29
|
-
|
|
32
|
+
S,
|
|
30
33
|
{
|
|
31
34
|
...e,
|
|
32
|
-
sx: { fontSize: 18, color: (
|
|
35
|
+
sx: { fontSize: 18, color: (o) => `${o.palette.text.secondary} !important` }
|
|
33
36
|
}
|
|
34
37
|
),
|
|
35
38
|
MenuProps: {
|
|
39
|
+
autoFocus: !1,
|
|
36
40
|
PaperProps: {
|
|
37
41
|
style: {
|
|
38
42
|
maxHeight: "400px"
|
|
39
43
|
}
|
|
40
44
|
},
|
|
41
45
|
style: {
|
|
42
|
-
zIndex:
|
|
46
|
+
zIndex: h === "drawer" ? 9999 : 1300
|
|
43
47
|
}
|
|
44
48
|
},
|
|
45
49
|
sx: {
|
|
@@ -54,16 +58,17 @@ function P({ value: s, onChange: u, disabled: l = !1, mode: c = "self" }) {
|
|
|
54
58
|
}
|
|
55
59
|
},
|
|
56
60
|
children: [
|
|
57
|
-
/* @__PURE__ */ t(
|
|
58
|
-
|
|
61
|
+
/* @__PURE__ */ t(T, { children: /* @__PURE__ */ t(
|
|
62
|
+
w,
|
|
59
63
|
{
|
|
64
|
+
inputRef: u,
|
|
60
65
|
autoFocus: !0,
|
|
61
|
-
value:
|
|
62
|
-
placeholder: "
|
|
66
|
+
value: s,
|
|
67
|
+
placeholder: n("profile.timezone"),
|
|
63
68
|
variant: "outlined",
|
|
64
69
|
size: "small",
|
|
65
70
|
fullWidth: !0,
|
|
66
|
-
onChange: (e) =>
|
|
71
|
+
onChange: (e) => C(e.target.value),
|
|
67
72
|
onClick: (e) => e.stopPropagation(),
|
|
68
73
|
onKeyDown: (e) => e.stopPropagation(),
|
|
69
74
|
sx: {
|
|
@@ -83,11 +88,12 @@ function P({ value: s, onChange: u, disabled: l = !1, mode: c = "self" }) {
|
|
|
83
88
|
}
|
|
84
89
|
}
|
|
85
90
|
) }),
|
|
86
|
-
|
|
91
|
+
l.map((e) => /* @__PURE__ */ t(M, { value: e.value, children: e.label }, e.value)),
|
|
92
|
+
l.length > 0 ? null : /* @__PURE__ */ t(P, { children: n("emptyContent") })
|
|
87
93
|
]
|
|
88
94
|
}
|
|
89
95
|
);
|
|
90
96
|
}
|
|
91
97
|
export {
|
|
92
|
-
|
|
98
|
+
V as TimezoneSelect
|
|
93
99
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { withHttps as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
1
|
+
import T from "is-url";
|
|
2
|
+
import { withHttps as u } from "ufo";
|
|
3
|
+
import i from "dayjs";
|
|
4
|
+
import A from "dayjs/plugin/timezone";
|
|
5
|
+
import I from "dayjs/plugin/utc";
|
|
6
6
|
import { DurationEnum as s } from "../../../@types/index.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
7
|
+
i.extend(I);
|
|
8
|
+
i.extend(A);
|
|
9
|
+
const d = 3600, p = 1800, f = 600, k = 300, b = 60, g = 1, E = i.tz.guess(), y = [
|
|
10
10
|
"America/New_York",
|
|
11
11
|
"America/Chicago",
|
|
12
12
|
"America/Denver",
|
|
@@ -28,7 +28,7 @@ const l = 3600, m = 1800, d = 600, f = 300, p = 60, b = 1, _ = n.tz.guess(), y =
|
|
|
28
28
|
"America/Mexico_City",
|
|
29
29
|
"Africa/Cairo",
|
|
30
30
|
"UTC"
|
|
31
|
-
],
|
|
31
|
+
], C = () => {
|
|
32
32
|
if (typeof Intl < "u" && Intl.supportedValuesOf)
|
|
33
33
|
try {
|
|
34
34
|
return Intl.supportedValuesOf("timeZone");
|
|
@@ -43,57 +43,57 @@ const l = 3600, m = 1800, d = 600, f = 300, p = 60, b = 1, _ = n.tz.guess(), y =
|
|
|
43
43
|
console.warn("Intl.DateTimeFormat timezone support limited");
|
|
44
44
|
}
|
|
45
45
|
return y;
|
|
46
|
-
},
|
|
46
|
+
}, _ = () => C().map((o) => {
|
|
47
47
|
try {
|
|
48
|
-
const
|
|
49
|
-
return { label: `GMT${
|
|
48
|
+
const r = i.tz(i(), o).utcOffset() / 60, n = Math.floor(r), a = r % 1 * 60;
|
|
49
|
+
return { label: `GMT${n >= 0 ? "+" : ""}${n}:${a === 30 ? "30" : "00"}`, value: o };
|
|
50
50
|
} catch {
|
|
51
|
-
return console.warn(`Timezone ${
|
|
51
|
+
return console.warn(`Timezone ${o} not supported, skipping`), null;
|
|
52
52
|
}
|
|
53
|
-
}).filter((
|
|
54
|
-
const [
|
|
55
|
-
return
|
|
56
|
-
}).map((
|
|
57
|
-
label: `(${
|
|
58
|
-
value:
|
|
59
|
-
})),
|
|
60
|
-
if (!
|
|
53
|
+
}).filter((o) => o !== null).sort((o, r) => {
|
|
54
|
+
const [n, a] = o.label.replace("GMT", "").split(":").map(Number), [c, l] = r.label.replace("GMT", "").split(":").map(Number), m = n * 60 + a;
|
|
55
|
+
return c * 60 + l - m;
|
|
56
|
+
}).map((o) => ({
|
|
57
|
+
label: `(${o.label}) ${o.value}`,
|
|
58
|
+
value: o.value
|
|
59
|
+
})), h = (t) => T(u(t)), R = (t, e) => {
|
|
60
|
+
if (!t || !e || !h(t) || !h(e))
|
|
61
61
|
return !1;
|
|
62
|
-
const
|
|
63
|
-
return
|
|
64
|
-
},
|
|
65
|
-
let
|
|
66
|
-
const
|
|
67
|
-
switch (
|
|
62
|
+
const o = u(t.trim()), r = u(e.trim());
|
|
63
|
+
return o.toLowerCase() === r.toLowerCase();
|
|
64
|
+
}, z = (t) => {
|
|
65
|
+
let e = t?.dateRange?.map((r) => i(r)) ?? [];
|
|
66
|
+
const o = i();
|
|
67
|
+
switch (t?.duration) {
|
|
68
68
|
case s.ThirtyMinutes:
|
|
69
|
-
|
|
69
|
+
e = [o, o.add(30, "minutes")];
|
|
70
70
|
break;
|
|
71
71
|
case s.OneHour:
|
|
72
|
-
|
|
72
|
+
e = [o, o.add(1, "hour")];
|
|
73
73
|
break;
|
|
74
74
|
case s.FourHours:
|
|
75
|
-
|
|
75
|
+
e = [o, o.add(4, "hours")];
|
|
76
76
|
break;
|
|
77
77
|
case s.Today:
|
|
78
|
-
|
|
78
|
+
e = [o, o.endOf("day")];
|
|
79
79
|
break;
|
|
80
80
|
case s.ThisWeek:
|
|
81
|
-
|
|
81
|
+
e = [o, o.endOf("week")];
|
|
82
82
|
break;
|
|
83
83
|
case s.NoClear:
|
|
84
|
-
|
|
84
|
+
e = [o, o];
|
|
85
85
|
break;
|
|
86
86
|
}
|
|
87
|
-
return
|
|
88
|
-
}, B = (
|
|
89
|
-
const
|
|
90
|
-
return
|
|
91
|
-
},
|
|
92
|
-
const { duration:
|
|
93
|
-
return !
|
|
94
|
-
}, x = (
|
|
95
|
-
const
|
|
96
|
-
return
|
|
87
|
+
return e.map((r) => r.toDate());
|
|
88
|
+
}, B = (t) => {
|
|
89
|
+
const e = i();
|
|
90
|
+
return e.isAfter(i(t[0])) && e.isBefore(i(t[1]));
|
|
91
|
+
}, L = (t) => {
|
|
92
|
+
const { duration: e, dateRange: o } = t ?? {};
|
|
93
|
+
return !e || !o ? !1 : e === s.NoClear || i(o?.[0]).isSame(i(o?.[1]));
|
|
94
|
+
}, x = (t) => {
|
|
95
|
+
const e = i(), r = i(t).diff(e, "seconds"), n = (a) => a * 1e3;
|
|
96
|
+
return r >= d ? n(d) : r >= p ? n(p) : r >= f ? n(f) : r >= k ? n(k) : r >= b ? n(b) : r >= g ? n(g) : 0;
|
|
97
97
|
}, $ = {
|
|
98
98
|
color: "text.primary",
|
|
99
99
|
borderColor: "grey.100",
|
|
@@ -104,7 +104,7 @@ const l = 3600, m = 1800, d = 600, f = 300, p = 60, b = 1, _ = n.tz.guess(), y =
|
|
|
104
104
|
},
|
|
105
105
|
py: 0.5,
|
|
106
106
|
borderRadius: 1
|
|
107
|
-
},
|
|
107
|
+
}, F = {
|
|
108
108
|
color: "primary.contrastText",
|
|
109
109
|
borderColor: "primary.main",
|
|
110
110
|
backgroundColor: "primary.main",
|
|
@@ -114,16 +114,81 @@ const l = 3600, m = 1800, d = 600, f = 300, p = 60, b = 1, _ = n.tz.guess(), y =
|
|
|
114
114
|
},
|
|
115
115
|
py: 0.5,
|
|
116
116
|
borderRadius: 1
|
|
117
|
+
}, O = {
|
|
118
|
+
x: {
|
|
119
|
+
domains: ["twitter.com", "x.com"]
|
|
120
|
+
},
|
|
121
|
+
facebook: {
|
|
122
|
+
domains: ["facebook.com", "fb.com"],
|
|
123
|
+
options: { skipDarkInvert: !0 }
|
|
124
|
+
},
|
|
125
|
+
"linkedin-icon": {
|
|
126
|
+
domains: ["linkedin.com"],
|
|
127
|
+
options: { skipDarkInvert: !0 }
|
|
128
|
+
},
|
|
129
|
+
"github-icon": {
|
|
130
|
+
domains: ["github.com"]
|
|
131
|
+
},
|
|
132
|
+
"instagram-icon": {
|
|
133
|
+
domains: ["instagram.com"]
|
|
134
|
+
},
|
|
135
|
+
"youtube-icon": {
|
|
136
|
+
domains: ["youtube.com", "youtu.be"],
|
|
137
|
+
options: { skipDarkInvert: !0 }
|
|
138
|
+
},
|
|
139
|
+
"tiktok-icon": {
|
|
140
|
+
domains: ["tiktok.com"]
|
|
141
|
+
},
|
|
142
|
+
"reddit-icon": {
|
|
143
|
+
domains: ["reddit.com"],
|
|
144
|
+
options: { skipDarkInvert: !0 }
|
|
145
|
+
},
|
|
146
|
+
"medium-icon": {
|
|
147
|
+
domains: ["medium.com"]
|
|
148
|
+
},
|
|
149
|
+
"discord-icon": {
|
|
150
|
+
domains: ["discord.com", "discord.gg"],
|
|
151
|
+
options: { skipDarkInvert: !0 }
|
|
152
|
+
},
|
|
153
|
+
telegram: {
|
|
154
|
+
domains: ["telegram.org", "t.me"],
|
|
155
|
+
options: { skipDarkInvert: !0 }
|
|
156
|
+
},
|
|
157
|
+
"whatsapp-monochrome-icon": {
|
|
158
|
+
domains: ["whatsapp.com"]
|
|
159
|
+
},
|
|
160
|
+
producthunt: {
|
|
161
|
+
domains: ["producthunt.com"],
|
|
162
|
+
options: { skipDarkInvert: !0 }
|
|
163
|
+
},
|
|
164
|
+
ycombinator: {
|
|
165
|
+
domains: ["ycombinator.com", "news.ycombinator.com"],
|
|
166
|
+
options: { skipDarkInvert: !0 }
|
|
167
|
+
}
|
|
168
|
+
}, H = (t) => {
|
|
169
|
+
try {
|
|
170
|
+
const e = u(t), n = new URL(e).hostname.toLowerCase().replace(/^www\./, "");
|
|
171
|
+
for (const [a, { domains: c, options: l }] of Object.entries(O))
|
|
172
|
+
if (c.some((m) => n === m || n.endsWith(`.${m}`)))
|
|
173
|
+
return {
|
|
174
|
+
icon: `logos:${a}`,
|
|
175
|
+
options: l
|
|
176
|
+
};
|
|
177
|
+
return;
|
|
178
|
+
} catch {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
117
181
|
};
|
|
118
182
|
export {
|
|
119
|
-
|
|
183
|
+
E as currentTimezone,
|
|
120
184
|
$ as defaultButtonStyle,
|
|
121
|
-
|
|
185
|
+
H as getLogoByUrl,
|
|
186
|
+
z as getStatusDuration,
|
|
122
187
|
x as getTimeRemaining,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
188
|
+
_ as getTimezones,
|
|
189
|
+
R as isDuplicateUrl,
|
|
190
|
+
L as isNotClear,
|
|
191
|
+
h as isValidUrl,
|
|
127
192
|
B as isWithinTimeRange,
|
|
128
|
-
|
|
193
|
+
F as primaryButtonStyle
|
|
129
194
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/ui-react",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.10",
|
|
4
4
|
"description": "Some useful front-end web components that can be used in Blocklets.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@abtnode/constant": "1.17.2",
|
|
37
37
|
"@abtnode/util": "1.17.2",
|
|
38
|
-
"@arcblock/bridge": "3.2.
|
|
39
|
-
"@arcblock/icons": "3.2.
|
|
40
|
-
"@arcblock/react-hooks": "3.2.
|
|
38
|
+
"@arcblock/bridge": "3.2.10",
|
|
39
|
+
"@arcblock/icons": "3.2.10",
|
|
40
|
+
"@arcblock/react-hooks": "3.2.10",
|
|
41
41
|
"@arcblock/ws": "^1.27.6",
|
|
42
42
|
"@blocklet/constant": "1.17.2",
|
|
43
43
|
"@blocklet/did-space-react": "^1.2.3",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"access": "public"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"@arcblock/did-connect-react": "3.2.
|
|
86
|
+
"@arcblock/did-connect-react": "3.2.10",
|
|
87
87
|
"@types/dompurify": "^3.2.0",
|
|
88
88
|
"@types/ua-parser-js": "^0.7.39",
|
|
89
89
|
"@types/validator": "^13.15.2",
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"jest": "^29.7.0",
|
|
92
92
|
"unbuild": "^2.0.0"
|
|
93
93
|
},
|
|
94
|
-
"gitHead": "
|
|
94
|
+
"gitHead": "8ed4de885ae6ce687de01add02b489c178da0c12"
|
|
95
95
|
}
|
|
@@ -7,7 +7,8 @@ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
|
7
7
|
import LinkIcon from '@arcblock/icons/lib/Link';
|
|
8
8
|
import { mergeSx } from '@arcblock/ux/lib/Util/style';
|
|
9
9
|
import { withoutProtocol } from 'ufo';
|
|
10
|
-
import {
|
|
10
|
+
import { Icon } from '@iconify/react';
|
|
11
|
+
import { getLogoByUrl, isDuplicateUrl, isValidUrl } from './utils';
|
|
11
12
|
import { translations } from '../../libs/locales';
|
|
12
13
|
import { commonInputStyle, inputFieldStyle } from '../editable-field';
|
|
13
14
|
|
|
@@ -188,6 +189,23 @@ function FaviconPreview({ link }: { link: string }) {
|
|
|
188
189
|
return null;
|
|
189
190
|
}
|
|
190
191
|
|
|
192
|
+
const { icon: logoIcon, options } = getLogoByUrl(link) || {};
|
|
193
|
+
|
|
194
|
+
if (logoIcon) {
|
|
195
|
+
return (
|
|
196
|
+
<Icon
|
|
197
|
+
icon={logoIcon}
|
|
198
|
+
width={20}
|
|
199
|
+
height={20}
|
|
200
|
+
style={{
|
|
201
|
+
filter: isDark && !options?.skipDarkInvert ? 'brightness(0) saturate(100%) invert(1)' : 'none',
|
|
202
|
+
transform: 'scale(0.8)',
|
|
203
|
+
}}
|
|
204
|
+
{...options}
|
|
205
|
+
/>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
191
209
|
return (
|
|
192
210
|
<LinkIcon width={20} height={20} style={{ filter: isDark ? 'brightness(0) saturate(100%) invert(1)' : 'none' }} />
|
|
193
211
|
);
|
|
@@ -28,7 +28,7 @@ import { translations } from '../../libs/locales';
|
|
|
28
28
|
import type { User, UserAddress, UserMetadata, UserPhoneProps } from '../../../@types';
|
|
29
29
|
import EditableField, { commonInputStyle, inputFieldStyle } from '../editable-field';
|
|
30
30
|
import { LinkPreviewInput } from './link-preview-input';
|
|
31
|
-
import {
|
|
31
|
+
import { defaultButtonStyle, primaryButtonStyle } from './utils';
|
|
32
32
|
import { TimezoneSelect } from './timezone-select';
|
|
33
33
|
import AddressEditor from './address';
|
|
34
34
|
|
|
@@ -287,7 +287,7 @@ export default function UserMetadataComponent({
|
|
|
287
287
|
metadata[k] = metadata[k]?.slice(0, bioMaxLength);
|
|
288
288
|
}
|
|
289
289
|
if (k === 'timezone') {
|
|
290
|
-
metadata[k] = (value as string) ||
|
|
290
|
+
metadata[k] = (value as string) || '';
|
|
291
291
|
}
|
|
292
292
|
if (k === 'phone' && value && typeof value === 'object') {
|
|
293
293
|
const phoneInput = value as UserPhoneProps;
|
|
@@ -417,7 +417,7 @@ export default function UserMetadataComponent({
|
|
|
417
417
|
/>
|
|
418
418
|
)}
|
|
419
419
|
<EditableField
|
|
420
|
-
value={metadata.timezone ||
|
|
420
|
+
value={metadata.timezone || ''}
|
|
421
421
|
onChange={(value) => onChange(value, 'timezone')}
|
|
422
422
|
editable={editing}
|
|
423
423
|
placeholder="timezone"
|
|
@@ -427,7 +427,7 @@ export default function UserMetadataComponent({
|
|
|
427
427
|
return <Clock value={value} />;
|
|
428
428
|
}}>
|
|
429
429
|
<TimezoneSelect
|
|
430
|
-
value={metadata.timezone
|
|
430
|
+
value={metadata.timezone ?? ''}
|
|
431
431
|
onChange={(value) => onChange(value, 'timezone')}
|
|
432
432
|
disabled={!editing}
|
|
433
433
|
mode={mode}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { useState, useEffect,
|
|
1
|
+
import { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { MenuItem, Select, SelectChangeEvent, ListSubheader, TextField } from '@mui/material';
|
|
3
|
-
import
|
|
3
|
+
import { useDebounce, useMemoizedFn } from 'ahooks';
|
|
4
4
|
import { KeyboardArrowDown as KeyboardArrowDownIcon } from '@mui/icons-material';
|
|
5
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
6
|
+
import { translate } from '@arcblock/ux/lib/Locale/util';
|
|
7
|
+
import Empty from '@arcblock/ux/lib/Empty';
|
|
5
8
|
import { getTimezones } from './utils';
|
|
9
|
+
import { translations } from '../../libs/locales';
|
|
6
10
|
|
|
7
11
|
const timezones = getTimezones();
|
|
8
12
|
|
|
@@ -14,27 +18,27 @@ interface TimezoneSelectProps {
|
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export function TimezoneSelect({ value, onChange, disabled = false, mode = 'self' }: TimezoneSelectProps) {
|
|
21
|
+
const { locale } = useLocaleContext();
|
|
22
|
+
const t = useMemoizedFn((key, data = {}) => {
|
|
23
|
+
return translate(translations, key, locale, 'en', data);
|
|
24
|
+
});
|
|
17
25
|
const [timezoneData, setTimezoneData] = useState(timezones);
|
|
18
26
|
const [searchText, setSearchText] = useState('');
|
|
27
|
+
const debouncedValue = useDebounce(searchText, { wait: 500 });
|
|
28
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
19
29
|
|
|
20
|
-
const
|
|
21
|
-
() =>
|
|
22
|
-
debounce((v: string) => {
|
|
23
|
-
return v ? timezones.filter((tz) => tz.value.toLowerCase().includes(v.toLowerCase())) : timezones;
|
|
24
|
-
}, 300),
|
|
25
|
-
[]
|
|
30
|
+
const searchTimezones = useMemoizedFn((v: string) =>
|
|
31
|
+
v ? timezones.filter((tz) => tz.value.toLowerCase().includes(v.toLowerCase())) : timezones
|
|
26
32
|
);
|
|
27
33
|
|
|
28
34
|
useEffect(() => {
|
|
29
|
-
const data =
|
|
35
|
+
const data = searchTimezones(debouncedValue);
|
|
30
36
|
setTimezoneData(data ?? timezones);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
37
|
-
}, [timezoneDebounce]);
|
|
37
|
+
// 数据更新后重新聚焦到输入框
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
inputRef.current?.focus();
|
|
40
|
+
}, 0);
|
|
41
|
+
}, [debouncedValue, searchTimezones]);
|
|
38
42
|
|
|
39
43
|
return (
|
|
40
44
|
<Select
|
|
@@ -45,7 +49,7 @@ export function TimezoneSelect({ value, onChange, disabled = false, mode = 'self
|
|
|
45
49
|
displayEmpty
|
|
46
50
|
variant="outlined"
|
|
47
51
|
// @ts-expect-error
|
|
48
|
-
placeholder=
|
|
52
|
+
placeholder={t('profile.timezone')}
|
|
49
53
|
// eslint-disable-next-line react/no-unstable-nested-components
|
|
50
54
|
IconComponent={(props) => (
|
|
51
55
|
<KeyboardArrowDownIcon
|
|
@@ -54,6 +58,7 @@ export function TimezoneSelect({ value, onChange, disabled = false, mode = 'self
|
|
|
54
58
|
/>
|
|
55
59
|
)}
|
|
56
60
|
MenuProps={{
|
|
61
|
+
autoFocus: false,
|
|
57
62
|
PaperProps: {
|
|
58
63
|
style: {
|
|
59
64
|
maxHeight: '400px',
|
|
@@ -76,9 +81,10 @@ export function TimezoneSelect({ value, onChange, disabled = false, mode = 'self
|
|
|
76
81
|
}}>
|
|
77
82
|
<ListSubheader>
|
|
78
83
|
<TextField
|
|
84
|
+
inputRef={inputRef}
|
|
79
85
|
autoFocus
|
|
80
86
|
value={searchText}
|
|
81
|
-
placeholder=
|
|
87
|
+
placeholder={t('profile.timezone')}
|
|
82
88
|
variant="outlined"
|
|
83
89
|
size="small"
|
|
84
90
|
fullWidth
|
|
@@ -107,6 +113,7 @@ export function TimezoneSelect({ value, onChange, disabled = false, mode = 'self
|
|
|
107
113
|
{tz.label}
|
|
108
114
|
</MenuItem>
|
|
109
115
|
))}
|
|
116
|
+
{timezoneData.length > 0 ? null : <Empty>{t('emptyContent')}</Empty>}
|
|
110
117
|
</Select>
|
|
111
118
|
);
|
|
112
119
|
}
|
|
@@ -235,3 +235,86 @@ export const primaryButtonStyle = {
|
|
|
235
235
|
py: 0.5,
|
|
236
236
|
borderRadius: 1,
|
|
237
237
|
};
|
|
238
|
+
|
|
239
|
+
// 域名关键词到平台标识符的映射表
|
|
240
|
+
const DOMAIN_PLATFORM_MAP: Record<string, { domains: string[]; options?: Record<string, any> }> = {
|
|
241
|
+
x: {
|
|
242
|
+
domains: ['twitter.com', 'x.com'],
|
|
243
|
+
},
|
|
244
|
+
facebook: {
|
|
245
|
+
domains: ['facebook.com', 'fb.com'],
|
|
246
|
+
options: { skipDarkInvert: true },
|
|
247
|
+
},
|
|
248
|
+
'linkedin-icon': {
|
|
249
|
+
domains: ['linkedin.com'],
|
|
250
|
+
options: { skipDarkInvert: true },
|
|
251
|
+
},
|
|
252
|
+
'github-icon': {
|
|
253
|
+
domains: ['github.com'],
|
|
254
|
+
},
|
|
255
|
+
'instagram-icon': {
|
|
256
|
+
domains: ['instagram.com'],
|
|
257
|
+
},
|
|
258
|
+
'youtube-icon': {
|
|
259
|
+
domains: ['youtube.com', 'youtu.be'],
|
|
260
|
+
options: { skipDarkInvert: true },
|
|
261
|
+
},
|
|
262
|
+
'tiktok-icon': {
|
|
263
|
+
domains: ['tiktok.com'],
|
|
264
|
+
},
|
|
265
|
+
'reddit-icon': {
|
|
266
|
+
domains: ['reddit.com'],
|
|
267
|
+
options: { skipDarkInvert: true },
|
|
268
|
+
},
|
|
269
|
+
'medium-icon': {
|
|
270
|
+
domains: ['medium.com'],
|
|
271
|
+
},
|
|
272
|
+
'discord-icon': {
|
|
273
|
+
domains: ['discord.com', 'discord.gg'],
|
|
274
|
+
options: { skipDarkInvert: true },
|
|
275
|
+
},
|
|
276
|
+
telegram: {
|
|
277
|
+
domains: ['telegram.org', 't.me'],
|
|
278
|
+
options: { skipDarkInvert: true },
|
|
279
|
+
},
|
|
280
|
+
'whatsapp-monochrome-icon': {
|
|
281
|
+
domains: ['whatsapp.com'],
|
|
282
|
+
},
|
|
283
|
+
producthunt: {
|
|
284
|
+
domains: ['producthunt.com'],
|
|
285
|
+
options: { skipDarkInvert: true },
|
|
286
|
+
},
|
|
287
|
+
ycombinator: {
|
|
288
|
+
domains: ['ycombinator.com', 'news.ycombinator.com'],
|
|
289
|
+
options: { skipDarkInvert: true },
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
export const getLogoByUrl = (url: string): { icon: string; options?: Record<string, any> } | undefined => {
|
|
294
|
+
try {
|
|
295
|
+
// 添加协议(如果没有)
|
|
296
|
+
const fullUrl = withHttps(url);
|
|
297
|
+
|
|
298
|
+
// 解析 URL
|
|
299
|
+
const urlObj = new URL(fullUrl);
|
|
300
|
+
const hostname = urlObj.hostname.toLowerCase();
|
|
301
|
+
|
|
302
|
+
// 移除 www. 前缀
|
|
303
|
+
const domain = hostname.replace(/^www\./, '');
|
|
304
|
+
|
|
305
|
+
// 根据域名返回对应的平台标识符
|
|
306
|
+
for (const [platform, { domains, options }] of Object.entries(DOMAIN_PLATFORM_MAP)) {
|
|
307
|
+
if (domains.some((d) => domain === d || domain.endsWith(`.${d}`))) {
|
|
308
|
+
return {
|
|
309
|
+
icon: `logos:${platform}`,
|
|
310
|
+
options,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// 对于未匹配的域名,返回空字符串
|
|
316
|
+
return undefined;
|
|
317
|
+
} catch {
|
|
318
|
+
return undefined;
|
|
319
|
+
}
|
|
320
|
+
};
|