@arcblock/ux 2.7.15 → 2.7.17

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 (57) hide show
  1. package/es/Dialog/confirm.js +10 -8
  2. package/es/Img/index.js +7 -7
  3. package/es/SessionManager/account-item.js +133 -0
  4. package/es/SessionManager/add-account-item.js +100 -0
  5. package/es/SessionManager/federated-login-detecter.js +37 -33
  6. package/es/SessionManager/index.js +119 -259
  7. package/es/SessionManager/manage-accounts.js +156 -0
  8. package/es/SessionManager/manage-blocklet.js +70 -0
  9. package/es/SessionManager/menu-accordion.js +104 -0
  10. package/es/SessionManager/translation.js +52 -0
  11. package/es/SessionManager/use-config.js +34 -0
  12. package/es/SessionManager/user-info.js +147 -0
  13. package/es/SessionManager/user-popper.js +10 -53
  14. package/es/SessionManager/utils.js +2 -0
  15. package/es/Typography/index.js +89 -0
  16. package/es/Util/federated.js +65 -0
  17. package/es/Util/index.js +7 -0
  18. package/lib/Dialog/confirm.js +9 -7
  19. package/lib/Img/index.js +7 -7
  20. package/lib/SessionManager/account-item.js +141 -0
  21. package/lib/SessionManager/add-account-item.js +108 -0
  22. package/lib/SessionManager/federated-login-detecter.js +38 -33
  23. package/lib/SessionManager/index.js +122 -272
  24. package/lib/SessionManager/manage-accounts.js +168 -0
  25. package/lib/SessionManager/manage-blocklet.js +86 -0
  26. package/lib/SessionManager/menu-accordion.js +112 -0
  27. package/lib/SessionManager/translation.js +59 -0
  28. package/lib/SessionManager/use-config.js +41 -0
  29. package/lib/SessionManager/user-info.js +163 -0
  30. package/lib/SessionManager/user-popper.js +8 -8
  31. package/lib/SessionManager/utils.js +16 -0
  32. package/lib/Typography/index.js +100 -0
  33. package/lib/Util/federated.js +85 -0
  34. package/lib/Util/index.js +11 -2
  35. package/package.json +12 -5
  36. package/src/Dialog/confirm.js +9 -6
  37. package/src/Img/index.js +5 -5
  38. package/src/SessionManager/account-item.jsx +109 -0
  39. package/src/SessionManager/add-account-item.jsx +97 -0
  40. package/src/SessionManager/federated-login-detecter.jsx +42 -29
  41. package/src/SessionManager/index.jsx +131 -259
  42. package/src/SessionManager/manage-accounts.jsx +157 -0
  43. package/src/SessionManager/manage-blocklet.jsx +70 -0
  44. package/src/SessionManager/menu-accordion.jsx +94 -0
  45. package/src/SessionManager/translation.js +52 -0
  46. package/src/SessionManager/use-config.js +33 -0
  47. package/src/SessionManager/user-info.jsx +116 -0
  48. package/src/SessionManager/user-popper.jsx +6 -51
  49. package/src/SessionManager/utils.js +3 -0
  50. package/src/Typography/index.jsx +79 -0
  51. package/src/Util/federated.js +73 -0
  52. package/src/Util/index.js +8 -0
  53. /package/src/Avatar/{did-motif.js → did-motif.jsx} +0 -0
  54. /package/src/Avatar/{index.js → index.jsx} +0 -0
  55. /package/src/Header/{auto-hidden.js → auto-hidden.jsx} +0 -0
  56. /package/src/Header/{header.js → header.jsx} +0 -0
  57. /package/src/Header/{responsive-header.js → responsive-header.jsx} +0 -0
@@ -1,8 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
- import { useContext, forwardRef, useRef, useImperativeHandle } from 'react';
2
+ import { forwardRef, useRef, useImperativeHandle } from 'react';
3
3
  import { useMemoizedFn, useReactive } from 'ahooks';
4
4
  import noop from 'lodash/noop';
5
- import { LocaleContext } from '../Locale/context';
6
5
  import Button from '../Button';
7
6
  import Dialog from './dialog';
8
7
 
@@ -93,16 +92,15 @@ Confirm.defaultProps = {
93
92
  PaperProps: {}
94
93
  };
95
94
  const ConfirmHolder = /*#__PURE__*/forwardRef((props, ref) => {
96
- const {
97
- t
98
- } = useContext(LocaleContext);
99
95
  const state = useReactive({
100
96
  show: false,
101
97
  title: '',
102
98
  content: '',
103
99
  onConfirm: noop,
104
100
  onCancel: noop,
105
- loading: false
101
+ loading: false,
102
+ confirmButtonText: 'Confirm',
103
+ cancelButtonText: 'Cancel'
106
104
  });
107
105
  const open = useMemoizedFn((params = {}) => {
108
106
  state.show = true;
@@ -110,6 +108,8 @@ const ConfirmHolder = /*#__PURE__*/forwardRef((props, ref) => {
110
108
  state.content = params.content;
111
109
  state.onConfirm = params.onConfirm || noop;
112
110
  state.onCancel = params.onCancel || noop;
111
+ if (params.confirmButtonText) state.confirmButtonText = params.confirmButtonText;
112
+ if (params.cancelButtonText) state.cancelButtonText = params.cancelButtonText;
113
113
  state.loading = false;
114
114
  });
115
115
  const reset = useMemoizedFn(() => {
@@ -117,6 +117,8 @@ const ConfirmHolder = /*#__PURE__*/forwardRef((props, ref) => {
117
117
  state.content = '';
118
118
  state.onConfirm = noop;
119
119
  state.onCancel = noop;
120
+ state.confirmButtonText = 'Confirm';
121
+ state.cancelButtonText = 'Cancel';
120
122
  });
121
123
  const close = useMemoizedFn(() => {
122
124
  state.show = false;
@@ -148,7 +150,7 @@ const ConfirmHolder = /*#__PURE__*/forwardRef((props, ref) => {
148
150
  onConfirm: onConfirm,
149
151
  onCancel: onCancel,
150
152
  confirmButton: {
151
- text: t('common.confirm'),
153
+ text: state.confirmButtonText,
152
154
  props: {
153
155
  variant: 'contained',
154
156
  color: 'primary',
@@ -156,7 +158,7 @@ const ConfirmHolder = /*#__PURE__*/forwardRef((props, ref) => {
156
158
  }
157
159
  },
158
160
  cancelButton: {
159
- text: t('common.cancel'),
161
+ text: state.cancelButtonText,
160
162
  props: {
161
163
  variant: 'outlined',
162
164
  color: 'primary'
package/es/Img/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { useEffect, useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import SvgIcon from '@mui/material/SvgIcon';
4
3
  import { useInView } from 'react-intersection-observer';
5
- import Alert from 'mdi-material-ui/Alert';
6
- import ImageIcon from 'mdi-material-ui/Image';
4
+ import AlertIcon from '@iconify-icons/mdi/alert';
5
+ import ImageIcon from '@iconify-icons/mdi/image';
6
+ import { Icon } from '@iconify/react';
7
7
  import { styled } from '../Theme';
8
8
 
9
9
  /**
@@ -161,15 +161,15 @@ function Img({
161
161
  children: [!fallback && imgState === 'error' && /*#__PURE__*/_jsx("div", {
162
162
  className: "image--state",
163
163
  title: "loading image",
164
- children: /*#__PURE__*/_jsx(SvgIcon, {
165
- component: Alert,
164
+ children: /*#__PURE__*/_jsx(Icon, {
165
+ icon: AlertIcon,
166
166
  className: "image--icon"
167
167
  })
168
168
  }), !placeholder && imgState === 'loading' && /*#__PURE__*/_jsx("div", {
169
169
  className: "image--state",
170
170
  title: "Image load error",
171
- children: /*#__PURE__*/_jsx(SvgIcon, {
172
- component: ImageIcon,
171
+ children: /*#__PURE__*/_jsx(Icon, {
172
+ icon: ImageIcon,
173
173
  className: "image--icon"
174
174
  })
175
175
  }), imgState === 'loaded' && /*#__PURE__*/_jsx("img", {
@@ -0,0 +1,133 @@
1
+ import { Box, IconButton, Link, MenuItem, Typography } from '@mui/material';
2
+ import PropTypes from 'prop-types';
3
+ import { Icon } from '@iconify/react';
4
+ import CheckIcon from '@iconify-icons/mdi/check';
5
+ import TrashCanOutlineIcon from '@iconify-icons/mdi/trash-can-outline';
6
+ import { useMemoizedFn } from 'ahooks';
7
+ import Avatar from '../Avatar';
8
+ import DID from '../DID';
9
+ import { translate } from '../Locale/util';
10
+ import { translations } from './translation';
11
+ import { jsx as _jsx } from "react/jsx-runtime";
12
+ import { jsxs as _jsxs } from "react/jsx-runtime";
13
+ export default function AccountItem({
14
+ account,
15
+ active,
16
+ onDelete,
17
+ onChoose,
18
+ locale
19
+ }) {
20
+ const t = useMemoizedFn((key, data = {}) => {
21
+ return translate(translations, key, locale, 'en', data);
22
+ });
23
+ const _onChoose = useMemoizedFn(() => onChoose(account, {
24
+ active
25
+ }));
26
+ const _onDelete = useMemoizedFn(e => {
27
+ e.preventDefault();
28
+ e.stopPropagation();
29
+ onDelete(account, {
30
+ active
31
+ });
32
+ });
33
+ if (!account?.did || !account?.appName) {
34
+ return null;
35
+ }
36
+ return /*#__PURE__*/_jsxs(MenuItem, {
37
+ onClick: _onChoose,
38
+ sx: {
39
+ display: 'flex',
40
+ alignItems: 'center',
41
+ overflow: 'hidden',
42
+ gap: '8px',
43
+ position: 'relative',
44
+ '.account-item-actions': {
45
+ position: 'absolute',
46
+ right: 0,
47
+ top: 0,
48
+ bottom: 0,
49
+ marginRight: '12px',
50
+ display: 'flex',
51
+ alignItems: 'center'
52
+ },
53
+ '.account-item-action': {
54
+ alignItems: 'center',
55
+ display: 'none'
56
+ },
57
+ '&:hover .account-item-action': {
58
+ display: 'flex'
59
+ }
60
+ },
61
+ className: "session-manager-menu-item",
62
+ children: [/*#__PURE__*/_jsx(Avatar, {
63
+ did: account.did,
64
+ size: 42
65
+ }), /*#__PURE__*/_jsxs(Box, {
66
+ sx: {
67
+ flex: 1,
68
+ overflow: 'hidden',
69
+ fontSize: 0,
70
+ '.did-address-avatar': {
71
+ display: 'none !important'
72
+ }
73
+ },
74
+ children: [/*#__PURE__*/_jsx(DID, {
75
+ did: account.did,
76
+ copyable: false,
77
+ size: 14,
78
+ responsive: false,
79
+ compact: true,
80
+ sx: {
81
+ lineHeight: 1
82
+ }
83
+ }), account.sourceAppPid && /*#__PURE__*/_jsxs(Typography, {
84
+ variant: "caption",
85
+ children: [t('from'), ' ', /*#__PURE__*/_jsx(Link, {
86
+ href: account.appUrl,
87
+ target: "_blank",
88
+ underline: "none",
89
+ children: account.appName
90
+ })]
91
+ })]
92
+ }), /*#__PURE__*/_jsx(Box, {
93
+ className: "account-item-actions",
94
+ children: active ? /*#__PURE__*/_jsx(Box, {
95
+ className: "account-item-action",
96
+ style: {
97
+ display: 'flex'
98
+ },
99
+ children: /*#__PURE__*/_jsx(IconButton, {
100
+ color: "success",
101
+ children: /*#__PURE__*/_jsx(Icon, {
102
+ icon: CheckIcon,
103
+ color: "success"
104
+ })
105
+ })
106
+ }, "CheckIcon") : /*#__PURE__*/_jsx(Box, {
107
+ className: "account-item-action",
108
+ children: /*#__PURE__*/_jsx(IconButton, {
109
+ color: "error",
110
+ onClick: _onDelete,
111
+ children: /*#__PURE__*/_jsx(Icon, {
112
+ icon: TrashCanOutlineIcon,
113
+ color: "error"
114
+ })
115
+ })
116
+ }, "TrashCanOutlineIcon")
117
+ })]
118
+ });
119
+ }
120
+ AccountItem.propTypes = {
121
+ account: PropTypes.object,
122
+ active: PropTypes.bool,
123
+ locale: PropTypes.string,
124
+ onChoose: PropTypes.func,
125
+ onDelete: PropTypes.func
126
+ };
127
+ AccountItem.defaultProps = {
128
+ account: null,
129
+ active: false,
130
+ locale: 'en',
131
+ onChoose: () => {},
132
+ onDelete: () => {}
133
+ };
@@ -0,0 +1,100 @@
1
+ import { Icon } from '@iconify/react';
2
+ import PropTypes from 'prop-types';
3
+ import { Menu, MenuItem, Typography } from '@mui/material';
4
+ import AddIcon from '@iconify-icons/ion/ios-add-circle-outline';
5
+ import { useCreation, useMemoizedFn, useReactive } from 'ahooks';
6
+ import { useRef } from 'react';
7
+ import { translate } from '../Locale/util';
8
+ import { translations } from './translation';
9
+ import { getCurrentApp, getFederatedApp } from '../Util/federated';
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { jsxs as _jsxs } from "react/jsx-runtime";
12
+ import { Fragment as _Fragment } from "react/jsx-runtime";
13
+ export default function AddAccountItem({
14
+ onAdd,
15
+ locale
16
+ }) {
17
+ const addRef = useRef(null);
18
+ const state = useReactive({
19
+ open: false
20
+ });
21
+ const t = useMemoizedFn((key, data = {}) => {
22
+ return translate(translations, key, locale, 'en', data);
23
+ });
24
+ const apps = useCreation(() => {
25
+ const appList = [];
26
+ if (typeof window === 'undefined') {
27
+ return appList;
28
+ }
29
+ const blocklet = window?.blocklet;
30
+ const masterApp = getFederatedApp(blocklet);
31
+ const currentApp = getCurrentApp(blocklet);
32
+ if (currentApp) {
33
+ appList.push(currentApp);
34
+ }
35
+ if (masterApp && masterApp?.appId !== currentApp?.appId) {
36
+ appList.push(masterApp);
37
+ }
38
+ // NOTICE: masterApp 应该排在前面
39
+ return appList.reverse();
40
+ }, [window.blocklet]);
41
+ const _onAdd = useMemoizedFn(() => {
42
+ if (apps.length <= 1) {
43
+ onAdd(apps[0]);
44
+ } else {
45
+ state.open = true;
46
+ }
47
+ });
48
+ const onClose = useMemoizedFn(() => {
49
+ state.open = false;
50
+ });
51
+ return /*#__PURE__*/_jsxs(_Fragment, {
52
+ children: [/*#__PURE__*/_jsxs(MenuItem, {
53
+ ref: addRef,
54
+ onClick: _onAdd,
55
+ className: "session-manager-menu-item",
56
+ sx: {
57
+ display: 'flex',
58
+ gap: '8px'
59
+ },
60
+ "data-cy": "sessionManager-switch-trigger",
61
+ children: [/*#__PURE__*/_jsx(Icon, {
62
+ icon: AddIcon,
63
+ width: 24,
64
+ height: 24
65
+ }), /*#__PURE__*/_jsx(Typography, {
66
+ children: t('addAnotherAccount')
67
+ })]
68
+ }), addRef.current ? /*#__PURE__*/_jsx(Menu, {
69
+ anchorEl: addRef.current,
70
+ open: state.open,
71
+ onClose: onClose,
72
+ elevation: 0,
73
+ PaperProps: {
74
+ variant: 'outlined'
75
+ },
76
+ anchorOrigin: {
77
+ vertical: 'top',
78
+ horizontal: 'left'
79
+ },
80
+ transformOrigin: {
81
+ vertical: 'top',
82
+ horizontal: 'left'
83
+ },
84
+ children: apps.map(app => /*#__PURE__*/_jsx(MenuItem, {
85
+ onClick: () => onAdd(app),
86
+ children: t('connectWithAccount', {
87
+ name: app.appName
88
+ })
89
+ }, app.appId))
90
+ }) : null]
91
+ });
92
+ }
93
+ AddAccountItem.propTypes = {
94
+ onAdd: PropTypes.func,
95
+ locale: PropTypes.string
96
+ };
97
+ AddAccountItem.defaultProps = {
98
+ onAdd: () => {},
99
+ locale: 'en'
100
+ };
@@ -1,10 +1,11 @@
1
1
  import PropTypes from 'prop-types';
2
- import { useCallback, useState } from 'react';
2
+ import { useCallback } from 'react';
3
3
  import Box from '@mui/material/Box';
4
4
  import Chip from '@mui/material/Chip';
5
5
  import Divider from '@mui/material/Divider';
6
- import SvgIcon from '@mui/material/SvgIcon';
7
- import ShieldCheck from 'mdi-material-ui/ShieldCheck';
6
+ import ShieldCheckIcon from '@iconify-icons/mdi/shield-check';
7
+ import { Icon } from '@iconify/react';
8
+ import { useCreation, useReactive } from 'ahooks';
8
9
  import UserPopper from './user-popper';
9
10
  import DidAvatar from '../Avatar';
10
11
  import DidAddress from '../Address';
@@ -46,9 +47,12 @@ export default function FederatedLoginDetecter({
46
47
  dark,
47
48
  locale: _locale
48
49
  }) {
49
- const [federatedLoginOpen, setFederatedLoginOpen] = useState(true);
50
- const siteInfo = session.federatedMaster?.site;
51
- const userInfo = session.federatedMaster?.user;
50
+ const state = useReactive({
51
+ open: true
52
+ });
53
+ const federatedMaster = useCreation(() => {
54
+ return session.federatedMaster;
55
+ }, [session?.federatedMaster]);
52
56
  const localeList = Object.keys(translations);
53
57
  const locale = localeList.includes(_locale) ? _locale : localeList[0];
54
58
  const onLoginFederated = useCallback(() => {
@@ -56,37 +60,39 @@ export default function FederatedLoginDetecter({
56
60
  if (err) {
57
61
  Toast.error(err || translations[_locale].loginFederatedFailed);
58
62
  } else {
59
- setFederatedLoginOpen(false);
63
+ state.open = false;
60
64
  }
61
65
  }, {
62
- provider: 'federated',
63
- mode: userInfo ? 'auto' : 'manual'
66
+ sourceAppPid: federatedMaster?.site?.appPid,
67
+ mode: federatedMaster?.user ? 'auto' : 'manual'
64
68
  });
65
- }, [session, userInfo, _locale]);
69
+ }, [session, federatedMaster?.site?.appPid, federatedMaster?.user, _locale, state]);
66
70
  let appLogoUrl;
67
- if (siteInfo) {
68
- appLogoUrl = new URL(siteInfo.appLogo, siteInfo.appUrl);
71
+ if (federatedMaster?.site) {
72
+ appLogoUrl = new URL(federatedMaster.site.appLogo, federatedMaster.site.appUrl);
69
73
  appLogoUrl.searchParams.set('imageFilter', 'resize');
70
74
  // HACK: 保持跟其他地方使用的尺寸一致,可以复用同一资源的缓存,减少网络请求
71
75
  appLogoUrl.searchParams.set('w', '80');
72
76
  appLogoUrl.searchParams.set('h', '80');
73
77
  }
74
- return siteInfo && /*#__PURE__*/_jsx(UserPopper, {
75
- open: federatedLoginOpen,
78
+ return federatedMaster?.site && /*#__PURE__*/_jsx(UserPopper, {
79
+ open: state.open,
76
80
  anchorEl: anchorEl,
77
81
  dark: dark,
78
82
  autoClose: false,
79
- onClose: () => setFederatedLoginOpen(false),
83
+ onClose: () => {
84
+ state.open = false;
85
+ },
80
86
  children: /*#__PURE__*/_jsxs(Box, {
81
87
  p: 2,
82
- children: [siteInfo && /*#__PURE__*/_jsxs(Box, {
88
+ children: [federatedMaster.site && /*#__PURE__*/_jsxs(Box, {
83
89
  display: "flex",
84
90
  alignItems: "center",
85
91
  children: [/*#__PURE__*/_jsx(Box, {
86
92
  component: "img",
87
93
  mr: 2,
88
94
  src: appLogoUrl.href,
89
- alt: siteInfo.appName,
95
+ alt: federatedMaster.site.appName,
90
96
  width: "30px",
91
97
  height: "30px"
92
98
  }), /*#__PURE__*/_jsx(Box, {
@@ -96,7 +102,7 @@ export default function FederatedLoginDetecter({
96
102
  children: translations[locale].useToConnect({
97
103
  master: /*#__PURE__*/_jsx(Box, {
98
104
  component: "a",
99
- href: siteInfo.appUrl,
105
+ href: federatedMaster.site.appUrl,
100
106
  target: "_blank",
101
107
  sx: {
102
108
  textDecoration: 'none',
@@ -104,22 +110,22 @@ export default function FederatedLoginDetecter({
104
110
  color: 'primary.main',
105
111
  fontSize: '1.2em'
106
112
  },
107
- children: siteInfo.appName
113
+ children: federatedMaster.site.appName
108
114
  }),
109
115
  member: window.blocklet.appName
110
116
  })
111
117
  })]
112
- }), siteInfo && userInfo && /*#__PURE__*/_jsx(Divider, {
118
+ }), federatedMaster?.site && federatedMaster?.user && /*#__PURE__*/_jsx(Divider, {
113
119
  style: {
114
120
  margin: '15px 0 10px 0'
115
121
  }
116
- }), userInfo && /*#__PURE__*/_jsxs(Box, {
122
+ }), federatedMaster?.user && /*#__PURE__*/_jsxs(Box, {
117
123
  display: "flex",
118
124
  alignItems: "center",
119
125
  children: [/*#__PURE__*/_jsx(DidAvatar, {
120
126
  variant: "circle",
121
- did: userInfo.did,
122
- src: getUserAvatar(userInfo.avatar),
127
+ did: federatedMaster.user.did,
128
+ src: getUserAvatar(federatedMaster.user.avatar),
123
129
  size: 28,
124
130
  shape: "circle"
125
131
  }), /*#__PURE__*/_jsxs(Box, {
@@ -130,9 +136,9 @@ export default function FederatedLoginDetecter({
130
136
  alignItems: "center",
131
137
  children: [/*#__PURE__*/_jsx(Box, {
132
138
  fontSize: 18,
133
- children: userInfo.fullName
134
- }), userInfo.role?.toUpperCase() && /*#__PURE__*/_jsx(Chip, {
135
- label: userInfo.role?.toUpperCase(),
139
+ children: federatedMaster.user.fullName
140
+ }), federatedMaster.user.role?.toUpperCase() && /*#__PURE__*/_jsx(Chip, {
141
+ label: federatedMaster.user.role?.toUpperCase(),
136
142
  size: "small",
137
143
  variant: "outlined",
138
144
  sx: {
@@ -140,19 +146,17 @@ export default function FederatedLoginDetecter({
140
146
  marginRight: 0,
141
147
  fontSize: 12
142
148
  },
143
- icon: /*#__PURE__*/_jsx(SvgIcon, {
144
- component: ShieldCheck,
145
- style: {
146
- fontSize: '14px'
147
- }
149
+ icon: /*#__PURE__*/_jsx(Icon, {
150
+ icon: ShieldCheckIcon,
151
+ fontSize: 14
148
152
  })
149
153
  })]
150
154
  }), /*#__PURE__*/_jsx(DidAddress, {
151
155
  responsive: false,
152
- children: userInfo.did
156
+ children: federatedMaster.user.did
153
157
  })]
154
158
  })]
155
- }), siteInfo && /*#__PURE__*/_jsx(Box, {
159
+ }), federatedMaster?.site && /*#__PURE__*/_jsx(Box, {
156
160
  display: "flex",
157
161
  justifyContent: "center",
158
162
  mt: 2,