@arcblock/ux 2.7.14 → 2.7.16

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.
Files changed (55) hide show
  1. package/es/Dialog/confirm.js +10 -8
  2. package/es/Img/index.js +7 -7
  3. package/es/Locale/selector.js +9 -9
  4. package/es/SessionManager/account-item.js +132 -0
  5. package/es/SessionManager/add-account-item.js +118 -0
  6. package/es/SessionManager/federated-login-detecter.js +15 -9
  7. package/es/SessionManager/index.js +122 -224
  8. package/es/SessionManager/manage-accounts.js +143 -0
  9. package/es/SessionManager/manage-blocklet.js +62 -0
  10. package/es/SessionManager/menu-accordion.js +95 -0
  11. package/es/SessionManager/translation.js +52 -0
  12. package/es/SessionManager/use-accounts.js +19 -0
  13. package/es/SessionManager/user-info.js +139 -0
  14. package/es/SessionManager/user-popper.js +13 -37
  15. package/es/SessionManager/utils.js +2 -0
  16. package/es/Util/index.js +7 -0
  17. package/lib/Dialog/confirm.js +9 -7
  18. package/lib/Img/index.js +7 -7
  19. package/lib/Locale/selector.js +16 -17
  20. package/lib/SessionManager/account-item.js +140 -0
  21. package/lib/SessionManager/add-account-item.js +126 -0
  22. package/lib/SessionManager/federated-login-detecter.js +15 -9
  23. package/lib/SessionManager/index.js +125 -237
  24. package/lib/SessionManager/manage-accounts.js +155 -0
  25. package/lib/SessionManager/manage-blocklet.js +78 -0
  26. package/lib/SessionManager/menu-accordion.js +103 -0
  27. package/lib/SessionManager/translation.js +59 -0
  28. package/lib/SessionManager/use-accounts.js +25 -0
  29. package/lib/SessionManager/user-info.js +155 -0
  30. package/lib/SessionManager/user-popper.js +8 -3
  31. package/lib/SessionManager/utils.js +16 -0
  32. package/lib/Util/index.js +11 -2
  33. package/package.json +8 -5
  34. package/src/Dialog/confirm.js +9 -6
  35. package/src/Img/index.js +5 -5
  36. package/src/Locale/{selector.js → selector.jsx} +9 -10
  37. package/src/SessionManager/account-item.jsx +111 -0
  38. package/src/SessionManager/add-account-item.jsx +115 -0
  39. package/src/SessionManager/federated-login-detecter.jsx +14 -12
  40. package/src/SessionManager/index.jsx +135 -214
  41. package/src/SessionManager/manage-accounts.jsx +143 -0
  42. package/src/SessionManager/manage-blocklet.jsx +64 -0
  43. package/src/SessionManager/menu-accordion.jsx +87 -0
  44. package/src/SessionManager/translation.js +52 -0
  45. package/src/SessionManager/use-accounts.js +18 -0
  46. package/src/SessionManager/user-info.jsx +116 -0
  47. package/src/SessionManager/user-popper.jsx +9 -37
  48. package/src/SessionManager/utils.js +3 -0
  49. package/src/Util/index.js +8 -0
  50. /package/src/Avatar/{did-motif.js → did-motif.jsx} +0 -0
  51. /package/src/Avatar/{index.js → index.jsx} +0 -0
  52. /package/src/Header/{auto-hidden.js → auto-hidden.jsx} +0 -0
  53. /package/src/Header/{header.js → header.jsx} +0 -0
  54. /package/src/Header/{responsive-header.js → responsive-header.jsx} +0 -0
  55. /package/src/Locale/{context.js → context.jsx} +0 -0
@@ -0,0 +1,87 @@
1
+ import PropTypes from 'prop-types';
2
+ import { Accordion, AccordionDetails, AccordionSummary, MenuItem } from '@mui/material';
3
+ import ExpandMoreIcon from '@iconify-icons/mdi/expand-more';
4
+ import { Icon } from '@iconify/react';
5
+ import isEmpty from 'lodash/isEmpty';
6
+ import isNil from 'lodash/isNil';
7
+ import { useCreation, useMemoizedFn } from 'ahooks';
8
+ import { translate } from '../Locale/util';
9
+ import { translations } from './translation';
10
+
11
+ function isEmptyNode(node) {
12
+ if (isNil(node)) {
13
+ return true;
14
+ }
15
+ if (isEmpty(node)) {
16
+ return true;
17
+ }
18
+ if (Array.isArray(node)) {
19
+ return node.every((item) => isEmptyNode(item));
20
+ }
21
+ return false;
22
+ }
23
+
24
+ export default function MenuAccordion({ title, children, locale }) {
25
+ const isEmptyChildren = useCreation(() => isEmptyNode(children), [children]);
26
+ const t = useMemoizedFn((key, data = {}) => {
27
+ return translate(translations, key, locale, 'en', data);
28
+ });
29
+
30
+ return (
31
+ <Accordion
32
+ defaultExpanded
33
+ disableGutters
34
+ elevation={0}
35
+ sx={{
36
+ '&.MuiAccordion-root:before': {
37
+ content: 'unset',
38
+ },
39
+ '.MuiAccordionSummary-root': {
40
+ minHeight: 'auto',
41
+ width: '100%',
42
+ },
43
+ '.MuiAccordionSummary-content': {
44
+ margin: 0,
45
+ },
46
+ '.MuiAccordionDetails-root': {
47
+ padding: 0,
48
+ paddingLeft: '30px',
49
+ '.session-manager-menu-item': {
50
+ fontSize: '15px',
51
+ padding: '12px 20px',
52
+ whiteSpace: 'normal',
53
+ },
54
+ '.session-manager-menu-icon': {
55
+ height: '21px',
56
+ widht: '21px',
57
+ },
58
+ },
59
+ }}>
60
+ <MenuItem sx={{ padding: 0, width: '100%' }}>
61
+ <AccordionSummary
62
+ className="session-manager-menu-item"
63
+ expandIcon={<Icon icon={ExpandMoreIcon} width={24} height={24} />}>
64
+ {title}
65
+ </AccordionSummary>
66
+ </MenuItem>
67
+ <AccordionDetails>
68
+ {isEmptyChildren ? (
69
+ <MenuItem disabled key="empty" className="session-manager-menu-item" sx={{ justifyContent: 'center' }}>
70
+ {t('noneMenu')}
71
+ </MenuItem>
72
+ ) : (
73
+ children
74
+ )}
75
+ </AccordionDetails>
76
+ </Accordion>
77
+ );
78
+ }
79
+
80
+ MenuAccordion.propTypes = {
81
+ title: PropTypes.any.isRequired,
82
+ children: PropTypes.any.isRequired,
83
+ locale: PropTypes.string,
84
+ };
85
+ MenuAccordion.defaultProps = {
86
+ locale: 'en',
87
+ };
@@ -0,0 +1,52 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ export const translations = {
3
+ en: {
4
+ edit: 'Edit',
5
+ account: 'account',
6
+ switchDid: 'Switch DID',
7
+ switchTo: 'Switch to',
8
+ switchProfile: 'Switch Profile',
9
+ switchPassport: 'Switch Passport',
10
+ disconnect: 'Disconnect',
11
+ connect: 'Connect',
12
+ openInWallet: 'Open DID Wallet',
13
+ alreadyBindOAuth: 'Already bind Auth0',
14
+ bind: 'Bind ',
15
+ thirdParty: 'Third Party Login',
16
+ connectedWith: 'Connected with',
17
+ manageAccounts: 'Manage Accounts',
18
+ manageBlocklet: 'Manage Blocklet',
19
+ from: 'From',
20
+ addAnotherAccount: 'Add another account',
21
+ deleteAccountTitle: 'Remove this account ?',
22
+ deleteAccountContent: 'After delete account, you can add it agian',
23
+ confirm: 'Confirm',
24
+ cancel: 'Cancel',
25
+ noneMenu: 'Empty menu, maybe you should switch to another role',
26
+ },
27
+ zh: {
28
+ edit: '编辑',
29
+ account: '账号',
30
+ switchDid: '切换账户',
31
+ switchTo: '切换至',
32
+ switchProfile: '切换用户信息',
33
+ switchPassport: '切换通行证',
34
+ disconnect: '退出',
35
+ connect: '登录',
36
+ openInWallet: '打开 DID 钱包',
37
+ // NOTE: 目前只有 Auth0,展示出具体的第三方名字会更好
38
+ alreadyBindOAuth: '已绑定 Auth0 账号',
39
+ bind: '绑定',
40
+ thirdParty: '第三方登录',
41
+ connectedWith: '连接至',
42
+ manageAccounts: '管理账户',
43
+ manageBlocklet: '管理应用',
44
+ from: '连接至',
45
+ addAnotherAccount: '添加一个账号',
46
+ deleteAccountTitle: '是否删除账户?',
47
+ deleteAccountContent: '账户删除后,可再次添加',
48
+ confirm: '确认',
49
+ cancel: '取消',
50
+ noneMenu: '无操作项,请尝试切换角色',
51
+ },
52
+ };
@@ -0,0 +1,18 @@
1
+ import { useLocalStorageState, useMemoizedFn } from 'ahooks';
2
+
3
+ export default function useAccounts() {
4
+ const [accounts, setAccounts] = useLocalStorageState('blocklet:sessionManager:accounts', {
5
+ defaultValue: [],
6
+ });
7
+
8
+ const connectAccount = useMemoizedFn((account) => {
9
+ const accountIndex = accounts.findIndex((x) => x.did === account.did);
10
+ if (accountIndex >= 0) {
11
+ accounts.splice(accountIndex, 1);
12
+ }
13
+ accounts.unshift(account);
14
+ setAccounts(accounts);
15
+ });
16
+
17
+ return { accounts, setAccounts, connectAccount };
18
+ }
@@ -0,0 +1,116 @@
1
+ /* eslint-disable react/jsx-no-bind */
2
+ /* eslint-disable react/prop-types */
3
+ import { Box, Chip, Typography } from '@mui/material';
4
+ import ShieldCheckIcon from '@iconify-icons/mdi/shield-check';
5
+ import ExpandMoreIcon from '@iconify-icons/mdi/expand-more';
6
+ import { Icon } from '@iconify/react';
7
+ import { useCreation, useMemoizedFn } from 'ahooks';
8
+
9
+ import DidAvatar from '../Avatar';
10
+ import DidAddress from '../Address';
11
+ import DID from '../DID';
12
+ import { getUserAvatar } from '../Util';
13
+ import { t as translate } from '../Locale/util';
14
+ import { translations } from './translation';
15
+
16
+ export default function UserInfo({ session, locale, onEditUser, onSwitchPassport, switchProfile, hasBindWallet }) {
17
+ const t = (key, data = {}) => {
18
+ return translate(translations, key, locale, 'en', data);
19
+ };
20
+ const avatar = getUserAvatar(session.user?.avatar?.replace(/\s/g, encodeURIComponent(' ')));
21
+ const { walletDid } = session.useDid({ session });
22
+ const currentRole = useCreation(
23
+ () => session.user?.passports?.find((item) => item.name === session.user.role),
24
+ [session?.user?.passports, session?.user?.role]
25
+ );
26
+ const userEmail = useCreation(() => session.user?.email || 'lancelot_lewis@163.com', [session?.user]);
27
+
28
+ const canEdit = useCreation(() => {
29
+ if (onEditUser instanceof Function) {
30
+ if (switchProfile && hasBindWallet && session.provider !== 'federated') {
31
+ return true;
32
+ }
33
+ }
34
+ return false;
35
+ }, [onEditUser, switchProfile, hasBindWallet, session.provider]);
36
+
37
+ const _onEditUser = useMemoizedFn(() => {
38
+ if (canEdit) {
39
+ onEditUser();
40
+ }
41
+ });
42
+
43
+ return (
44
+ <Box
45
+ sx={{
46
+ display: 'flex',
47
+ alignItems: 'center',
48
+ gap: '16px',
49
+ padding: '15px 20px',
50
+ }}>
51
+ <Box
52
+ onClick={_onEditUser}
53
+ data-cy="sessionManager-switch-profile-trigger"
54
+ sx={{
55
+ cursor: canEdit ? 'pointer' : 'default',
56
+ position: 'relative',
57
+ borderRadius: '100%',
58
+ overflow: 'hidden',
59
+ fontSize: 0,
60
+ '&:hover': canEdit
61
+ ? {
62
+ '&::after': {
63
+ content: `"${t('edit')}"`,
64
+ position: 'absolute',
65
+ bottom: 0,
66
+ background: 'rgba(0, 0, 0, 0.2)',
67
+ left: 0,
68
+ right: 0,
69
+ height: '2.2em',
70
+ color: 'white',
71
+ textAlign: 'center',
72
+ fontSize: '12px',
73
+ lineHeight: '2em',
74
+ },
75
+ }
76
+ : {},
77
+ }}>
78
+ <DidAvatar variant="circle" did={session.user.did} src={avatar} size={64} shape="circle" />
79
+ </Box>
80
+ <Box sx={{ flex: 1, position: 'static', overflow: 'hidden', fontSize: '14px' }}>
81
+ <Typography variant="h5" fontWeight="bold" mb={1}>
82
+ {session.user.fullName}
83
+ </Typography>
84
+ {/* eslint-disable-next-line no-nested-ternary */}
85
+ {session.provider === 'auth0' ? (
86
+ walletDid ? (
87
+ <DID responsive={false} compact did={walletDid} />
88
+ ) : null
89
+ ) : (
90
+ <DID responsive={false} compact did={session.user.did} />
91
+ )}
92
+ {userEmail ? <DidAddress responsive={false}>{userEmail}</DidAddress> : null}
93
+ <Chip
94
+ label={currentRole?.title || session.user?.role.toUpperCase()}
95
+ size="small"
96
+ variant="outlined"
97
+ sx={{
98
+ height: 'auto',
99
+ marginRight: 0,
100
+ position: 'absolute',
101
+ top: 20,
102
+ right: 15,
103
+ fontWeight: 'bold',
104
+ fontSize: '12px',
105
+ }}
106
+ icon={<Icon icon={ShieldCheckIcon} height="0.8em" />}
107
+ deleteIcon={<Icon icon={ExpandMoreIcon} height="1em" />}
108
+ // HACK: 必须设置 onDelete 函数,deleteIcon 才能显示出来
109
+ onDelete={onSwitchPassport}
110
+ onClick={onSwitchPassport}
111
+ data-cy="sessionManager-switch-passport-trigger"
112
+ />
113
+ </Box>
114
+ </Box>
115
+ );
116
+ }
@@ -1,6 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import { IconButton, Paper, Popper, ClickAwayListener } from '@mui/material';
3
- import { Close as CloseIcon } from '@mui/icons-material';
3
+ import CloseIcon from '@iconify-icons/mdi/close';
4
+ import { Icon } from '@iconify/react';
4
5
  import { styled } from '../Theme';
5
6
 
6
7
  export default function UserPopper({ anchorEl, dark, children, open, onClose, autoClose }) {
@@ -43,7 +44,7 @@ export default function UserPopper({ anchorEl, dark, children, open, onClose, au
43
44
  size="small"
44
45
  sx={{ cursor: 'pointer', position: 'absolute', right: 0, top: 0, zIndex: 1 }}
45
46
  onClick={onClose}>
46
- <CloseIcon />
47
+ <Icon icon={CloseIcon} width={20} height={20} />
47
48
  </IconButton>
48
49
  {children}
49
50
  </>
@@ -71,10 +72,11 @@ UserPopper.defaultProps = {
71
72
  };
72
73
 
73
74
  const StyledPopper = styled(Popper)`
74
- z-index: ${({ theme }) => theme.zIndex.tooltip};
75
+ z-index: ${({ theme }) => {
76
+ return theme.zIndex.tooltip;
77
+ }};
75
78
  .MuiList-root {
76
- /* HACK: 需要288px 才能将 did 展示完整 */
77
- width: 290px;
79
+ width: 320px;
78
80
  }
79
81
  .session-manager-user {
80
82
  font-size: 12px;
@@ -91,38 +93,8 @@ const StyledPopper = styled(Popper)`
91
93
  align-items: center;
92
94
  justify-content: space-between;
93
95
  }
94
- .session-manager-id-item {
95
- position: relative;
96
- padding-left: 8px;
97
- /* HACK: 当前元素既是第一个,也是最后一个,即只有一个同级元素 */
98
- &:first-of-type:last-of-type {
99
- padding-left: 0;
100
- &:before,
101
- &:after {
102
- content: unset;
103
- }
104
- }
105
- &:before {
106
- position: absolute;
107
- content: '';
108
- left: 0px;
109
- top: 50%;
110
- width: 6px;
111
- height: 1px;
112
- background-color: #aeaeae;
113
- }
114
- &:not(:last-of-type):after {
115
- position: absolute;
116
- content: '';
117
- left: 0px;
118
- top: 50%;
119
- height: 100%;
120
- width: 1px;
121
- background-color: #aeaeae;
122
- }
123
- }
124
96
  .session-manager-menu-item {
125
- padding: 18.5px 24px;
97
+ padding: 18px 20px;
126
98
  color: #777;
127
99
  font-size: 16px;
128
100
  &:hover {
@@ -131,6 +103,6 @@ const StyledPopper = styled(Popper)`
131
103
  }
132
104
  .session-manager-menu-icon {
133
105
  color: #999;
134
- margin-right: 16px;
106
+ margin-right: 8px;
135
107
  }
136
108
  `;
@@ -0,0 +1,3 @@
1
+ export const getSourceProvider = (user) => user?.sourceProvider || user?.extraConfigs?.sourceProvider || 'wallet';
2
+
3
+ export const getConnectedAccounts = (user) => user?.connectedAccounts || user?.extraConfigs?.connectedAccounts || [];
package/src/Util/index.js CHANGED
@@ -324,3 +324,11 @@ export const getUserAvatar = (avatar, size = 48) => {
324
324
 
325
325
  return avatar;
326
326
  };
327
+
328
+ export const sleep = (time = 0) => {
329
+ return new Promise((resolve) => {
330
+ setTimeout(() => {
331
+ resolve();
332
+ }, time);
333
+ });
334
+ };
File without changes
File without changes
File without changes
File without changes
File without changes