@blocklet/ui-react 2.12.8 → 2.12.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/@types/index.d.ts +34 -0
- package/lib/@types/index.js +16 -0
- package/lib/@types/shims.d.ts +1 -0
- package/lib/UserCenter/components/config-profile.js +23 -1
- package/lib/UserCenter/components/editable-field.d.ts +22 -0
- package/lib/UserCenter/components/editable-field.js +159 -0
- package/lib/UserCenter/components/nft.d.ts +4 -0
- package/lib/UserCenter/components/nft.js +93 -0
- package/lib/UserCenter/components/settings.js +32 -15
- package/lib/UserCenter/components/status-selector/duration-menu.d.ts +9 -0
- package/lib/UserCenter/components/status-selector/duration-menu.js +75 -0
- package/lib/UserCenter/components/status-selector/index.d.ts +9 -0
- package/lib/UserCenter/components/status-selector/index.js +39 -0
- package/lib/UserCenter/components/status-selector/menu-item.d.ts +24 -0
- package/lib/UserCenter/components/status-selector/menu-item.js +24 -0
- package/lib/UserCenter/components/user-center.js +119 -122
- package/lib/UserCenter/components/user-info/clock.d.ts +4 -0
- package/lib/UserCenter/components/user-info/clock.js +23 -0
- package/lib/UserCenter/components/user-info/link-preview-input.d.ts +5 -0
- package/lib/UserCenter/components/user-info/link-preview-input.js +181 -0
- package/lib/UserCenter/components/user-info/metadata.d.ts +7 -0
- package/lib/UserCenter/components/user-info/metadata.js +458 -0
- package/lib/UserCenter/components/user-info/switch-role.js +2 -3
- package/lib/UserCenter/components/user-info/user-basic-info.d.ts +2 -0
- package/lib/UserCenter/components/user-info/user-basic-info.js +159 -90
- package/lib/UserCenter/components/user-info/user-info.js +2 -16
- package/lib/UserCenter/components/user-info/user-status.d.ts +8 -0
- package/lib/UserCenter/components/user-info/user-status.js +153 -0
- package/lib/UserCenter/components/user-info/utils.d.ts +19 -0
- package/lib/UserCenter/components/user-info/utils.js +86 -0
- package/lib/UserCenter/libs/locales.d.ts +65 -0
- package/lib/UserCenter/libs/locales.js +67 -2
- package/lib/UserSessions/components/user-sessions.js +48 -14
- package/package.json +8 -5
- package/src/@types/index.ts +39 -0
- package/src/@types/shims.d.ts +1 -0
- package/src/UserCenter/components/config-profile.tsx +20 -1
- package/src/UserCenter/components/editable-field.tsx +180 -0
- package/src/UserCenter/components/nft.tsx +122 -0
- package/src/UserCenter/components/settings.tsx +16 -4
- package/src/UserCenter/components/status-selector/duration-menu.tsx +87 -0
- package/src/UserCenter/components/status-selector/index.tsx +52 -0
- package/src/UserCenter/components/status-selector/menu-item.tsx +52 -0
- package/src/UserCenter/components/user-center.tsx +104 -103
- package/src/UserCenter/components/user-info/clock.tsx +29 -0
- package/src/UserCenter/components/user-info/link-preview-input.tsx +227 -0
- package/src/UserCenter/components/user-info/metadata.tsx +465 -0
- package/src/UserCenter/components/user-info/switch-role.tsx +3 -3
- package/src/UserCenter/components/user-info/user-basic-info.tsx +150 -87
- package/src/UserCenter/components/user-info/user-info.tsx +6 -16
- package/src/UserCenter/components/user-info/user-status.tsx +182 -0
- package/src/UserCenter/components/user-info/utils.ts +114 -0
- package/src/UserCenter/libs/locales.ts +65 -0
- package/src/UserSessions/components/user-sessions.tsx +68 -18
package/lib/@types/index.d.ts
CHANGED
|
@@ -38,6 +38,39 @@ export type NFTAccount = {
|
|
|
38
38
|
firstLoginAt: string;
|
|
39
39
|
};
|
|
40
40
|
export type ConnectedAccount = OAuthAccount | WalletAccount | NFTAccount;
|
|
41
|
+
export type UserMetadataLink = {
|
|
42
|
+
url: string;
|
|
43
|
+
favicon?: string;
|
|
44
|
+
};
|
|
45
|
+
export declare enum DurationEnum {
|
|
46
|
+
ThirtyMinutes = "30_minutes",
|
|
47
|
+
OneHour = "1_hour",
|
|
48
|
+
FourHours = "4_hours",
|
|
49
|
+
Today = "today",
|
|
50
|
+
ThisWeek = "this_week"
|
|
51
|
+
}
|
|
52
|
+
export declare enum StatusEnum {
|
|
53
|
+
Meeting = "meeting",
|
|
54
|
+
Community = "community",
|
|
55
|
+
Holiday = "holiday",
|
|
56
|
+
OffSick = "off_sick",
|
|
57
|
+
WorkingRemotely = "working_remotely"
|
|
58
|
+
}
|
|
59
|
+
export type UserMetadata = {
|
|
60
|
+
bio?: string;
|
|
61
|
+
location?: string;
|
|
62
|
+
timezone?: string;
|
|
63
|
+
joinedAt?: string;
|
|
64
|
+
status?: {
|
|
65
|
+
value: string;
|
|
66
|
+
duration?: DurationEnum;
|
|
67
|
+
dateRange?: Date[];
|
|
68
|
+
};
|
|
69
|
+
links?: UserMetadataLink[];
|
|
70
|
+
cover?: string;
|
|
71
|
+
email?: string;
|
|
72
|
+
phone?: string;
|
|
73
|
+
};
|
|
41
74
|
export type User = UserPublicInfo & {
|
|
42
75
|
role: string;
|
|
43
76
|
email?: string;
|
|
@@ -55,6 +88,7 @@ export type User = UserPublicInfo & {
|
|
|
55
88
|
inviter?: string;
|
|
56
89
|
emailVerified?: boolean;
|
|
57
90
|
phoneVerified?: boolean;
|
|
91
|
+
metadata?: UserMetadata;
|
|
58
92
|
};
|
|
59
93
|
export type UserCenterTab = {
|
|
60
94
|
value: string;
|
package/lib/@types/index.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export var DurationEnum = /* @__PURE__ */ ((DurationEnum2) => {
|
|
2
|
+
DurationEnum2["ThirtyMinutes"] = "30_minutes";
|
|
3
|
+
DurationEnum2["OneHour"] = "1_hour";
|
|
4
|
+
DurationEnum2["FourHours"] = "4_hours";
|
|
5
|
+
DurationEnum2["Today"] = "today";
|
|
6
|
+
DurationEnum2["ThisWeek"] = "this_week";
|
|
7
|
+
return DurationEnum2;
|
|
8
|
+
})(DurationEnum || {});
|
|
9
|
+
export var StatusEnum = /* @__PURE__ */ ((StatusEnum2) => {
|
|
10
|
+
StatusEnum2["Meeting"] = "meeting";
|
|
11
|
+
StatusEnum2["Community"] = "community";
|
|
12
|
+
StatusEnum2["Holiday"] = "holiday";
|
|
13
|
+
StatusEnum2["OffSick"] = "off_sick";
|
|
14
|
+
StatusEnum2["WorkingRemotely"] = "working_remotely";
|
|
15
|
+
return StatusEnum2;
|
|
16
|
+
})(StatusEnum || {});
|
package/lib/@types/shims.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { useMemoizedFn, useReactive } from "ahooks";
|
|
|
4
4
|
import { translate } from "@arcblock/ux/lib/Locale/util";
|
|
5
5
|
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
6
6
|
import Toast from "@arcblock/ux/lib/Toast";
|
|
7
|
+
import { temp as colors } from "@arcblock/ux/lib/Colors";
|
|
8
|
+
import ArrowDownwardIcon from "@arcblock/icons/lib/ArrowDown";
|
|
7
9
|
import { translations } from "../libs/locales.js";
|
|
8
10
|
import { client } from "../../libs/client.js";
|
|
9
11
|
import { formatAxiosError } from "../libs/utils.js";
|
|
@@ -61,7 +63,27 @@ export default function ConfigProfile({ user, onSave }) {
|
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
),
|
|
64
|
-
/* @__PURE__ */ jsx(
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
Select,
|
|
68
|
+
{
|
|
69
|
+
value: currentState.locale,
|
|
70
|
+
onChange: handleChange,
|
|
71
|
+
size: "small",
|
|
72
|
+
IconComponent: (props) => /* @__PURE__ */ jsx(ArrowDownwardIcon, { ...props, width: 20, height: 20 }),
|
|
73
|
+
sx: {
|
|
74
|
+
minWidth: 300,
|
|
75
|
+
"&:hover": {
|
|
76
|
+
"fieldset.MuiOutlinedInput-notchedOutline": {
|
|
77
|
+
borderColor: colors.dividerColor
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
fieldset: {
|
|
81
|
+
borderColor: colors.dividerColor
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
children: (window.blocklet.languages || languages).map((x) => /* @__PURE__ */ jsx(MenuItem, { value: x.code, children: x.name }, x.code))
|
|
85
|
+
}
|
|
86
|
+
)
|
|
65
87
|
] })
|
|
66
88
|
]
|
|
67
89
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TooltipProps } from '@mui/material';
|
|
3
|
+
interface EditableFieldProps {
|
|
4
|
+
value: string;
|
|
5
|
+
onChange?: (value: string) => void;
|
|
6
|
+
onValueValidate?: (value: string) => void;
|
|
7
|
+
editable: boolean;
|
|
8
|
+
component?: 'input' | 'textarea';
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
rows?: number;
|
|
11
|
+
maxLength?: number;
|
|
12
|
+
icon?: React.ReactNode;
|
|
13
|
+
label?: string;
|
|
14
|
+
children?: React.ReactNode;
|
|
15
|
+
tooltip?: TooltipProps['title'];
|
|
16
|
+
inline?: boolean;
|
|
17
|
+
style?: React.CSSProperties;
|
|
18
|
+
verified?: boolean;
|
|
19
|
+
errorMsg?: string;
|
|
20
|
+
}
|
|
21
|
+
declare function EditableField({ value, onChange, onValueValidate, errorMsg, editable, component, placeholder, rows, maxLength, icon, label, children, tooltip, inline, style, verified, }: EditableFieldProps): JSX.Element | null;
|
|
22
|
+
export default EditableField;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, TextField, Typography, Tooltip } from "@mui/material";
|
|
3
|
+
import { useCreation, useMemoizedFn } from "ahooks";
|
|
4
|
+
import { temp as colors } from "@arcblock/ux/lib/Colors";
|
|
5
|
+
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
6
|
+
import { translate } from "@arcblock/ux/lib/Locale/util";
|
|
7
|
+
import VerifiedIcon from "@mui/icons-material/Verified";
|
|
8
|
+
import { translations } from "../libs/locales.js";
|
|
9
|
+
const inputFieldStyle = {
|
|
10
|
+
width: "100%",
|
|
11
|
+
".MuiOutlinedInput-root": {
|
|
12
|
+
"&:hover": {
|
|
13
|
+
fieldset: {
|
|
14
|
+
borderColor: colors.dividerColor
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"&.Mui-focused": {
|
|
18
|
+
fieldset: {
|
|
19
|
+
borderColor: colors.dividerColor
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
fieldset: {
|
|
24
|
+
borderColor: colors.dividerColor
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function EditableField({
|
|
28
|
+
value,
|
|
29
|
+
onChange = () => {
|
|
30
|
+
},
|
|
31
|
+
onValueValidate = () => {
|
|
32
|
+
},
|
|
33
|
+
errorMsg = "",
|
|
34
|
+
editable = false,
|
|
35
|
+
component = "input",
|
|
36
|
+
placeholder = "",
|
|
37
|
+
rows = 2,
|
|
38
|
+
maxLength,
|
|
39
|
+
icon,
|
|
40
|
+
label = "",
|
|
41
|
+
children,
|
|
42
|
+
tooltip,
|
|
43
|
+
inline = true,
|
|
44
|
+
style = {},
|
|
45
|
+
verified = false
|
|
46
|
+
}) {
|
|
47
|
+
const { locale } = useLocaleContext();
|
|
48
|
+
const t = useMemoizedFn((key, data = {}) => {
|
|
49
|
+
return translate(translations, key, locale, "en", data);
|
|
50
|
+
});
|
|
51
|
+
const handleChange = useMemoizedFn((v) => {
|
|
52
|
+
if (onChange) {
|
|
53
|
+
onChange(v);
|
|
54
|
+
}
|
|
55
|
+
if (onValueValidate) {
|
|
56
|
+
onValueValidate(v);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
const content = useCreation(() => {
|
|
60
|
+
if (children) {
|
|
61
|
+
return children;
|
|
62
|
+
}
|
|
63
|
+
if (component === "input") {
|
|
64
|
+
return /* @__PURE__ */ jsx(
|
|
65
|
+
TextField,
|
|
66
|
+
{
|
|
67
|
+
variant: "outlined",
|
|
68
|
+
className: "editable-field",
|
|
69
|
+
InputProps: {
|
|
70
|
+
sx: { backgroundColor: "transparent" },
|
|
71
|
+
placeholder
|
|
72
|
+
},
|
|
73
|
+
value,
|
|
74
|
+
onChange: (e) => handleChange(e.target.value),
|
|
75
|
+
sx: inputFieldStyle,
|
|
76
|
+
error: Boolean(errorMsg),
|
|
77
|
+
helperText: errorMsg
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const isTooLong = value.length > (maxLength || 300);
|
|
82
|
+
return /* @__PURE__ */ jsxs(Box, { position: "relative", children: [
|
|
83
|
+
/* @__PURE__ */ jsx(
|
|
84
|
+
TextField,
|
|
85
|
+
{
|
|
86
|
+
variant: "outlined",
|
|
87
|
+
InputProps: {
|
|
88
|
+
multiline: true,
|
|
89
|
+
minRows: rows,
|
|
90
|
+
placeholder
|
|
91
|
+
},
|
|
92
|
+
sx: inputFieldStyle,
|
|
93
|
+
value,
|
|
94
|
+
onChange: (e) => handleChange(e.target.value),
|
|
95
|
+
error: Boolean(errorMsg),
|
|
96
|
+
helperText: errorMsg
|
|
97
|
+
}
|
|
98
|
+
),
|
|
99
|
+
/* @__PURE__ */ jsxs(
|
|
100
|
+
Typography,
|
|
101
|
+
{
|
|
102
|
+
position: "absolute",
|
|
103
|
+
bottom: -22,
|
|
104
|
+
right: 2,
|
|
105
|
+
variant: "caption",
|
|
106
|
+
fontSize: "12px",
|
|
107
|
+
component: "span",
|
|
108
|
+
color: isTooLong ? "error" : "text.secondary",
|
|
109
|
+
children: [
|
|
110
|
+
isTooLong ? `(${t("profile.maxInputLength")} ${maxLength}) ` : "",
|
|
111
|
+
value.length,
|
|
112
|
+
" / ",
|
|
113
|
+
maxLength
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
] });
|
|
118
|
+
}, [value, handleChange, component, placeholder, rows, children]);
|
|
119
|
+
if (!editable) {
|
|
120
|
+
return value ? /* @__PURE__ */ jsx(Tooltip, { title: tooltip, placement: "top", children: /* @__PURE__ */ jsxs(
|
|
121
|
+
Typography,
|
|
122
|
+
{
|
|
123
|
+
variant: "subtitle1",
|
|
124
|
+
component: "p",
|
|
125
|
+
gutterBottom: true,
|
|
126
|
+
sx: {
|
|
127
|
+
width: "100%",
|
|
128
|
+
mb: 0,
|
|
129
|
+
lineHeight: 1.4,
|
|
130
|
+
overflow: "hidden"
|
|
131
|
+
},
|
|
132
|
+
display: "flex",
|
|
133
|
+
alignItems: "center",
|
|
134
|
+
gap: 1,
|
|
135
|
+
children: [
|
|
136
|
+
icon,
|
|
137
|
+
/* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "row", alignItems: "center", width: "90%", children: [
|
|
138
|
+
/* @__PURE__ */ jsx(
|
|
139
|
+
Typography,
|
|
140
|
+
{
|
|
141
|
+
sx: {
|
|
142
|
+
whiteSpace: "pre-wrap",
|
|
143
|
+
...inline ? { whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" } : {}
|
|
144
|
+
},
|
|
145
|
+
children: value
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
verified && /* @__PURE__ */ jsx(VerifiedIcon, { color: "success", style: { fontSize: 16, width: 16, marginLeft: 4, flexShrink: 0 } })
|
|
149
|
+
] })
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
) }) : null;
|
|
153
|
+
}
|
|
154
|
+
return /* @__PURE__ */ jsxs(Box, { sx: { width: "100%" }, style, children: [
|
|
155
|
+
label && /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", gutterBottom: true, sx: { mb: 0.5, fontSize: "12px", color: "#4B5563" }, children: label }),
|
|
156
|
+
content
|
|
157
|
+
] });
|
|
158
|
+
}
|
|
159
|
+
export default EditableField;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Pagination, Skeleton, Typography } from "@mui/material";
|
|
3
|
+
import { useCreation, useMemoizedFn, useReactive, useRequest } from "ahooks";
|
|
4
|
+
import axios from "axios";
|
|
5
|
+
import { temp as colors } from "@arcblock/ux/lib/Colors";
|
|
6
|
+
import NFTDisplay from "@arcblock/ux/lib/NFTDisplay";
|
|
7
|
+
import Empty from "@arcblock/ux/lib/Empty";
|
|
8
|
+
import { WELLKNOWN_SERVICE_PATH_PREFIX } from "@abtnode/constant";
|
|
9
|
+
import { translate } from "@arcblock/ux/lib/Locale/util";
|
|
10
|
+
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
11
|
+
import { translations } from "../libs/locales.js";
|
|
12
|
+
export default function Nft({ user }) {
|
|
13
|
+
const { locale } = useLocaleContext();
|
|
14
|
+
const t = useMemoizedFn((key, data2 = {}) => {
|
|
15
|
+
return translate(translations, key, locale, "en", data2);
|
|
16
|
+
});
|
|
17
|
+
const paging = useReactive({
|
|
18
|
+
page: 1,
|
|
19
|
+
size: 20
|
|
20
|
+
});
|
|
21
|
+
const userState = useRequest(
|
|
22
|
+
async (pagination = paging) => {
|
|
23
|
+
const response = await axios.get(`${WELLKNOWN_SERVICE_PATH_PREFIX}/ocap/listAssets`, {
|
|
24
|
+
params: {
|
|
25
|
+
ownerAddress: user.did,
|
|
26
|
+
...pagination
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return response.data;
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
defaultParams: [paging],
|
|
33
|
+
refreshDeps: [user.did, paging]
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
const { loading, data } = userState;
|
|
37
|
+
const dataPage = data?.page ?? { cursor: 0, next: false, total: 0 };
|
|
38
|
+
const handlePageChange = (event, value) => {
|
|
39
|
+
paging.page = value;
|
|
40
|
+
userState.run(paging);
|
|
41
|
+
};
|
|
42
|
+
const content = useCreation(() => {
|
|
43
|
+
if (loading) {
|
|
44
|
+
return /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "column", gap: 2, children: [
|
|
45
|
+
/* @__PURE__ */ jsx(Skeleton, { width: "20%" }),
|
|
46
|
+
/* @__PURE__ */ jsx(Skeleton, { variant: "rectangular", height: 200, sx: { borderRadius: 2 } })
|
|
47
|
+
] });
|
|
48
|
+
}
|
|
49
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
Typography,
|
|
52
|
+
{
|
|
53
|
+
sx: {
|
|
54
|
+
color: colors.foregroundsFgBase,
|
|
55
|
+
fontWeight: 600,
|
|
56
|
+
mb: 2.5
|
|
57
|
+
},
|
|
58
|
+
children: t("common.nft")
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
/* @__PURE__ */ jsxs(Box, { className: "nft-list-wrapper", display: "flex", flexDirection: "row", gap: 2, children: [
|
|
62
|
+
data?.assets?.map((item) => /* @__PURE__ */ jsx(Box, { width: 166, height: 166, children: /* @__PURE__ */ jsx(
|
|
63
|
+
NFTDisplay,
|
|
64
|
+
{
|
|
65
|
+
data: item.display,
|
|
66
|
+
address: item.address,
|
|
67
|
+
inset: true,
|
|
68
|
+
imageFilter: {
|
|
69
|
+
imageFilter: "resize",
|
|
70
|
+
w: "500",
|
|
71
|
+
f: "webp"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
) }, item.address)),
|
|
75
|
+
data?.assets?.length === 0 && !loading && /* @__PURE__ */ jsx(Box, { display: "flex", justifyContent: "center", alignItems: "center", width: "100%", height: "100%", children: /* @__PURE__ */ jsx(Empty, { children: t("common.noNFT") }) })
|
|
76
|
+
] }),
|
|
77
|
+
dataPage.next || paging.page > 1 ? /* @__PURE__ */ jsx(
|
|
78
|
+
Pagination,
|
|
79
|
+
{
|
|
80
|
+
sx: {
|
|
81
|
+
display: "flex",
|
|
82
|
+
justifyContent: "end"
|
|
83
|
+
},
|
|
84
|
+
page: paging.page,
|
|
85
|
+
onChange: handlePageChange,
|
|
86
|
+
count: Math.ceil(dataPage.total / paging.size),
|
|
87
|
+
size: "small"
|
|
88
|
+
}
|
|
89
|
+
) : null
|
|
90
|
+
] });
|
|
91
|
+
}, [loading, dataPage, paging.page, paging.size, handlePageChange]);
|
|
92
|
+
return /* @__PURE__ */ jsx(Box, { sx: { border: `1px solid ${colors.dividerColor}`, borderRadius: 2, p: 2, mb: 5 }, children: content });
|
|
93
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from "react";
|
|
3
|
-
import { Box,
|
|
3
|
+
import { Box, Typography } from "@mui/material";
|
|
4
4
|
import { useCreation, useMemoizedFn } from "ahooks";
|
|
5
5
|
import { translate } from "@arcblock/ux/lib/Locale/util";
|
|
6
6
|
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
@@ -74,25 +74,42 @@ export default function Settings({
|
|
|
74
74
|
...rest,
|
|
75
75
|
sx: {
|
|
76
76
|
...rest?.sx,
|
|
77
|
+
display: "flex",
|
|
78
|
+
flexDirection: "column",
|
|
79
|
+
gap: 2.5,
|
|
77
80
|
minWidth: {
|
|
78
81
|
md: 500
|
|
79
82
|
},
|
|
80
83
|
maxWidth: "100%"
|
|
81
84
|
},
|
|
82
|
-
children: tabs.map((tab
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
85
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxs(
|
|
86
|
+
Box,
|
|
87
|
+
{
|
|
88
|
+
id: tab.value,
|
|
89
|
+
sx: {
|
|
90
|
+
border: `1px solid ${colors.dividerColor}`,
|
|
91
|
+
borderRadius: 2,
|
|
92
|
+
p: 2,
|
|
93
|
+
"&:last-child": {
|
|
94
|
+
mb: 5
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ jsx(
|
|
99
|
+
Typography,
|
|
100
|
+
{
|
|
101
|
+
sx: {
|
|
102
|
+
color: colors.foregroundsFgBase,
|
|
103
|
+
fontWeight: 600
|
|
104
|
+
},
|
|
105
|
+
children: tab.label
|
|
106
|
+
}
|
|
107
|
+
),
|
|
108
|
+
/* @__PURE__ */ jsx(Box, { mt: 2.5, children: tab.content })
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
tab.value
|
|
112
|
+
))
|
|
96
113
|
}
|
|
97
114
|
);
|
|
98
115
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseStatusProps, StatusItem } from './menu-item';
|
|
2
|
+
interface StatusDurationMenuProps extends BaseStatusProps {
|
|
3
|
+
data: StatusItem;
|
|
4
|
+
}
|
|
5
|
+
declare function DurationMenu({ data, selected, onSelect }: StatusDurationMenuProps): import("react").JSX.Element;
|
|
6
|
+
export default DurationMenu;
|
|
7
|
+
export declare const MenuDiv: import("@emotion/styled").StyledComponent<import("@mui/material").MenuProps & {
|
|
8
|
+
theme?: import("@emotion/react").Theme;
|
|
9
|
+
}, {}, {}>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Menu, Typography } from "@mui/material";
|
|
3
|
+
import styled from "@emotion/styled";
|
|
4
|
+
import { temp as colors } from "@arcblock/ux/lib/Colors";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
7
|
+
import { useMemoizedFn } from "ahooks";
|
|
8
|
+
import { translate } from "@arcblock/ux/lib/Locale/util";
|
|
9
|
+
import { translations } from "../../libs/locales.js";
|
|
10
|
+
import StatusMenuItem, { StyledMenu } from "./menu-item.js";
|
|
11
|
+
function DurationMenu({ data, selected, onSelect }) {
|
|
12
|
+
const { locale } = useLocaleContext();
|
|
13
|
+
const t = useMemoizedFn((key, _data = {}) => {
|
|
14
|
+
return translate(translations, key, locale, "en", _data);
|
|
15
|
+
});
|
|
16
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
|
17
|
+
const open = Boolean(anchorEl);
|
|
18
|
+
const openSubMenu = (e) => {
|
|
19
|
+
setAnchorEl(e.currentTarget);
|
|
20
|
+
};
|
|
21
|
+
const closeSubMenu = () => {
|
|
22
|
+
setAnchorEl(null);
|
|
23
|
+
};
|
|
24
|
+
const onSelectStatus = (e) => {
|
|
25
|
+
openSubMenu(e);
|
|
26
|
+
};
|
|
27
|
+
const onSelectDuration = (e, item) => {
|
|
28
|
+
onSelect({
|
|
29
|
+
...selected ?? {},
|
|
30
|
+
value: data.id,
|
|
31
|
+
duration: item.id
|
|
32
|
+
});
|
|
33
|
+
closeSubMenu();
|
|
34
|
+
};
|
|
35
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36
|
+
/* @__PURE__ */ jsx(StatusMenuItem, { icon: data.icon, selected: selected?.value === data.id, onClick: onSelectStatus, children: data.name }),
|
|
37
|
+
/* @__PURE__ */ jsxs(
|
|
38
|
+
StyledMenu,
|
|
39
|
+
{
|
|
40
|
+
anchorOrigin: {
|
|
41
|
+
vertical: "top",
|
|
42
|
+
horizontal: "right"
|
|
43
|
+
},
|
|
44
|
+
transformOrigin: {
|
|
45
|
+
vertical: "top",
|
|
46
|
+
horizontal: "left"
|
|
47
|
+
},
|
|
48
|
+
open,
|
|
49
|
+
onClose: closeSubMenu,
|
|
50
|
+
anchorEl,
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsx(Typography, { component: "span", color: "text.secondary", pl: 2, fontSize: "14px", children: t("profile.removeStatusAfter") }),
|
|
53
|
+
data.children?.map((item) => /* @__PURE__ */ jsx(
|
|
54
|
+
StatusMenuItem,
|
|
55
|
+
{
|
|
56
|
+
selected: selected?.duration === item.id,
|
|
57
|
+
onClick: (e) => onSelectDuration(e, item),
|
|
58
|
+
children: item.name
|
|
59
|
+
},
|
|
60
|
+
item.id
|
|
61
|
+
))
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
export default DurationMenu;
|
|
68
|
+
export const MenuDiv = styled(Menu)`
|
|
69
|
+
.MuiList-root {
|
|
70
|
+
min-width: 160px;
|
|
71
|
+
}
|
|
72
|
+
.selected {
|
|
73
|
+
background-color: ${colors.backgroundsBgSubtitle};
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PopoverProps } from '@mui/material';
|
|
2
|
+
import { BaseStatusProps, StatusItem } from './menu-item';
|
|
3
|
+
interface StatusSelectorProps extends BaseStatusProps {
|
|
4
|
+
data: Array<StatusItem>;
|
|
5
|
+
open: boolean;
|
|
6
|
+
anchorEl?: PopoverProps['anchorEl'];
|
|
7
|
+
}
|
|
8
|
+
declare function StatusSelector({ data, open, onSelect, anchorEl, selected }: StatusSelectorProps): import("react").JSX.Element;
|
|
9
|
+
export default StatusSelector;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Typography } from "@mui/material";
|
|
3
|
+
import { translate } from "@arcblock/ux/lib/Locale/util";
|
|
4
|
+
import { useMemoizedFn } from "ahooks";
|
|
5
|
+
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
6
|
+
import StatusDurationMenu from "./duration-menu.js";
|
|
7
|
+
import StatusMenuItem, { StyledMenu } from "./menu-item.js";
|
|
8
|
+
import { translations } from "../../libs/locales.js";
|
|
9
|
+
function StatusSelector({ data, open, onSelect, anchorEl, selected }) {
|
|
10
|
+
const { locale } = useLocaleContext();
|
|
11
|
+
const t = useMemoizedFn((key, _data = {}) => {
|
|
12
|
+
return translate(translations, key, locale, "en", _data);
|
|
13
|
+
});
|
|
14
|
+
const onSelectStatus = (v) => {
|
|
15
|
+
onSelect(v);
|
|
16
|
+
};
|
|
17
|
+
const renderMenuItems = () => {
|
|
18
|
+
return data.map((item) => {
|
|
19
|
+
if (item.children) {
|
|
20
|
+
return /* @__PURE__ */ jsx(StatusDurationMenu, { data: item, selected, onSelect: onSelectStatus }, item.id);
|
|
21
|
+
}
|
|
22
|
+
return /* @__PURE__ */ jsx(
|
|
23
|
+
StatusMenuItem,
|
|
24
|
+
{
|
|
25
|
+
icon: item.icon,
|
|
26
|
+
selected: selected?.value === item.id,
|
|
27
|
+
onClick: () => onSelectStatus({ value: item.id }),
|
|
28
|
+
children: item.name
|
|
29
|
+
},
|
|
30
|
+
item.id
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
return /* @__PURE__ */ jsxs(StyledMenu, { open, onClose: () => onSelectStatus(), anchorEl, children: [
|
|
35
|
+
/* @__PURE__ */ jsx(Typography, { component: "span", color: "text.secondary", pl: 2, fontSize: "14px", children: t("profile.setStatus") }),
|
|
36
|
+
renderMenuItems()
|
|
37
|
+
] });
|
|
38
|
+
}
|
|
39
|
+
export default StatusSelector;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SvgIconProps } from '@mui/material/SvgIcon';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { UserMetadata } from '../../../@types';
|
|
4
|
+
interface StatusMenuItemProps {
|
|
5
|
+
icon?: React.FC<SvgIconProps>;
|
|
6
|
+
selected?: boolean;
|
|
7
|
+
onClick: (e: React.MouseEvent<HTMLElement>) => void;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export default function StatusMenuItem({ icon, selected, onClick, children }: StatusMenuItemProps): JSX.Element;
|
|
11
|
+
export declare const StyledMenu: import("@emotion/styled").StyledComponent<import("@mui/material").MenuProps & {
|
|
12
|
+
theme?: import("@emotion/react").Theme;
|
|
13
|
+
}, {}, {}>;
|
|
14
|
+
export interface StatusItem {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
icon?: React.FC<SvgIconProps>;
|
|
18
|
+
children?: Array<StatusItem>;
|
|
19
|
+
}
|
|
20
|
+
export interface BaseStatusProps {
|
|
21
|
+
selected: UserMetadata['status'];
|
|
22
|
+
onSelect: (v: UserMetadata['status']) => void;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ListItemIcon, MenuItem, Menu } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import styled from "@emotion/styled";
|
|
5
|
+
import { temp as colors } from "@arcblock/ux/lib/Colors";
|
|
6
|
+
export default function StatusMenuItem({ icon, selected, onClick, children }) {
|
|
7
|
+
return /* @__PURE__ */ jsxs(MenuItem, { onClick, className: selected ? "selected" : "", children: [
|
|
8
|
+
icon && /* @__PURE__ */ jsx(ListItemIcon, { style: { minWidth: "24px" }, children: React.createElement(icon, {
|
|
9
|
+
style: { fontSize: "16px", width: "16px", height: "16px" }
|
|
10
|
+
}) }),
|
|
11
|
+
children
|
|
12
|
+
] });
|
|
13
|
+
}
|
|
14
|
+
export const StyledMenu = styled(Menu)`
|
|
15
|
+
.MuiPaper-root {
|
|
16
|
+
box-shadow: 0px 6px 24px rgba(0, 0, 0, 0.15);
|
|
17
|
+
}
|
|
18
|
+
.MuiList-root {
|
|
19
|
+
min-width: 160px;
|
|
20
|
+
}
|
|
21
|
+
.selected {
|
|
22
|
+
background-color: ${colors.backgroundsBgSubtitle};
|
|
23
|
+
}
|
|
24
|
+
`;
|