@arcblock/ux 2.5.59 → 2.5.60
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/Blocklet/blocklet.js +1 -1
- package/lib/BlockletNFT/index.js +1 -1
- package/lib/SessionManager/federated-login-detecter.js +171 -0
- package/lib/SessionManager/index.js +161 -191
- package/lib/SessionManager/user-popper.js +83 -0
- package/package.json +4 -4
- package/src/Blocklet/blocklet.js +1 -1
- package/src/BlockletNFT/index.js +1 -1
- package/src/SessionManager/federated-login-detecter.jsx +138 -0
- package/src/SessionManager/index.jsx +140 -233
- package/src/SessionManager/user-popper.jsx +121 -0
@@ -2,7 +2,7 @@
|
|
2
2
|
/* eslint-disable react/jsx-no-bind */
|
3
3
|
import { useMemo, useRef, useState } from 'react';
|
4
4
|
import PropTypes from 'prop-types';
|
5
|
-
import { IconButton,
|
5
|
+
import { IconButton, MenuList, MenuItem, SvgIcon, Button, Chip } from '@mui/material';
|
6
6
|
import AccountIcon from '@arcblock/icons/lib/Account';
|
7
7
|
import ShieldCheck from 'mdi-material-ui/ShieldCheck';
|
8
8
|
import OpenInIcon from '@arcblock/icons/lib/OpenIn';
|
@@ -12,12 +12,11 @@ import SwitchProfileIcon from '@mui/icons-material/PersonOutline';
|
|
12
12
|
import BindWalletIcon from '@mui/icons-material/Link';
|
13
13
|
import SwitchPassportIcon from '@mui/icons-material/VpnKeyOutlined';
|
14
14
|
import useBrowser from '@arcblock/react-hooks/lib/useBrowser';
|
15
|
-
import { useOAuth } from '@arcblock/did-connect/lib/OAuth';
|
16
|
-
import { useDid } from '@arcblock/did-connect/lib/User';
|
17
15
|
|
18
|
-
import { styled } from '../Theme';
|
19
16
|
import DidAvatar from '../Avatar';
|
20
17
|
import DidAddress from '../Address';
|
18
|
+
import FederatedLoginDetecter from './federated-login-detecter';
|
19
|
+
import UserPopper from './user-popper';
|
21
20
|
|
22
21
|
const translations = {
|
23
22
|
en: {
|
@@ -71,7 +70,8 @@ function SessionManager({
|
|
71
70
|
}) {
|
72
71
|
const translation = translations[locale] || translations.en;
|
73
72
|
const userAnchorRef = useRef(null);
|
74
|
-
|
73
|
+
// eslint-disable-next-line react/prop-types
|
74
|
+
const { logoutOAuth, bindOAuth, configs: oauthConfigs, switchOAuthPassport } = session.useOAuth();
|
75
75
|
const [userOpen, setUserOpen] = useState(false);
|
76
76
|
|
77
77
|
// base64 img maybe have some blank char, need encodeURIComponent to transform it
|
@@ -81,7 +81,8 @@ function SessionManager({
|
|
81
81
|
[session.user]
|
82
82
|
);
|
83
83
|
const browser = useBrowser();
|
84
|
-
|
84
|
+
// eslint-disable-next-line react/prop-types
|
85
|
+
const { walletDid } = session.useDid({ session });
|
85
86
|
|
86
87
|
const isRawWalletAccount = getSourceProvider(session.user) === 'wallet';
|
87
88
|
const connectedAccounts = getConnectedAccounts(session.user);
|
@@ -104,21 +105,28 @@ function SessionManager({
|
|
104
105
|
.filter((item) => item.enabled);
|
105
106
|
|
106
107
|
if (!session.user) {
|
107
|
-
return
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
108
|
+
return (
|
109
|
+
<>
|
110
|
+
{showText ? (
|
111
|
+
<Button
|
112
|
+
ref={userAnchorRef}
|
113
|
+
sx={[{ borderRadius: '100vw' }, dark && { color: '#fff', borderColor: '#fff' }]}
|
114
|
+
variant="outlined"
|
115
|
+
onClick={_onLogin}
|
116
|
+
aria-label="login button"
|
117
|
+
{...rest}
|
118
|
+
data-cy="sessionManager-login">
|
119
|
+
<AccountIcon />
|
120
|
+
<span style={{ lineHeight: '25px' }}>{translation.connect}</span>
|
121
|
+
</Button>
|
122
|
+
) : (
|
123
|
+
<IconButton ref={userAnchorRef} {...rest} onClick={_onLogin} data-cy="sessionManager-login" size="medium">
|
124
|
+
<AccountIcon style={{ width: size, height: size, color: dark ? '#fff' : '' }} />
|
125
|
+
</IconButton>
|
126
|
+
)}
|
127
|
+
|
128
|
+
<FederatedLoginDetecter locale={locale} dark={dark} session={session} anchorEl={userAnchorRef.current} />
|
129
|
+
</>
|
122
130
|
);
|
123
131
|
}
|
124
132
|
|
@@ -198,163 +206,127 @@ function SessionManager({
|
|
198
206
|
style={{ lineHeight: 1 }}>
|
199
207
|
<DidAvatar variant="circle" did={session.user.did} src={avatar} size={size} shape="circle" />
|
200
208
|
</IconButton>
|
201
|
-
{userAnchorRef.current && (
|
202
|
-
<StyledPopper
|
203
|
-
open={userOpen}
|
204
|
-
disablePortal
|
205
|
-
anchorEl={userAnchorRef.current}
|
206
|
-
placement="bottom-end"
|
207
|
-
$dark={dark}>
|
208
|
-
<Paper
|
209
|
-
sx={[
|
210
|
-
(theme) => ({
|
211
|
-
borderColor: '#F0F0F0',
|
212
|
-
boxShadow: '0px 8px 12px rgba(92, 92, 92, 0.04)',
|
213
|
-
borderRadius: theme.spacing(2),
|
214
|
-
overflow: 'hidden',
|
215
|
-
maxWidth: 'calc(100vw - 10px)',
|
216
|
-
'& .MuiChip-root .MuiChip-icon': {
|
217
|
-
color: theme.palette.success.main,
|
218
|
-
},
|
219
|
-
}),
|
220
|
-
dark && {
|
221
|
-
backgroundColor: '#27282c',
|
222
|
-
color: '#fff',
|
223
|
-
border: 0,
|
224
|
-
'& .MuiChip-root': {
|
225
|
-
borderColor: '#aaa',
|
226
|
-
},
|
227
|
-
'& .MuiListItem-root, & .MuiChip-label': {
|
228
|
-
color: '#aaa',
|
229
|
-
},
|
230
|
-
'& .MuiListItem-root:hover': {
|
231
|
-
backgroundColor: '#363434',
|
232
|
-
},
|
233
|
-
},
|
234
|
-
]}
|
235
|
-
variant="outlined">
|
236
|
-
<ClickAwayListener onClickAway={onCloseUser}>
|
237
|
-
<MenuList sx={{ p: 0 }}>
|
238
|
-
<div className="session-manager-user">
|
239
|
-
<div className="session-manager-user-name">
|
240
|
-
<span>{session.user.fullName}</span>
|
241
|
-
{!!showRole && (currentRole?.title || session.user?.role.toUpperCase()) && (
|
242
|
-
<Chip
|
243
|
-
label={currentRole?.title || session.user?.role.toUpperCase()}
|
244
|
-
size="small"
|
245
|
-
variant="outlined"
|
246
|
-
sx={{ height: 'auto', marginRight: 0 }}
|
247
|
-
icon={<SvgIcon component={ShieldCheck} size="small" />}
|
248
|
-
/>
|
249
|
-
)}
|
250
|
-
</div>
|
251
|
-
<div className="session-manager-id-list">
|
252
|
-
{walletDid && (
|
253
|
-
<div className="session-manager-id-item">
|
254
|
-
<DidAddress responsive={false}>{walletDid}</DidAddress>
|
255
|
-
</div>
|
256
|
-
)}
|
257
|
-
{session?.user?.email && (
|
258
|
-
<div className="session-manager-id-item">
|
259
|
-
<DidAddress responsive={false}>{session.user.email}</DidAddress>
|
260
|
-
</div>
|
261
|
-
)}
|
262
|
-
</div>
|
263
|
-
</div>
|
264
|
-
{Array.isArray(menu) &&
|
265
|
-
menu.map((menuItem, index) => {
|
266
|
-
const { svgIcon, ...menuProps } = menuItem;
|
267
|
-
return (
|
268
|
-
<MenuItem
|
269
|
-
key={index}
|
270
|
-
className="session-manager-menu-item"
|
271
|
-
{...{
|
272
|
-
...menuProps,
|
273
|
-
icon: undefined,
|
274
|
-
label: undefined,
|
275
|
-
}}>
|
276
|
-
{svgIcon
|
277
|
-
? svgIcon && <SvgIcon component={svgIcon} className="session-manager-menu-icon" />
|
278
|
-
: menuItem.icon}
|
279
|
-
{menuItem.label}
|
280
|
-
</MenuItem>
|
281
|
-
);
|
282
|
-
})}
|
283
|
-
{menuRender({
|
284
|
-
classes: {
|
285
|
-
menuItem: 'session-manager-menu-item',
|
286
|
-
menuIcon: 'session-manager-menu-icon',
|
287
|
-
},
|
288
|
-
})}
|
289
|
-
{!browser.wallet && (
|
290
|
-
<MenuItem
|
291
|
-
component="a"
|
292
|
-
className="session-manager-menu-item"
|
293
|
-
data-cy="sessionManager-openInWallet"
|
294
|
-
href="https://www.abtwallet.io/"
|
295
|
-
target="_blank">
|
296
|
-
<SvgIcon component={OpenInIcon} className="session-manager-menu-icon" />
|
297
|
-
{translation.openInWallet}
|
298
|
-
</MenuItem>
|
299
|
-
)}
|
300
|
-
{!!switchDid && (
|
301
|
-
<MenuItem
|
302
|
-
className="session-manager-menu-item"
|
303
|
-
onClick={_onSwitchDid}
|
304
|
-
data-cy="sessionManager-switch-trigger">
|
305
|
-
<SvgIcon component={SwitchDidIcon} className="session-manager-menu-icon" />
|
306
|
-
{translation.switchDid}
|
307
|
-
</MenuItem>
|
308
|
-
)}
|
309
|
-
{!!switchProfile && hasBindWallet && (
|
310
|
-
<MenuItem
|
311
|
-
className="session-manager-menu-item"
|
312
|
-
onClick={_onSwitchProfile}
|
313
|
-
data-cy="sessionManager-switch-profile-trigger">
|
314
|
-
<SvgIcon component={SwitchProfileIcon} className="session-manager-menu-icon" />
|
315
|
-
{translation.switchProfile}
|
316
|
-
</MenuItem>
|
317
|
-
)}
|
318
|
-
{!!switchPassport && (
|
319
|
-
<MenuItem
|
320
|
-
className="session-manager-menu-item"
|
321
|
-
onClick={_onSwitchPassport}
|
322
|
-
data-cy="sessionManager-switch-passport-trigger">
|
323
|
-
<SvgIcon component={SwitchPassportIcon} className="session-manager-menu-icon" />
|
324
|
-
{translation.switchPassport}
|
325
|
-
</MenuItem>
|
326
|
-
)}
|
327
|
-
{oauthConfigList.length > 0 && !hasBindAccount && (
|
328
|
-
<MenuItem
|
329
|
-
className="session-manager-menu-item"
|
330
|
-
onClick={_onBindWallet}
|
331
|
-
data-cy="sessionManager-bind-trigger">
|
332
|
-
<SvgIcon component={BindWalletIcon} className="session-manager-menu-icon" />
|
333
|
-
{isRawWalletAccount
|
334
|
-
? `${translation.bind}${translation.thirdParty}`
|
335
|
-
: `${translation.bind}DID Wallet`}
|
336
|
-
</MenuItem>
|
337
|
-
)}
|
338
209
|
|
210
|
+
<UserPopper open={userOpen} onClose={onCloseUser} anchorEl={userAnchorRef.current} dark={dark}>
|
211
|
+
<MenuList sx={{ p: 0 }}>
|
212
|
+
<div className="session-manager-user">
|
213
|
+
<div className="session-manager-user-name">
|
214
|
+
<span>{session.user.fullName}</span>
|
215
|
+
{!!showRole && (currentRole?.title || session.user?.role.toUpperCase()) && (
|
216
|
+
<Chip
|
217
|
+
label={currentRole?.title || session.user?.role.toUpperCase()}
|
218
|
+
size="small"
|
219
|
+
variant="outlined"
|
220
|
+
sx={{ height: 'auto', marginRight: 0 }}
|
221
|
+
icon={<SvgIcon component={ShieldCheck} size="small" />}
|
222
|
+
/>
|
223
|
+
)}
|
224
|
+
</div>
|
225
|
+
<div className="session-manager-id-list">
|
226
|
+
{walletDid && (
|
227
|
+
<div className="session-manager-id-item">
|
228
|
+
<DidAddress responsive={false}>{walletDid}</DidAddress>
|
229
|
+
</div>
|
230
|
+
)}
|
231
|
+
{session?.user?.email && (
|
232
|
+
<div className="session-manager-id-item">
|
233
|
+
<DidAddress responsive={false}>{session.user.email}</DidAddress>
|
234
|
+
</div>
|
235
|
+
)}
|
236
|
+
</div>
|
237
|
+
</div>
|
238
|
+
{Array.isArray(menu) &&
|
239
|
+
menu.map((menuItem, index) => {
|
240
|
+
const { svgIcon, ...menuProps } = menuItem;
|
241
|
+
return (
|
339
242
|
<MenuItem
|
243
|
+
key={index}
|
340
244
|
className="session-manager-menu-item"
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
245
|
+
{...{
|
246
|
+
...menuProps,
|
247
|
+
icon: undefined,
|
248
|
+
label: undefined,
|
249
|
+
}}>
|
250
|
+
{svgIcon
|
251
|
+
? svgIcon && <SvgIcon component={svgIcon} className="session-manager-menu-icon" />
|
252
|
+
: menuItem.icon}
|
253
|
+
{menuItem.label}
|
346
254
|
</MenuItem>
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
255
|
+
);
|
256
|
+
})}
|
257
|
+
{menuRender({
|
258
|
+
classes: {
|
259
|
+
menuItem: 'session-manager-menu-item',
|
260
|
+
menuIcon: 'session-manager-menu-icon',
|
261
|
+
},
|
262
|
+
})}
|
263
|
+
{!browser.wallet && (
|
264
|
+
<MenuItem
|
265
|
+
component="a"
|
266
|
+
className="session-manager-menu-item"
|
267
|
+
data-cy="sessionManager-openInWallet"
|
268
|
+
href="https://www.abtwallet.io/"
|
269
|
+
target="_blank">
|
270
|
+
<SvgIcon component={OpenInIcon} className="session-manager-menu-icon" />
|
271
|
+
{translation.openInWallet}
|
272
|
+
</MenuItem>
|
273
|
+
)}
|
274
|
+
{!!switchDid && (
|
275
|
+
<MenuItem
|
276
|
+
className="session-manager-menu-item"
|
277
|
+
onClick={_onSwitchDid}
|
278
|
+
data-cy="sessionManager-switch-trigger">
|
279
|
+
<SvgIcon component={SwitchDidIcon} className="session-manager-menu-icon" />
|
280
|
+
{translation.switchDid}
|
281
|
+
</MenuItem>
|
282
|
+
)}
|
283
|
+
{/* NOTE: federated 登录方式不允许切换 profile */}
|
284
|
+
{!!switchProfile && hasBindWallet && session.provider !== 'federated' && (
|
285
|
+
<MenuItem
|
286
|
+
className="session-manager-menu-item"
|
287
|
+
onClick={_onSwitchProfile}
|
288
|
+
data-cy="sessionManager-switch-profile-trigger">
|
289
|
+
<SvgIcon component={SwitchProfileIcon} className="session-manager-menu-icon" />
|
290
|
+
{translation.switchProfile}
|
291
|
+
</MenuItem>
|
292
|
+
)}
|
293
|
+
{!!switchPassport && (
|
294
|
+
<MenuItem
|
295
|
+
className="session-manager-menu-item"
|
296
|
+
onClick={_onSwitchPassport}
|
297
|
+
data-cy="sessionManager-switch-passport-trigger">
|
298
|
+
<SvgIcon component={SwitchPassportIcon} className="session-manager-menu-icon" />
|
299
|
+
{translation.switchPassport}
|
300
|
+
</MenuItem>
|
301
|
+
)}
|
302
|
+
{oauthConfigList.length > 0 && !hasBindAccount && session.provider !== 'federated' && (
|
303
|
+
<MenuItem
|
304
|
+
className="session-manager-menu-item"
|
305
|
+
onClick={_onBindWallet}
|
306
|
+
data-cy="sessionManager-bind-trigger">
|
307
|
+
<SvgIcon component={BindWalletIcon} className="session-manager-menu-icon" />
|
308
|
+
{isRawWalletAccount ? `${translation.bind}${translation.thirdParty}` : `${translation.bind}DID Wallet`}
|
309
|
+
</MenuItem>
|
310
|
+
)}
|
311
|
+
|
312
|
+
<MenuItem
|
313
|
+
className="session-manager-menu-item"
|
314
|
+
onClick={_onLogout}
|
315
|
+
disabled={disableLogout}
|
316
|
+
data-cy="sessionManager-logout-trigger">
|
317
|
+
<SvgIcon component={DisconnectIcon} className="session-manager-menu-icon" />
|
318
|
+
{translation.disconnect}
|
319
|
+
</MenuItem>
|
320
|
+
</MenuList>
|
321
|
+
</UserPopper>
|
352
322
|
</>
|
353
323
|
);
|
354
324
|
}
|
355
325
|
|
356
326
|
SessionManager.propTypes = {
|
357
327
|
session: PropTypes.shape({
|
328
|
+
federatedMaster: PropTypes.object,
|
329
|
+
provider: PropTypes.oneOf(['wallet', 'federated', 'auth0']),
|
358
330
|
user: PropTypes.shape({
|
359
331
|
did: PropTypes.string.isRequired,
|
360
332
|
role: PropTypes.string.isRequired,
|
@@ -427,69 +399,4 @@ SessionManager.defaultProps = {
|
|
427
399
|
size: 24,
|
428
400
|
};
|
429
401
|
|
430
|
-
const StyledPopper = styled(Popper)`
|
431
|
-
z-index: ${({ theme }) => theme.zIndex.tooltip};
|
432
|
-
.MuiList-root {
|
433
|
-
/* HACK: 需要288px 才能将 did 展示完整 */
|
434
|
-
width: 290px;
|
435
|
-
}
|
436
|
-
.session-manager-user {
|
437
|
-
font-size: 12px;
|
438
|
-
flex-direction: column;
|
439
|
-
align-items: flex-start;
|
440
|
-
padding: 24px 24px 10px;
|
441
|
-
}
|
442
|
-
.session-manager-user-name {
|
443
|
-
font-size: 20px;
|
444
|
-
color: ${({ $dark }) => ($dark ? '#aaa' : '#222')};
|
445
|
-
font-weight: bold;
|
446
|
-
margin-bottom: 10px;
|
447
|
-
display: flex;
|
448
|
-
align-items: center;
|
449
|
-
justify-content: space-between;
|
450
|
-
}
|
451
|
-
.session-manager-id-item {
|
452
|
-
position: relative;
|
453
|
-
padding-left: 8px;
|
454
|
-
/* HACK: 当前元素既是第一个,也是最后一个,即只有一个同级元素 */
|
455
|
-
&:first-of-type:last-of-type {
|
456
|
-
padding-left: 0;
|
457
|
-
&:before,
|
458
|
-
&:after {
|
459
|
-
content: unset;
|
460
|
-
}
|
461
|
-
}
|
462
|
-
&:before {
|
463
|
-
position: absolute;
|
464
|
-
content: '';
|
465
|
-
left: 0px;
|
466
|
-
top: 50%;
|
467
|
-
width: 6px;
|
468
|
-
height: 1px;
|
469
|
-
background-color: #aeaeae;
|
470
|
-
}
|
471
|
-
&:not(:last-of-type):after {
|
472
|
-
position: absolute;
|
473
|
-
content: '';
|
474
|
-
left: 0px;
|
475
|
-
top: 50%;
|
476
|
-
height: 100%;
|
477
|
-
width: 1px;
|
478
|
-
background-color: #aeaeae;
|
479
|
-
}
|
480
|
-
}
|
481
|
-
.session-manager-menu-item {
|
482
|
-
padding: 18.5px 24px;
|
483
|
-
color: #777;
|
484
|
-
font-size: 16px;
|
485
|
-
&:hover {
|
486
|
-
background-color: #fbfbfb;
|
487
|
-
}
|
488
|
-
}
|
489
|
-
.session-manager-menu-icon {
|
490
|
-
color: #999;
|
491
|
-
margin-right: 16px;
|
492
|
-
}
|
493
|
-
`;
|
494
|
-
|
495
402
|
export default SessionManager;
|
@@ -0,0 +1,121 @@
|
|
1
|
+
import PropTypes from 'prop-types';
|
2
|
+
import { ClickAwayListener, Paper, Popper } from '@mui/material';
|
3
|
+
import { styled } from '../Theme';
|
4
|
+
|
5
|
+
export default function UserPopper({ anchorEl, dark, children, open, onClose }) {
|
6
|
+
return (
|
7
|
+
anchorEl && (
|
8
|
+
<StyledPopper open={open} disablePortal anchorEl={anchorEl} placement="bottom-end" $dark={dark}>
|
9
|
+
<Paper
|
10
|
+
sx={[
|
11
|
+
(theme) => ({
|
12
|
+
borderColor: '#F0F0F0',
|
13
|
+
boxShadow: '0px 8px 12px rgba(92, 92, 92, 0.04)',
|
14
|
+
borderRadius: theme.spacing(2),
|
15
|
+
overflow: 'hidden',
|
16
|
+
maxWidth: 'calc(100vw - 10px)',
|
17
|
+
'& .MuiChip-root .MuiChip-icon': {
|
18
|
+
color: theme.palette.success.main,
|
19
|
+
},
|
20
|
+
}),
|
21
|
+
dark && {
|
22
|
+
backgroundColor: '#27282c',
|
23
|
+
color: '#fff',
|
24
|
+
border: 0,
|
25
|
+
'& .MuiChip-root': {
|
26
|
+
borderColor: '#aaa',
|
27
|
+
},
|
28
|
+
'& .MuiListItem-root, & .MuiChip-label': {
|
29
|
+
color: '#aaa',
|
30
|
+
},
|
31
|
+
'& .MuiListItem-root:hover': {
|
32
|
+
backgroundColor: '#363434',
|
33
|
+
},
|
34
|
+
},
|
35
|
+
]}
|
36
|
+
variant="outlined">
|
37
|
+
<ClickAwayListener onClickAway={onClose}>{children}</ClickAwayListener>
|
38
|
+
</Paper>
|
39
|
+
</StyledPopper>
|
40
|
+
)
|
41
|
+
);
|
42
|
+
}
|
43
|
+
|
44
|
+
UserPopper.propTypes = {
|
45
|
+
anchorEl: PropTypes.instanceOf(Element),
|
46
|
+
dark: PropTypes.bool,
|
47
|
+
open: PropTypes.bool,
|
48
|
+
children: PropTypes.any.isRequired,
|
49
|
+
onClose: PropTypes.func,
|
50
|
+
};
|
51
|
+
UserPopper.defaultProps = {
|
52
|
+
anchorEl: null,
|
53
|
+
dark: false,
|
54
|
+
open: false,
|
55
|
+
onClose: () => {},
|
56
|
+
};
|
57
|
+
|
58
|
+
const StyledPopper = styled(Popper)`
|
59
|
+
z-index: ${({ theme }) => theme.zIndex.tooltip};
|
60
|
+
.MuiList-root {
|
61
|
+
/* HACK: 需要288px 才能将 did 展示完整 */
|
62
|
+
width: 290px;
|
63
|
+
}
|
64
|
+
.session-manager-user {
|
65
|
+
font-size: 12px;
|
66
|
+
flex-direction: column;
|
67
|
+
align-items: flex-start;
|
68
|
+
padding: 24px 24px 10px;
|
69
|
+
}
|
70
|
+
.session-manager-user-name {
|
71
|
+
font-size: 20px;
|
72
|
+
color: ${({ $dark }) => ($dark ? '#aaa' : '#222')};
|
73
|
+
font-weight: bold;
|
74
|
+
margin-bottom: 10px;
|
75
|
+
display: flex;
|
76
|
+
align-items: center;
|
77
|
+
justify-content: space-between;
|
78
|
+
}
|
79
|
+
.session-manager-id-item {
|
80
|
+
position: relative;
|
81
|
+
padding-left: 8px;
|
82
|
+
/* HACK: 当前元素既是第一个,也是最后一个,即只有一个同级元素 */
|
83
|
+
&:first-of-type:last-of-type {
|
84
|
+
padding-left: 0;
|
85
|
+
&:before,
|
86
|
+
&:after {
|
87
|
+
content: unset;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
&:before {
|
91
|
+
position: absolute;
|
92
|
+
content: '';
|
93
|
+
left: 0px;
|
94
|
+
top: 50%;
|
95
|
+
width: 6px;
|
96
|
+
height: 1px;
|
97
|
+
background-color: #aeaeae;
|
98
|
+
}
|
99
|
+
&:not(:last-of-type):after {
|
100
|
+
position: absolute;
|
101
|
+
content: '';
|
102
|
+
left: 0px;
|
103
|
+
top: 50%;
|
104
|
+
height: 100%;
|
105
|
+
width: 1px;
|
106
|
+
background-color: #aeaeae;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
.session-manager-menu-item {
|
110
|
+
padding: 18.5px 24px;
|
111
|
+
color: #777;
|
112
|
+
font-size: 16px;
|
113
|
+
&:hover {
|
114
|
+
background-color: #fbfbfb;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
.session-manager-menu-icon {
|
118
|
+
color: #999;
|
119
|
+
margin-right: 16px;
|
120
|
+
}
|
121
|
+
`;
|