@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.
@@ -1,6 +1,6 @@
1
- import { jsx as t, jsxs as f } from "react/jsx-runtime";
2
- import { useState as C, useMemo as k } from "react";
3
- import { styled as I, Box as p, Typography as y, IconButton as D, Button as U, useTheme as S, FormControl as F, TextField as B } from "@mui/material";
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 { isValidUrl as h, isDuplicateUrl as P } from "./utils.js";
12
- import { translations as W } from "../../libs/locales.js";
13
- import { inputFieldStyle as N, commonInputStyle as V } from "../editable-field.js";
14
- const x = 10;
15
- function K(e) {
16
- return A(e);
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 O({
19
- value: e,
20
- onChange: a,
21
- errorMsg: s
19
+ function $({
20
+ value: t,
21
+ onChange: s,
22
+ errorMsg: l
22
23
  }) {
23
- return /* @__PURE__ */ t(F, { fullWidth: !0, children: /* @__PURE__ */ t(
24
- B,
24
+ return /* @__PURE__ */ e(B, { fullWidth: !0, children: /* @__PURE__ */ e(
25
+ F,
25
26
  {
26
27
  variant: "outlined",
27
- value: e,
28
+ value: t,
28
29
  onChange: (i) => {
29
30
  const u = i.target.value;
30
- a(u);
31
+ s(u);
31
32
  },
32
33
  fullWidth: !0,
33
- error: !!s,
34
- helperText: s,
35
- sx: j(N, s ? {} : V)
34
+ error: !!l,
35
+ helperText: l,
36
+ sx: j(K, l ? {} : O)
36
37
  }
37
38
  ) });
38
39
  }
39
- function X({ links: e = [], onChange: a }) {
40
- const { locale: s } = M(), n = E((r, o = {}) => z(W, r, s, "en", o)), [i, u] = C([""]), g = k(() => {
41
- const r = e[e.length - 1];
42
- return !h(r) || i.length > 0 && i[i.length - 1];
43
- }, [i, e]), L = () => {
44
- (e.length < x || !g) && a([...e, ""]);
45
- }, v = (r) => {
46
- const o = e.filter((c, d) => d !== r), l = i.filter((c, d) => d !== r);
47
- u(l), a(o);
48
- }, b = (r, o) => {
49
- const l = [...e];
50
- l[r] = o;
51
- const c = [...i], d = !!(o && !h(o));
52
- c[r] = !1, d ? c[r] = d : l.filter((m, w) => m && h(m) && w !== r).some((m) => P(m, o)) && (c[r] = "duplicate"), u(c), a(l);
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__ */ t(
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__ */ t(y, { variant: "subtitle1", gutterBottom: !0, sx: { mb: 0, fontSize: "12px", color: "text.primary" }, children: n("profile.socialMedia") })
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
- e.map((r, o) => {
74
- let l = "";
75
- return i[o] === "duplicate" ? l = n("profile.duplicateURL") : i[o] === !0 ? l = n("profile.invalidURL") : l = "", /* @__PURE__ */ f(
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__ */ t(O, { value: r, onChange: (c) => b(o, c), errorMsg: l }),
85
- /* @__PURE__ */ t(D, { onClick: () => v(o), children: /* @__PURE__ */ t(T, { sx: { color: "text.secondary" } }) })
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
- o
89
+ n
89
90
  );
90
91
  }),
91
- e.length < x ? /* @__PURE__ */ f(
92
+ t.length < g ? /* @__PURE__ */ f(
92
93
  U,
93
94
  {
94
95
  fullWidth: !0,
95
96
  variant: "outlined",
96
- disabled: !!g,
97
- onClick: L,
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__ */ t(_, {}),
114
+ /* @__PURE__ */ e(_, {}),
114
115
  " ",
115
- /* @__PURE__ */ t("span", { children: n("profile.addLink") })
116
+ /* @__PURE__ */ e("span", { children: r("profile.addLink") })
116
117
  ]
117
118
  }
118
- ) : /* @__PURE__ */ t(y, { variant: "subtitle1", gutterBottom: !0, sx: { mb: 0, fontSize: "12px", color: "text.secondary" }, children: n("profile.maxLinkCount", { count: x }) })
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 $({ link: e }) {
124
- const s = S().palette.mode === "dark";
125
- return e ? /* @__PURE__ */ t(R, { width: 20, height: 20, style: { filter: s ? "brightness(0) saturate(100%) invert(1)" : "none" } }) : null;
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 ce({
128
- editable: e = !1,
129
- links: a = [],
130
- onChange: s
143
+ function ut({
144
+ editable: t = !1,
145
+ links: s = [],
146
+ onChange: l
131
147
  }) {
132
- return e ? /* @__PURE__ */ t(X, { links: a, onChange: s }) : /* @__PURE__ */ t(
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: a.map((n) => /* @__PURE__ */ f(
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__ */ t($, { link: n }),
153
- /* @__PURE__ */ t(q, { children: /* @__PURE__ */ t(p, { component: "a", href: n, style: { textDecoration: "none" }, target: "_blank", rel: "noopener noreferrer", children: K(n) }) })
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
- n
172
+ r
157
173
  ))
158
174
  }
159
175
  );
160
176
  }
161
- const q = I("span")`
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: e }) => e.palette.text.primary};
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
- ce as LinkPreviewInput
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 ie, createElement as ae, useState as T, useRef as le, useEffect as de, useMemo as F } from "react";
3
- import { Icon as ce } from "@iconify/react";
4
- import { Backdrop as se, Box as m, useMediaQuery as pe, SwipeableDrawer as me, Typography as N, Tooltip as ue } from "@mui/material";
5
- import he from "@emotion/styled";
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 M, { detectCountryFromPhone as $, getCountryNameByCountry as fe, validatePhoneNumber as ye, getDialCodeByCountry as xe } from "@arcblock/ux/lib/PhoneInput";
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 be from "lodash/omit";
10
- import { mergeSx as ge } from "@arcblock/ux/lib/Util/style";
11
- import { LOGIN_PROVIDER as G } from "@arcblock/ux/lib/Util/constant";
12
- import { useReactive as w, useCreation as k, useMemoizedFn as Ce } from "ahooks";
13
- import { translate as ve } from "@arcblock/ux/lib/Locale/util";
14
- import we from "validator/lib/isEmail";
15
- import H from "validator/lib/isPostalCode";
16
- import { useLocaleContext as ke } from "@arcblock/ux/lib/Locale/context";
17
- import { useBrowser as Ee } from "@arcblock/react-hooks";
18
- import Ie from "@arcblock/ux/lib/UserCard/Content/clock";
19
- import { translations as ze } from "../../libs/locales.js";
20
- import g, { inputFieldStyle as Pe, commonInputStyle as Ve } from "../editable-field.js";
21
- import { LinkPreviewInput as Be } from "./link-preview-input.js";
22
- import { defaultButtonStyle as Q, currentTimezone as A, primaryButtonStyle as Le } from "./utils.js";
23
- import { TimezoneSelect as Ne } from "./timezone-select.js";
24
- import je from "./address.js";
25
- const Ae = I(() => import("@arcblock/icons/lib/Location")), Se = I(() => import("@arcblock/icons/lib/Timezone")), Oe = I(() => import("@arcblock/icons/lib/Email")), We = I(() => import("@arcblock/icons/lib/Phone")), E = {
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
- }, U = 200, Y = ie(function({
28
+ }, Q = 200, U = re(function({
29
29
  ref: r,
30
30
  ...z
31
31
  }) {
32
- return /* @__PURE__ */ ae(
33
- se,
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
- Y.displayName = "BackdropWrap";
48
- function so({
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 [_, P] = T(!1), [q, C] = T(!1), J = le(null), K = Ee(), b = pe("(max-width:640px)") || K.mobile.any, c = w({
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
- de(() => {
65
+ le(() => {
66
66
  b || C(!1);
67
67
  }, [b]);
68
- const S = k(() => r?.phoneVerified ?? !1, [r?.phoneVerified]), O = k(() => r?.emailVerified ?? !1, [r?.emailVerified]), { locale: V } = ke(), d = Ce((o, n = {}) => ve(ze, o, V, "en", n)), a = w(
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
- ), X = k(() => !!r?.address, [r?.address?.country]), h = F(() => r?.address?.country ? r.address.country : V === "zh" ? "cn" : "us", [r?.address?.country, V]), B = k(() => {
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: $(o) || h,
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 || $(e) || "",
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
- }, Z = (o, n) => {
110
- l[o] = n, o === "city" && p(n, "location"), o === "postalCode" ? u.postalCode = n && !H(n, "any") ? d("profile.address.invalidPostalCode") : "" : u[o] = "";
111
- }, W = () => {
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
- }, R = () => {
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
- }, ee = F(() => {
128
+ }, Z = F(() => {
129
129
  const o = a?.links?.map((n) => n.url) || [""];
130
130
  return o.length > 0 ? o : [""];
131
- }, [a.links]), oe = (o) => {
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
- }, ne = () => {
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, U)), e === "timezone" && (a[e] = i || A), e === "phone" && i && typeof i == "object") {
151
- const f = i, te = xe(f.country), re = (f.phoneNumber?.replace(new RegExp(`^\\+${te}`), "") || "")?.trim().length > 0;
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
- ...re ? { phoneNumber: f.phoneNumber } : {}
154
+ ...te ? { phoneNumber: f.phoneNumber } : {}
155
155
  };
156
156
  }
157
- }), l.postalCode && !H(l.postalCode, "any") && (u.postalCode = d("profile.address.invalidPostalCode")), [c, u].some((n) => Object.values(n).some((e) => e)))
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 = be(l, "detailedAddress");
159
+ const o = xe(l, "detailedAddress");
160
160
  o.country || (o.country = h), z({ metadata: a, address: o }), P(!1), C(!1);
161
- }, D = (o, n = "self") => /* @__PURE__ */ y(
162
- Re,
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: U,
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
- ...Q,
194
+ ...H,
195
195
  mb: x ? "4px" : 2,
196
196
  mt: x ? "4px" : 2,
197
197
  height: x ? "32px" : "40px"
198
198
  },
199
- onClick: W,
199
+ onClick: O,
200
200
  fullWidth: !0,
201
201
  children: d("profile.editProfile")
202
202
  }
203
203
  ) : null,
204
- o && s && X ? /* @__PURE__ */ t(
205
- je,
204
+ o && s && K ? /* @__PURE__ */ t(
205
+ Ne,
206
206
  {
207
207
  address: l,
208
208
  errors: u,
209
- handleChange: Z,
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 ? fe(l?.country) : "", l.province, l.city || a.location || ""].filter(Boolean).join(" ");
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(Ae, { ...E })
239
+ icon: /* @__PURE__ */ t(je, { ...E })
240
240
  }
241
241
  ),
242
242
  /* @__PURE__ */ t(
243
243
  g,
244
244
  {
245
- value: a.timezone || A,
245
+ value: a.timezone || "",
246
246
  onChange: (e) => p(e, "timezone"),
247
247
  editable: o,
248
248
  placeholder: "timezone",
249
- icon: /* @__PURE__ */ t(Se, { ...E }),
249
+ icon: /* @__PURE__ */ t(Ae, { ...E }),
250
250
  label: d("profile.timezone"),
251
- renderValue: (e) => /* @__PURE__ */ t(Ie, { value: e }),
251
+ renderValue: (e) => /* @__PURE__ */ t(Ee, { value: e }),
252
252
  children: /* @__PURE__ */ t(
253
- Ne,
253
+ Le,
254
254
  {
255
- value: a.timezone || A,
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 === G.EMAIL,
270
- canEdit: !O,
271
- verified: O,
269
+ disabled: r?.sourceProvider === $.EMAIL,
270
+ canEdit: !S,
271
+ verified: S,
272
272
  placeholder: "Email",
273
- icon: /* @__PURE__ */ t(Oe, { ...E }),
273
+ icon: /* @__PURE__ */ t(Se, { ...E }),
274
274
  label: /* @__PURE__ */ y(L, { children: [
275
275
  d("profile.email"),
276
- r?.sourceProvider === G.EMAIL ? /* @__PURE__ */ t(ue, { title: d("profile.emailSourceProviderNotAllowEdit"), children: /* @__PURE__ */ t(
276
+ r?.sourceProvider === $.EMAIL ? /* @__PURE__ */ t(me, { title: d("profile.emailSourceProviderNotAllowEdit"), children: /* @__PURE__ */ t(
277
277
  m,
278
278
  {
279
- component: ce,
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 && !we(e) && (i = d("profile.emailInvalid")), c.email = i;
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: !S,
314
- verified: S,
313
+ canEdit: !A,
314
+ verified: A,
315
315
  placeholder: "Phone",
316
- icon: /* @__PURE__ */ t(We, { ...E }),
316
+ icon: /* @__PURE__ */ t(Oe, { ...E }),
317
317
  onChange: (e) => p(e, "phone"),
318
318
  label: d("profile.phone"),
319
- renderValue: () => s ? /* @__PURE__ */ t(M, { value: B, preview: !0 }) : null,
319
+ renderValue: () => s ? /* @__PURE__ */ t(T, { value: B, preview: !0 }) : null,
320
320
  children: /* @__PURE__ */ t(
321
- M,
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: ge(Pe, c.phone ? {} : Ve),
332
+ sx: be(ze, c.phone ? {} : Pe),
333
333
  onChange: (e) => {
334
- ye(e.phone, e.country) ? c.phone = "" : c.phone = d("profile.phoneInvalid"), p(
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(Be, { editable: o, links: ee, onChange: oe }),
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: { ...Q, minWidth: "54px" },
365
- onClick: R,
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
- ...Le,
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: ne,
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
- D(_),
394
+ R(Y),
395
395
  b && /* @__PURE__ */ y(
396
- me,
396
+ pe,
397
397
  {
398
398
  sx: {
399
399
  zIndex: 9999
400
400
  },
401
401
  disableSwipeToOpen: !0,
402
- onOpen: W,
403
- open: q,
402
+ onOpen: O,
403
+ open: _,
404
404
  anchor: "bottom",
405
- onClose: R,
405
+ onClose: W,
406
406
  slots: {
407
- backdrop: Y
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: J,
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: D(!0, "drawer")
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 Re = he(m)`
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
- so as default
498
+ co as default
499
499
  };
@@ -1,45 +1,49 @@
1
- import { jsxs as h, jsx as t } from "react/jsx-runtime";
2
- import { useState as a, useMemo as v, useEffect as d } from "react";
3
- import { Select as x, ListSubheader as b, TextField as C, MenuItem as z } from "@mui/material";
4
- import g from "lodash/debounce";
5
- import { KeyboardArrowDown as T } from "@mui/icons-material";
6
- import { getTimezones as w } from "./utils.js";
7
- const r = w();
8
- function P({ value: s, onChange: u, disabled: l = !1, mode: c = "self" }) {
9
- const [m, p] = a(r), [i, f] = a(""), o = v(
10
- () => g((e) => e ? r.filter((n) => n.value.toLowerCase().includes(e.toLowerCase())) : r, 300),
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 d(() => {
14
- const e = o(i);
15
- p(e ?? r);
16
- }, [i, o]), d(() => () => {
17
- o.cancel();
18
- }, [o]), /* @__PURE__ */ h(
19
- x,
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 ${l ? "disabled" : ""}`,
22
- value: s,
23
- onChange: (e) => u(e.target.value),
24
- disabled: l,
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: "Timezone",
30
+ placeholder: n("profile.timezone"),
28
31
  IconComponent: (e) => /* @__PURE__ */ t(
29
- T,
32
+ S,
30
33
  {
31
34
  ...e,
32
- sx: { fontSize: 18, color: (n) => `${n.palette.text.secondary} !important` }
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: c === "drawer" ? 9999 : 1300
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(b, { children: /* @__PURE__ */ t(
58
- C,
61
+ /* @__PURE__ */ t(T, { children: /* @__PURE__ */ t(
62
+ w,
59
63
  {
64
+ inputRef: u,
60
65
  autoFocus: !0,
61
- value: i,
62
- placeholder: "Timezone",
66
+ value: s,
67
+ placeholder: n("profile.timezone"),
63
68
  variant: "outlined",
64
69
  size: "small",
65
70
  fullWidth: !0,
66
- onChange: (e) => f(e.target.value),
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
- m.map((e) => /* @__PURE__ */ t(z, { value: e.value, children: e.label }, e.value))
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
- P as TimezoneSelect
98
+ V as TimezoneSelect
93
99
  };
@@ -50,3 +50,7 @@ export declare const primaryButtonStyle: {
50
50
  py: number;
51
51
  borderRadius: number;
52
52
  };
53
+ export declare const getLogoByUrl: (url: string) => {
54
+ icon: string;
55
+ options?: Record<string, any>;
56
+ } | undefined;
@@ -1,12 +1,12 @@
1
- import h from "is-url";
2
- import { withHttps as c } from "ufo";
3
- import n from "dayjs";
4
- import C from "dayjs/plugin/timezone";
5
- import k from "dayjs/plugin/utc";
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
- n.extend(k);
8
- n.extend(C);
9
- const l = 3600, m = 1800, d = 600, f = 300, p = 60, b = 1, _ = n.tz.guess(), y = [
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
- ], O = () => {
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
- }, v = () => O().map((e) => {
46
+ }, _ = () => C().map((o) => {
47
47
  try {
48
- const t = n.tz(n(), e).utcOffset() / 60, a = Math.floor(t), i = t % 1 * 60;
49
- return { label: `GMT${a >= 0 ? "+" : ""}${a}:${i === 30 ? "30" : "00"}`, value: e };
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 ${e} not supported, skipping`), null;
51
+ return console.warn(`Timezone ${o} not supported, skipping`), null;
52
52
  }
53
- }).filter((e) => e !== null).sort((e, t) => {
54
- const [a, i] = e.label.replace("GMT", "").split(":").map(Number), [u, g] = t.label.replace("GMT", "").split(":").map(Number), A = a * 60 + i;
55
- return u * 60 + g - A;
56
- }).map((e) => ({
57
- label: `(${e.label}) ${e.value}`,
58
- value: e.value
59
- })), T = (o) => h(c(o)), z = (o, r) => {
60
- if (!o || !r || !T(o) || !T(r))
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 e = c(o.trim()), t = c(r.trim());
63
- return e.toLowerCase() === t.toLowerCase();
64
- }, D = (o) => {
65
- let r = o?.dateRange?.map((t) => n(t)) ?? [];
66
- const e = n();
67
- switch (o?.duration) {
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
- r = [e, e.add(30, "minutes")];
69
+ e = [o, o.add(30, "minutes")];
70
70
  break;
71
71
  case s.OneHour:
72
- r = [e, e.add(1, "hour")];
72
+ e = [o, o.add(1, "hour")];
73
73
  break;
74
74
  case s.FourHours:
75
- r = [e, e.add(4, "hours")];
75
+ e = [o, o.add(4, "hours")];
76
76
  break;
77
77
  case s.Today:
78
- r = [e, e.endOf("day")];
78
+ e = [o, o.endOf("day")];
79
79
  break;
80
80
  case s.ThisWeek:
81
- r = [e, e.endOf("week")];
81
+ e = [o, o.endOf("week")];
82
82
  break;
83
83
  case s.NoClear:
84
- r = [e, e];
84
+ e = [o, o];
85
85
  break;
86
86
  }
87
- return r.map((t) => t.toDate());
88
- }, B = (o) => {
89
- const r = n();
90
- return r.isAfter(n(o[0])) && r.isBefore(n(o[1]));
91
- }, R = (o) => {
92
- const { duration: r, dateRange: e } = o ?? {};
93
- return !r || !e ? !1 : r === s.NoClear || n(e?.[0]).isSame(n(e?.[1]));
94
- }, x = (o) => {
95
- const r = n(), t = n(o).diff(r, "seconds"), a = (i) => i * 1e3;
96
- return t >= l ? a(l) : t >= m ? a(m) : t >= d ? a(d) : t >= f ? a(f) : t >= p ? a(p) : t >= b ? a(b) : 0;
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
- }, H = {
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
- _ as currentTimezone,
183
+ E as currentTimezone,
120
184
  $ as defaultButtonStyle,
121
- D as getStatusDuration,
185
+ H as getLogoByUrl,
186
+ z as getStatusDuration,
122
187
  x as getTimeRemaining,
123
- v as getTimezones,
124
- z as isDuplicateUrl,
125
- R as isNotClear,
126
- T as isValidUrl,
188
+ _ as getTimezones,
189
+ R as isDuplicateUrl,
190
+ L as isNotClear,
191
+ h as isValidUrl,
127
192
  B as isWithinTimeRange,
128
- H as primaryButtonStyle
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.8",
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.8",
39
- "@arcblock/icons": "3.2.8",
40
- "@arcblock/react-hooks": "3.2.8",
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.8",
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": "c3986ded30e94992b83a628e4ffc73c99e630b5d"
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 { isDuplicateUrl, isValidUrl } from './utils';
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 { currentTimezone, defaultButtonStyle, primaryButtonStyle } from './utils';
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) || currentTimezone;
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 || currentTimezone}
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 || currentTimezone}
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, useMemo } from 'react';
1
+ import { useState, useEffect, useRef } from 'react';
2
2
  import { MenuItem, Select, SelectChangeEvent, ListSubheader, TextField } from '@mui/material';
3
- import debounce from 'lodash/debounce';
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 timezoneDebounce = useMemo(
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 = timezoneDebounce(searchText);
35
+ const data = searchTimezones(debouncedValue);
30
36
  setTimezoneData(data ?? timezones);
31
- }, [searchText, timezoneDebounce]);
32
-
33
- useEffect(() => {
34
- return () => {
35
- timezoneDebounce.cancel();
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="Timezone"
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="Timezone"
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
+ };