@arcblock/ux 2.13.7 → 2.13.9
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/UserCard/Cards/avatar-only.d.ts +3 -2
- package/lib/UserCard/Cards/basic-info.d.ts +3 -2
- package/lib/UserCard/Cards/basic-info.js +12 -6
- package/lib/UserCard/Cards/index.d.ts +3 -2
- package/lib/UserCard/Cards/name-only.d.ts +4 -2
- package/lib/UserCard/Cards/name-only.js +3 -2
- package/lib/UserCard/Container/dialog.js +1 -1
- package/lib/UserCard/Content/basic.d.ts +2 -1
- package/lib/UserCard/Content/basic.js +255 -68
- package/lib/UserCard/Content/clock.js +18 -5
- package/lib/UserCard/Content/minimal.d.ts +2 -2
- package/lib/UserCard/Content/minimal.js +6 -2
- package/lib/UserCard/Content/tooltip-avatar.d.ts +4 -4
- package/lib/UserCard/Content/tooltip-avatar.js +4 -3
- package/lib/UserCard/components.d.ts +2 -2
- package/lib/UserCard/components.js +9 -3
- package/lib/UserCard/index.js +36 -4
- package/lib/UserCard/types.d.ts +7 -4
- package/lib/UserCard/utils.d.ts +2 -0
- package/lib/UserCard/utils.js +33 -0
- package/package.json +6 -6
- package/src/UserCard/Cards/avatar-only.tsx +3 -2
- package/src/UserCard/Cards/basic-info.tsx +17 -5
- package/src/UserCard/Cards/index.tsx +3 -2
- package/src/UserCard/Cards/name-only.tsx +4 -4
- package/src/UserCard/Container/dialog.tsx +1 -1
- package/src/UserCard/Content/basic.tsx +243 -58
- package/src/UserCard/Content/clock.tsx +22 -11
- package/src/UserCard/Content/minimal.tsx +6 -3
- package/src/UserCard/Content/tooltip-avatar.tsx +10 -5
- package/src/UserCard/components.tsx +17 -7
- package/src/UserCard/index.tsx +41 -3
- package/src/UserCard/types.ts +11 -4
- package/src/UserCard/utils.ts +33 -0
- package/lib/UserCard/Content/left-layout.d.ts +0 -16
- package/lib/UserCard/Content/left-layout.js +0 -33
- package/src/UserCard/Content/left-layout.tsx +0 -40
@@ -1,6 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { UserCardProps } from '../types';
|
3
|
-
interface AvatarOnlyCardProps extends UserCardProps {
|
2
|
+
import { UserCardProps, User } from '../types';
|
3
|
+
interface AvatarOnlyCardProps extends Omit<UserCardProps, 'user'> {
|
4
|
+
user: User;
|
4
5
|
renderCardContent: () => React.ReactNode;
|
5
6
|
shouldShowHoverCard: boolean;
|
6
7
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { UserCardProps } from '../types';
|
3
|
-
interface BasicCardProps extends UserCardProps {
|
2
|
+
import { UserCardProps, User } from '../types';
|
3
|
+
interface BasicCardProps extends Omit<UserCardProps, 'user'> {
|
4
|
+
user: User;
|
4
5
|
shouldShowHoverCard: boolean;
|
5
6
|
renderCardContent?: () => React.ReactNode | null;
|
6
7
|
isFull?: boolean;
|
@@ -12,6 +12,8 @@ function BasicCard(props) {
|
|
12
12
|
renderCustomContent,
|
13
13
|
isFull = true,
|
14
14
|
infoType = InfoType.Minimal,
|
15
|
+
renderFields,
|
16
|
+
popupRenderFields,
|
15
17
|
...rest
|
16
18
|
} = props;
|
17
19
|
return /*#__PURE__*/_jsxs(Box, {
|
@@ -28,12 +30,16 @@ function BasicCard(props) {
|
|
28
30
|
...rest
|
29
31
|
}), infoType === InfoType.Basic && /*#__PURE__*/_jsx(BasicContent, {
|
30
32
|
user: user,
|
31
|
-
isFull: isFull
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
isFull: isFull,
|
34
|
+
renderFields: renderFields
|
35
|
+
}), /*#__PURE__*/_jsx(Box, {
|
36
|
+
className: "user-card__footer",
|
37
|
+
children: renderCustomContent && /*#__PURE__*/_jsx(Box, {
|
38
|
+
sx: {
|
39
|
+
mt: 1.5
|
40
|
+
},
|
41
|
+
children: renderCustomContent()
|
42
|
+
})
|
37
43
|
})]
|
38
44
|
});
|
39
45
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { UserCardProps } from '../types';
|
3
|
-
interface DetailedCardProps extends UserCardProps {
|
2
|
+
import { UserCardProps, User } from '../types';
|
3
|
+
interface DetailedCardProps extends Omit<UserCardProps, 'user'> {
|
4
|
+
user: User;
|
4
5
|
shouldShowHoverCard: boolean;
|
5
6
|
renderCardContent?: () => React.ReactNode | null;
|
6
7
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
-
import { UserCardProps } from '../types';
|
2
|
-
declare function NameOnlyCard(props: UserCardProps
|
1
|
+
import { UserCardProps, User } from '../types';
|
2
|
+
declare function NameOnlyCard(props: Omit<UserCardProps, 'user'> & {
|
3
|
+
user: User;
|
4
|
+
}): import("react/jsx-runtime").JSX.Element;
|
3
5
|
export default NameOnlyCard;
|
@@ -6,10 +6,11 @@ import { renderAvatar } from '../components';
|
|
6
6
|
function NameOnlyCard(props) {
|
7
7
|
const {
|
8
8
|
user,
|
9
|
-
avatarSize = 48
|
9
|
+
avatarSize = 48,
|
10
|
+
onAvatarClick
|
10
11
|
} = props;
|
11
12
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
12
|
-
children: [renderAvatar(user, avatarSize, props.avatarProps), /*#__PURE__*/_jsx(Typography, {
|
13
|
+
children: [renderAvatar(user, avatarSize, props.avatarProps, onAvatarClick), /*#__PURE__*/_jsx(Typography, {
|
13
14
|
variant: "body1",
|
14
15
|
children: user.fullName || user.email || user.did
|
15
16
|
})]
|
@@ -2,6 +2,7 @@ import { User } from '../types';
|
|
2
2
|
interface BasicContentProps {
|
3
3
|
user: User;
|
4
4
|
isFull?: boolean;
|
5
|
+
renderFields?: string[];
|
5
6
|
}
|
6
|
-
declare function BasicContent({ user, isFull }: BasicContentProps): import("react/jsx-runtime").JSX.Element;
|
7
|
+
declare function BasicContent({ user, isFull, renderFields }: BasicContentProps): import("react/jsx-runtime").JSX.Element | null;
|
7
8
|
export default BasicContent;
|
@@ -1,13 +1,25 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
-
import { Typography, Box } from '@mui/material';
|
3
|
-
import { useCreation } from 'ahooks';
|
2
|
+
import { Typography, Box, Grid } from '@mui/material';
|
3
|
+
import { useCreation, useMemoizedFn } from 'ahooks';
|
4
4
|
import styled from '@emotion/styled';
|
5
|
+
import isArray from 'lodash/isArray';
|
6
|
+
import { Icon as IconifyIcon } from '@iconify/react';
|
7
|
+
import infoCircleIcon from '@iconify-icons/tabler/info-circle';
|
5
8
|
import LinkIcon from '@arcblock/icons/lib/Link';
|
9
|
+
import PhoneIcon from '@arcblock/icons/lib/Phone';
|
6
10
|
import LocationIcon from '@arcblock/icons/lib/Location';
|
7
11
|
import EmailIcon from '@arcblock/icons/lib/Email';
|
8
12
|
import TimezoneIcon from '@arcblock/icons/lib/Timezone';
|
9
|
-
import { withoutProtocol } from 'ufo';
|
13
|
+
import { joinURL, withoutProtocol } from 'ufo';
|
14
|
+
import { useState, useMemo, useCallback } from 'react';
|
10
15
|
import Clock from './clock';
|
16
|
+
const IconMap = {
|
17
|
+
timezone: TimezoneIcon,
|
18
|
+
email: EmailIcon,
|
19
|
+
phone: PhoneIcon,
|
20
|
+
location: LocationIcon,
|
21
|
+
link: LinkIcon
|
22
|
+
};
|
11
23
|
|
12
24
|
/**
|
13
25
|
* 格式化链接显示
|
@@ -20,10 +32,111 @@ const iconSize = {
|
|
20
32
|
width: 16,
|
21
33
|
height: 16
|
22
34
|
};
|
35
|
+
|
36
|
+
// 定义渲染项的类型
|
37
|
+
|
38
|
+
function TimeZoneField({
|
39
|
+
value
|
40
|
+
}) {
|
41
|
+
return /*#__PURE__*/_jsxs(Box, {
|
42
|
+
display: "flex",
|
43
|
+
alignItems: "center",
|
44
|
+
gap: 1,
|
45
|
+
className: "user-card__timezone-field",
|
46
|
+
children: [/*#__PURE__*/_jsx(TimezoneIcon, {
|
47
|
+
...iconSize
|
48
|
+
}), /*#__PURE__*/_jsx(Clock, {
|
49
|
+
value: value,
|
50
|
+
variant: "body2",
|
51
|
+
color: "grey.800"
|
52
|
+
})]
|
53
|
+
});
|
54
|
+
}
|
55
|
+
function LinkField({
|
56
|
+
value
|
57
|
+
}) {
|
58
|
+
const [useFallback, setUseFallback] = useState(false);
|
59
|
+
const faviconUrl = useCreation(() => {
|
60
|
+
try {
|
61
|
+
const url = new URL(value);
|
62
|
+
return joinURL(url.origin, 'favicon.ico');
|
63
|
+
} catch (e) {
|
64
|
+
return '';
|
65
|
+
}
|
66
|
+
}, [value]);
|
67
|
+
const handleImageError = () => {
|
68
|
+
setUseFallback(true);
|
69
|
+
};
|
70
|
+
return /*#__PURE__*/_jsxs(Box, {
|
71
|
+
display: "flex",
|
72
|
+
alignItems: "center",
|
73
|
+
gap: 1,
|
74
|
+
className: "user-card__link-field",
|
75
|
+
children: [faviconUrl && !useFallback ? /*#__PURE__*/_jsx("img", {
|
76
|
+
src: faviconUrl,
|
77
|
+
alt: "site icon",
|
78
|
+
style: {
|
79
|
+
width: 16,
|
80
|
+
height: 16,
|
81
|
+
objectFit: 'contain'
|
82
|
+
},
|
83
|
+
onError: handleImageError
|
84
|
+
}) : /*#__PURE__*/_jsx(LinkIcon, {
|
85
|
+
...iconSize
|
86
|
+
}), /*#__PURE__*/_jsx(LineText, {
|
87
|
+
variant: "body2",
|
88
|
+
color: "grey.800",
|
89
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
90
|
+
component: "a",
|
91
|
+
href: value,
|
92
|
+
style: {
|
93
|
+
textDecoration: 'none',
|
94
|
+
color: 'inherit',
|
95
|
+
fontSize: 'inherit'
|
96
|
+
},
|
97
|
+
target: "_blank",
|
98
|
+
variant: "body2",
|
99
|
+
color: "grey.800",
|
100
|
+
rel: "noopener noreferrer",
|
101
|
+
children: formatLinkDisplay(value)
|
102
|
+
})
|
103
|
+
})]
|
104
|
+
});
|
105
|
+
}
|
106
|
+
function BasicField({
|
107
|
+
field,
|
108
|
+
value,
|
109
|
+
children
|
110
|
+
}) {
|
111
|
+
const Icon = IconMap[field];
|
112
|
+
return /*#__PURE__*/_jsxs(Box, {
|
113
|
+
display: "flex",
|
114
|
+
alignItems: "center",
|
115
|
+
gap: 1,
|
116
|
+
className: `user-card__${field}-field`,
|
117
|
+
children: [Icon ? /*#__PURE__*/_jsx(Icon, {
|
118
|
+
...iconSize
|
119
|
+
}) : /*#__PURE__*/_jsx(IconifyIcon, {
|
120
|
+
icon: infoCircleIcon,
|
121
|
+
...iconSize
|
122
|
+
}), /*#__PURE__*/_jsx(LineText, {
|
123
|
+
variant: "body2",
|
124
|
+
color: "grey.800",
|
125
|
+
children: children ?? value
|
126
|
+
})]
|
127
|
+
}, field);
|
128
|
+
}
|
23
129
|
function BasicContent({
|
24
130
|
user,
|
25
|
-
isFull = false
|
131
|
+
isFull = false,
|
132
|
+
renderFields
|
26
133
|
}) {
|
134
|
+
const fields = useCreation(() => {
|
135
|
+
return renderFields ?? ['bio', 'email', 'phone', 'location', 'timezone', 'link'];
|
136
|
+
}, [renderFields]);
|
137
|
+
const includeBio = useCreation(() => {
|
138
|
+
return fields.includes('bio');
|
139
|
+
}, [fields]);
|
27
140
|
const metadata = useCreation(() => {
|
28
141
|
return user.metadata ?? {
|
29
142
|
joinedAt: user?.createdAt,
|
@@ -34,83 +147,157 @@ function BasicContent({
|
|
34
147
|
}
|
35
148
|
};
|
36
149
|
}, [user]);
|
150
|
+
const address = useCreation(() => {
|
151
|
+
return user.address;
|
152
|
+
}, [user.address]);
|
153
|
+
const getFieldValue = useCallback(field => {
|
154
|
+
if (!field) return '';
|
155
|
+
switch (field) {
|
156
|
+
case 'bio':
|
157
|
+
return user.metadata?.bio || '';
|
158
|
+
case 'email':
|
159
|
+
return metadata.email || user.email || '';
|
160
|
+
case 'phone':
|
161
|
+
return metadata.phone?.phoneNumber || user.phone || '';
|
162
|
+
case 'location':
|
163
|
+
return address?.city || metadata.location || '';
|
164
|
+
case 'timezone':
|
165
|
+
return metadata.timezone || '';
|
166
|
+
case 'link':
|
167
|
+
return metadata.links?.map(link => link.url).filter(Boolean) || [];
|
168
|
+
default:
|
169
|
+
return user[field] || '';
|
170
|
+
}
|
171
|
+
}, [user, metadata, address]);
|
37
172
|
|
38
|
-
//
|
39
|
-
const
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
})
|
173
|
+
// 计算实际可见的字段数量和渲染元素数量
|
174
|
+
const {
|
175
|
+
effectiveRenderCount
|
176
|
+
} = useMemo(() => {
|
177
|
+
const visible = fields.filter(field => {
|
178
|
+
if (field === 'bio') return false; // bio field is handled separately
|
179
|
+
const value = getFieldValue(field);
|
180
|
+
if (value === undefined || value === null || value === '') return false;
|
181
|
+
if (isArray(value)) {
|
182
|
+
return value.length > 0;
|
183
|
+
}
|
184
|
+
return String(value).trim().length > 0;
|
185
|
+
});
|
186
|
+
|
187
|
+
// 计算实际渲染数量
|
188
|
+
const renderCount = visible.reduce((count, field) => {
|
189
|
+
const value = getFieldValue(field);
|
190
|
+
return count + (Array.isArray(value) ? value.filter(item => item && String(item).trim()).length : 1);
|
191
|
+
}, 0);
|
192
|
+
return {
|
193
|
+
visibleFields: visible,
|
194
|
+
effectiveRenderCount: renderCount
|
195
|
+
};
|
196
|
+
}, [fields, getFieldValue]);
|
197
|
+
|
198
|
+
// 判断是否需要使用两列布局
|
199
|
+
const useDoubleColumn = effectiveRenderCount > 4;
|
200
|
+
const isValidValue = useMemoizedFn(value => value !== undefined && value !== null && String(value).trim().length > 0);
|
201
|
+
|
202
|
+
// 准备要渲染的所有元素项
|
203
|
+
const renderItems = useMemo(() => {
|
204
|
+
const items = [];
|
205
|
+
|
206
|
+
// 遍历有效字段,展开数组字段为单独的渲染项
|
207
|
+
fields.forEach(field => {
|
208
|
+
if (field === 'bio') return; // bio field is handled separately
|
209
|
+
const value = getFieldValue(field);
|
210
|
+
if (!value) return;
|
211
|
+
if (isArray(value)) {
|
212
|
+
// 数组类型字段,每个有效项生成一个渲染元素
|
213
|
+
value.forEach((item, index) => {
|
214
|
+
if (isValidValue(item)) {
|
215
|
+
items.push({
|
216
|
+
field,
|
217
|
+
value: item,
|
218
|
+
key: `${field}-${index}`
|
219
|
+
});
|
220
|
+
}
|
221
|
+
});
|
222
|
+
} else if (isValidValue(value)) {
|
223
|
+
// 非数组类型字段,生成一个渲染元素
|
224
|
+
items.push({
|
225
|
+
field,
|
226
|
+
value,
|
227
|
+
key: field
|
228
|
+
});
|
229
|
+
}
|
230
|
+
});
|
231
|
+
return items;
|
232
|
+
}, [fields, getFieldValue, isValidValue]);
|
233
|
+
if (fields.length === 0) {
|
234
|
+
return null;
|
235
|
+
}
|
236
|
+
const renderItem = item => {
|
237
|
+
const {
|
238
|
+
field,
|
239
|
+
value,
|
240
|
+
key
|
241
|
+
} = item;
|
242
|
+
switch (field) {
|
243
|
+
case 'link':
|
244
|
+
return /*#__PURE__*/_jsx(LinkField, {
|
245
|
+
value: value
|
246
|
+
}, key);
|
247
|
+
case 'timezone':
|
248
|
+
return /*#__PURE__*/_jsx(TimeZoneField, {
|
249
|
+
value: value
|
250
|
+
}, key);
|
251
|
+
case 'email':
|
252
|
+
return /*#__PURE__*/_jsx(BasicField, {
|
253
|
+
field: field,
|
254
|
+
value: value
|
255
|
+
// eslint-disable-next-line react/no-children-prop
|
256
|
+
,
|
257
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
258
|
+
component: "a",
|
259
|
+
href: `mailto:${value}`,
|
260
|
+
rel: "noopener noreferrer",
|
261
|
+
referrerPolicy: "no-referrer",
|
262
|
+
style: {
|
263
|
+
color: 'inherit',
|
264
|
+
textDecoration: 'none',
|
265
|
+
fontSize: 'inherit'
|
266
|
+
},
|
267
|
+
children: value
|
268
|
+
})
|
269
|
+
});
|
270
|
+
default:
|
271
|
+
return /*#__PURE__*/_jsx(BasicField, {
|
272
|
+
field: field,
|
273
|
+
value: value
|
274
|
+
}, key);
|
275
|
+
}
|
57
276
|
};
|
58
277
|
return /*#__PURE__*/_jsxs(Box, {
|
59
278
|
mt: 1,
|
60
279
|
display: "flex",
|
61
280
|
flexDirection: "column",
|
62
281
|
gap: 1.5,
|
63
|
-
|
282
|
+
className: "user-card__basic-content",
|
283
|
+
children: [includeBio && user.metadata?.bio && /*#__PURE__*/_jsx(LineText, {
|
64
284
|
variant: "body2",
|
65
285
|
color: "grey.800",
|
286
|
+
className: "user-card__bio-field",
|
66
287
|
children: user.metadata.bio
|
67
|
-
}), /*#__PURE__*/
|
288
|
+
}), useDoubleColumn ? /*#__PURE__*/_jsx(Grid, {
|
289
|
+
container: true,
|
290
|
+
spacing: 0.5,
|
291
|
+
children: renderItems.map(item => /*#__PURE__*/_jsx(Grid, {
|
292
|
+
item: true,
|
293
|
+
xs: 6,
|
294
|
+
children: renderItem(item)
|
295
|
+
}, item.key))
|
296
|
+
}) : /*#__PURE__*/_jsx(Box, {
|
68
297
|
display: "flex",
|
69
298
|
flexDirection: "column",
|
70
299
|
gap: 0.5,
|
71
|
-
children:
|
72
|
-
display: "flex",
|
73
|
-
alignItems: "center",
|
74
|
-
gap: 1,
|
75
|
-
children: [/*#__PURE__*/_jsx(LinkIcon, {
|
76
|
-
...iconSize
|
77
|
-
}), /*#__PURE__*/_jsx(LineText, {
|
78
|
-
children: /*#__PURE__*/_jsx(Typography, {
|
79
|
-
component: "a",
|
80
|
-
href: firstLink.url,
|
81
|
-
style: {
|
82
|
-
textDecoration: 'none'
|
83
|
-
},
|
84
|
-
target: "_blank",
|
85
|
-
variant: "body2",
|
86
|
-
color: "grey.800",
|
87
|
-
rel: "noopener noreferrer",
|
88
|
-
children: formatLinkDisplay(firstLink.url)
|
89
|
-
})
|
90
|
-
})]
|
91
|
-
}), metadata.location && /*#__PURE__*/_jsxs(Box, {
|
92
|
-
display: "flex",
|
93
|
-
alignItems: "center",
|
94
|
-
gap: 1,
|
95
|
-
children: [/*#__PURE__*/_jsx(LocationIcon, {
|
96
|
-
...iconSize
|
97
|
-
}), /*#__PURE__*/_jsx(LineText, {
|
98
|
-
variant: "body2",
|
99
|
-
color: "grey.800",
|
100
|
-
children: metadata.location
|
101
|
-
})]
|
102
|
-
}), isFull && moreContent(), (metadata.email || user.email) && /*#__PURE__*/_jsxs(Box, {
|
103
|
-
display: "flex",
|
104
|
-
alignItems: "center",
|
105
|
-
gap: 1,
|
106
|
-
children: [/*#__PURE__*/_jsx(EmailIcon, {
|
107
|
-
...iconSize
|
108
|
-
}), /*#__PURE__*/_jsx(LineText, {
|
109
|
-
variant: "body2",
|
110
|
-
color: "grey.800",
|
111
|
-
children: metadata.email || user.email
|
112
|
-
})]
|
113
|
-
})]
|
300
|
+
children: renderItems.map(item => renderItem(item))
|
114
301
|
})]
|
115
302
|
});
|
116
303
|
}
|
@@ -40,16 +40,21 @@ export default function Clock({
|
|
40
40
|
});
|
41
41
|
const timeInfo = useClock(value, locale);
|
42
42
|
return /*#__PURE__*/_jsxs(Box, {
|
43
|
-
sx: {
|
44
|
-
whiteSpace: 'nowrap',
|
45
|
-
overflow: 'hidden',
|
46
|
-
textOverflow: 'ellipsis'
|
47
|
-
},
|
48
43
|
display: "flex",
|
49
44
|
alignItems: "center",
|
50
45
|
gap: 1,
|
46
|
+
flex: 1,
|
47
|
+
justifyContent: "flex-start",
|
48
|
+
overflow: "hidden",
|
49
|
+
width: "100%",
|
51
50
|
children: [/*#__PURE__*/_jsx(Typography, {
|
52
51
|
...props,
|
52
|
+
noWrap: true,
|
53
|
+
sx: {
|
54
|
+
flex: '0 1 auto',
|
55
|
+
minWidth: 0,
|
56
|
+
...props.sx
|
57
|
+
},
|
53
58
|
children: value
|
54
59
|
}), /*#__PURE__*/_jsx(Tooltip, {
|
55
60
|
enterDelay: 200,
|
@@ -61,6 +66,14 @@ export default function Clock({
|
|
61
66
|
children: /*#__PURE__*/_jsxs(Typography, {
|
62
67
|
component: "span",
|
63
68
|
fontSize: 14,
|
69
|
+
noWrap: true,
|
70
|
+
sx: {
|
71
|
+
whiteSpace: 'nowrap',
|
72
|
+
overflow: 'hidden',
|
73
|
+
textOverflow: 'ellipsis',
|
74
|
+
flex: '0 0 auto',
|
75
|
+
maxWidth: '100%'
|
76
|
+
},
|
64
77
|
children: ["(", locale === 'zh' ? `${t(`timezonePhase.${timeInfo.phase}`)} ` : '', timeInfo.formattedTime, ")"]
|
65
78
|
})
|
66
79
|
})]
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { UserCardProps } from '../types';
|
2
|
+
import { User, UserCardProps } from '../types';
|
3
3
|
interface MinimalContentProps extends UserCardProps {
|
4
|
-
user:
|
4
|
+
user: User;
|
5
5
|
avatarSize: number;
|
6
6
|
shouldShowHoverCard: boolean;
|
7
7
|
renderCardContent?: () => React.ReactNode | null;
|
@@ -16,12 +16,14 @@ function MinimalContent(props) {
|
|
16
16
|
renderTopRightContent,
|
17
17
|
topRightMaxWidth,
|
18
18
|
avatarProps,
|
19
|
-
shortenLabelProps
|
19
|
+
shortenLabelProps,
|
20
|
+
...rest
|
20
21
|
} = props;
|
21
22
|
return /*#__PURE__*/_jsxs(Box, {
|
22
23
|
display: "flex",
|
23
24
|
justifyContent: "space-between",
|
24
25
|
alignItems: "center",
|
26
|
+
className: "user-card__avatar-content",
|
25
27
|
children: [/*#__PURE__*/_jsxs(Box, {
|
26
28
|
display: "flex",
|
27
29
|
justifyContent: "flex-start",
|
@@ -34,12 +36,14 @@ function MinimalContent(props) {
|
|
34
36
|
avatarSize: avatarSize,
|
35
37
|
shouldShowHoverCard: shouldShowHoverCard,
|
36
38
|
renderCardContent: renderCardContent,
|
37
|
-
avatarProps: avatarProps
|
39
|
+
avatarProps: avatarProps,
|
40
|
+
...rest
|
38
41
|
}), /*#__PURE__*/_jsxs(Box, {
|
39
42
|
children: [/*#__PURE__*/_jsx(Typography, {
|
40
43
|
variant: "subtitle1",
|
41
44
|
fontWeight: 500,
|
42
45
|
color: "text.primary",
|
46
|
+
className: "user-card__full-name-label",
|
43
47
|
fontSize: 18,
|
44
48
|
noWrap: true,
|
45
49
|
sx: {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { UserCardProps } from '../types';
|
3
|
-
interface TooltipAvatarProps {
|
4
|
-
user:
|
2
|
+
import { User, UserCardProps } from '../types';
|
3
|
+
interface TooltipAvatarProps extends UserCardProps {
|
4
|
+
user: User;
|
5
5
|
avatarSize: number;
|
6
6
|
shouldShowHoverCard: boolean;
|
7
7
|
renderCardContent?: () => React.ReactNode | null;
|
@@ -13,5 +13,5 @@ interface TooltipAvatarProps {
|
|
13
13
|
* 统一处理头像的Tooltip显示组件
|
14
14
|
* 根据条件显示普通Tooltip、自定义Tooltip内容或无Tooltip的头像
|
15
15
|
*/
|
16
|
-
declare function TooltipAvatar({ user, avatarSize, shouldShowHoverCard, renderCardContent, tooltipTitle, tooltipProps, avatarProps, }: TooltipAvatarProps): import("react/jsx-runtime").JSX.Element;
|
16
|
+
declare function TooltipAvatar({ user, avatarSize, shouldShowHoverCard, renderCardContent, tooltipTitle, tooltipProps, avatarProps, onAvatarClick, }: TooltipAvatarProps): import("react/jsx-runtime").JSX.Element;
|
17
17
|
export default TooltipAvatar;
|
@@ -14,11 +14,12 @@ function TooltipAvatar({
|
|
14
14
|
renderCardContent,
|
15
15
|
tooltipTitle,
|
16
16
|
tooltipProps,
|
17
|
-
avatarProps
|
17
|
+
avatarProps,
|
18
|
+
onAvatarClick
|
18
19
|
}) {
|
19
20
|
const avatarElement = /*#__PURE__*/_jsx(Box, {
|
20
21
|
display: "inline-block",
|
21
|
-
children: renderAvatar(user, avatarSize, avatarProps)
|
22
|
+
children: renderAvatar(user, avatarSize, avatarProps, onAvatarClick, shouldShowHoverCard || !!tooltipTitle)
|
22
23
|
});
|
23
24
|
// 使用普通文本Tooltip
|
24
25
|
if (tooltipTitle) {
|
@@ -44,7 +45,7 @@ function TooltipAvatar({
|
|
44
45
|
'& .MuiTooltip-tooltip': {
|
45
46
|
backgroundColor: 'transparent',
|
46
47
|
p: 0,
|
47
|
-
maxWidth:
|
48
|
+
maxWidth: 500,
|
48
49
|
zIndex: 1000
|
49
50
|
}
|
50
51
|
}
|
@@ -1,4 +1,4 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { UserCardProps } from './types';
|
3
|
-
export declare const renderAvatar: (user:
|
2
|
+
import { User, UserCardProps } from './types';
|
3
|
+
export declare const renderAvatar: (user: User, avatarSize?: number, avatarProps?: UserCardProps["avatarProps"], onAvatarClick?: UserCardProps["onAvatarClick"], shouldShowHoverCard?: boolean) => import("react/jsx-runtime").JSX.Element;
|
4
4
|
export declare const renderTopRight: (renderTopRightContent: (() => React.ReactNode) | undefined, topRightMaxWidth?: number) => import("react/jsx-runtime").JSX.Element | null;
|
@@ -5,7 +5,10 @@ import Avatar from '../Avatar';
|
|
5
5
|
import { createNameOnlyAvatar } from './utils';
|
6
6
|
|
7
7
|
// 渲染头像
|
8
|
-
export const renderAvatar = (user, avatarSize = 48, avatarProps = undefined) => {
|
8
|
+
export const renderAvatar = (user, avatarSize = 48, avatarProps = undefined, onAvatarClick = undefined, shouldShowHoverCard = false) => {
|
9
|
+
const onClick = e => {
|
10
|
+
onAvatarClick?.(user, e);
|
11
|
+
};
|
9
12
|
// 如果用户没有头像,则显示名称首字母头像
|
10
13
|
if (!user.avatar) {
|
11
14
|
const avatarContent = createNameOnlyAvatar(user);
|
@@ -13,9 +16,10 @@ export const renderAvatar = (user, avatarSize = 48, avatarProps = undefined) =>
|
|
13
16
|
size: avatarSize,
|
14
17
|
did: user.did,
|
15
18
|
variant: "circle",
|
19
|
+
onClick: onClick,
|
16
20
|
sx: {
|
17
21
|
fontSize: avatarSize * 0.4,
|
18
|
-
cursor: 'pointer'
|
22
|
+
cursor: shouldShowHoverCard || onAvatarClick ? 'pointer' : 'default'
|
19
23
|
},
|
20
24
|
...(avatarProps || {}),
|
21
25
|
children: avatarContent
|
@@ -28,8 +32,9 @@ export const renderAvatar = (user, avatarSize = 48, avatarProps = undefined) =>
|
|
28
32
|
did: user.did,
|
29
33
|
variant: "circle",
|
30
34
|
style: {
|
31
|
-
cursor: 'pointer'
|
35
|
+
cursor: shouldShowHoverCard || onAvatarClick ? 'pointer' : 'default'
|
32
36
|
},
|
37
|
+
onClick: onClick,
|
33
38
|
src: user.avatar,
|
34
39
|
alt: user.fullName || '',
|
35
40
|
...(avatarProps || {})
|
@@ -43,6 +48,7 @@ export const renderTopRight = (renderTopRightContent, topRightMaxWidth = 120) =>
|
|
43
48
|
sx: {
|
44
49
|
maxWidth: topRightMaxWidth
|
45
50
|
},
|
51
|
+
className: "user-card__top-right-content",
|
46
52
|
children: renderTopRightContent()
|
47
53
|
});
|
48
54
|
}
|