@arcblock/ux 2.10.26 → 2.10.28

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.
@@ -5,8 +5,8 @@
5
5
  * title: React.ReactNode,
6
6
  * open: boolean,
7
7
  * children: React.ReactNode,
8
- * onConfirm: () => void | Promise<void>,
9
- * onCancel: () => void | Promise<void>,
8
+ * onConfirm: Function,
9
+ * onCancel: Function,
10
10
  * showCancelButton?: boolean,
11
11
  * showCloseButton?: boolean,
12
12
  * fullScreen?: boolean,
@@ -68,8 +68,8 @@ export type ConfirmProps = {
68
68
  title: React.ReactNode;
69
69
  open: boolean;
70
70
  children: React.ReactNode;
71
- onConfirm: () => void | Promise<void>;
72
- onCancel: () => void | Promise<void>;
71
+ onConfirm: Function;
72
+ onCancel: Function;
73
73
  showCancelButton?: boolean;
74
74
  showCloseButton?: boolean;
75
75
  fullScreen?: boolean;
@@ -11,8 +11,8 @@ import Dialog from './dialog';
11
11
  * title: React.ReactNode,
12
12
  * open: boolean,
13
13
  * children: React.ReactNode,
14
- * onConfirm: () => void | Promise<void>,
15
- * onCancel: () => void | Promise<void>,
14
+ * onConfirm: Function,
15
+ * onCancel: Function,
16
16
  * showCancelButton?: boolean,
17
17
  * showCloseButton?: boolean,
18
18
  * fullScreen?: boolean,
@@ -28,6 +28,12 @@ function Header({
28
28
  minWidth: brandWrapperMinWidth
29
29
  };
30
30
  useEffect(() => {
31
+ const {
32
+ searchParams
33
+ } = new URL(window.location.href);
34
+ if (searchParams.get('inviter')) {
35
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
36
+ }
31
37
  if (logoRef.current) {
32
38
  setBrandWrapperMinWidth(`${logoRef.current.offsetWidth}px`);
33
39
  }
@@ -93,6 +93,14 @@ function Dashboard({
93
93
  homeLink: defaultHomeLink,
94
94
  ...headerProps
95
95
  };
96
+ useEffect(() => {
97
+ const {
98
+ searchParams
99
+ } = new URL(window.location.href);
100
+ if (searchParams.get('inviter')) {
101
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
102
+ }
103
+ }, []);
96
104
  return /*#__PURE__*/_jsxs(Wrapper, {
97
105
  ...rest,
98
106
  className: classes,
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState } from 'react';
2
+ import { useEffect, useState } from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import Helmet from 'react-helmet';
5
5
  import { AppBar, Container, Drawer, Divider, IconButton, Link, List, ListItem, ListItemText, Toolbar, Typography } from '@mui/material';
@@ -29,6 +29,14 @@ export default function Layout({
29
29
  const onToggleDrawer = () => {
30
30
  setDrawerOpen(!drawerOpen);
31
31
  };
32
+ useEffect(() => {
33
+ const {
34
+ searchParams
35
+ } = new URL(window.location.href);
36
+ if (searchParams.get('inviter')) {
37
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
38
+ }
39
+ }, []);
32
40
  if (contentOnly) {
33
41
  return /*#__PURE__*/_jsx(Container, {
34
42
  children: children
@@ -1,13 +1,16 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import PropTypes from 'prop-types';
3
3
  import { useRef } from 'react';
4
- import { useMemoizedFn, useReactive } from 'ahooks';
4
+ import { useCreation, useMemoizedFn, useReactive } from 'ahooks';
5
5
  import { Box, ClickAwayListener, Divider, Fade, IconButton, MenuItem, MenuList, Paper, Popper } from '@mui/material';
6
6
  import { Icon } from '@iconify/react';
7
7
  import PersonOutlineRoundedIcon from '@iconify-icons/material-symbols/person-outline-rounded';
8
8
  import FilterVintageOutlineRoundedIcon from '@iconify-icons/material-symbols/filter-vintage-outline-rounded';
9
9
  import AccountCircleOffOutlineRoundedIcon from '@iconify-icons/material-symbols/account-circle-off-outline-rounded';
10
+ import InviteIcon from '@iconify-icons/material-symbols/featured-seasonal-and-gifts-rounded';
11
+ import Copy from 'copy-to-clipboard';
10
12
  import noop from 'lodash/noop';
13
+ import Toast from '../../Toast';
11
14
  import DidAvatar from '../../Avatar';
12
15
  import { getUserAvatar } from '../../Util';
13
16
  import UserInfo from './user-info';
@@ -16,6 +19,11 @@ import { DASHBOARD_URL, PROFILE_URL } from '../../Util/constant';
16
19
  import SessionPermission from '../../SessionPermission';
17
20
  import { translations } from '../libs/translation';
18
21
  import { translate } from '../../Locale/util';
22
+ const getInviteLink = inviter => {
23
+ const url = new URL(window.location.href);
24
+ url.searchParams.set('inviter', inviter);
25
+ return url.toString();
26
+ };
19
27
  export default function LoggedIn({
20
28
  session,
21
29
  dark,
@@ -27,6 +35,9 @@ export default function LoggedIn({
27
35
  const t = useMemoizedFn((key, data = {}) => {
28
36
  return translate(translations, key, locale, 'en', data);
29
37
  });
38
+ const isInviteEnabled = useCreation(() => {
39
+ return !!globalThis?.blocklet?.settings?.invite?.enabled;
40
+ });
30
41
  const popperAnchorRef = useRef(null);
31
42
  const currentState = useReactive({
32
43
  open: false
@@ -69,6 +80,12 @@ export default function LoggedIn({
69
80
  onTogglePopper(false);
70
81
  session.bindWallet(onBindWallet);
71
82
  });
83
+ const handleOpenInvite = useMemoizedFn(() => {
84
+ onTogglePopper(false);
85
+ const link = getInviteLink(session.user.did);
86
+ Copy(link);
87
+ Toast.success(t('inviteCopied'));
88
+ });
72
89
  return /*#__PURE__*/_jsxs(_Fragment, {
73
90
  children: [/*#__PURE__*/_jsx(IconButton, {
74
91
  ref: popperAnchorRef,
@@ -155,6 +172,14 @@ export default function LoggedIn({
155
172
  textDecoration: 'none',
156
173
  color: 'inherit'
157
174
  }
175
+ }), isInviteEnabled && /*#__PURE__*/_jsx(SessionMenuItem, {
176
+ icon: InviteIcon,
177
+ title: t('invite'),
178
+ onClick: handleOpenInvite,
179
+ sx: {
180
+ display: 'block',
181
+ color: 'inherit'
182
+ }
158
183
  }), /*#__PURE__*/_jsx(Divider, {
159
184
  sx: {
160
185
  m: '0!important',
@@ -4,6 +4,8 @@ export const translations = {
4
4
  connectDIDWallet: 'Connect your DID Wallet for enhanced security',
5
5
  switch: 'Switch',
6
6
  profile: 'Profile',
7
+ invite: 'Invite friends',
8
+ inviteCopied: 'Your invite link has been copied to the clipboard. Send it to your friends to complete the invitation',
7
9
  dashboard: 'Dashboard',
8
10
  logout: 'Sign Out',
9
11
  addAnotherAccount: 'Add another account'
@@ -12,6 +14,8 @@ export const translations = {
12
14
  connectDIDWallet: '连接你的 DID Wallet 获得更高的安全性',
13
15
  switch: '切换',
14
16
  profile: '个人中心',
17
+ invite: '邀请好友',
18
+ inviteCopied: '你的专属链接已经复制到剪贴板,发送给朋友即可完成邀请',
15
19
  dashboard: '控制台',
16
20
  logout: '退出登录',
17
21
  addAnotherAccount: '添加账户'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/ux",
3
- "version": "2.10.26",
3
+ "version": "2.10.28",
4
4
  "description": "Common used react components for arcblock products",
5
5
  "keywords": [
6
6
  "react",
@@ -59,12 +59,12 @@
59
59
  "react": ">=18.2.0",
60
60
  "react-router-dom": ">=6.22.3"
61
61
  },
62
- "gitHead": "196e6adde06c3c62b95faecf931e2120e366a2fe",
62
+ "gitHead": "71cb15e455bd2f3bdf906c14ae4ef87f9da9c271",
63
63
  "dependencies": {
64
64
  "@arcblock/did-motif": "^1.1.13",
65
- "@arcblock/icons": "^2.10.26",
66
- "@arcblock/nft-display": "^2.10.26",
67
- "@arcblock/react-hooks": "^2.10.26",
65
+ "@arcblock/icons": "^2.10.28",
66
+ "@arcblock/nft-display": "^2.10.28",
67
+ "@arcblock/react-hooks": "^2.10.28",
68
68
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
69
69
  "@fontsource/inter": "^5.0.16",
70
70
  "@fontsource/ubuntu-mono": "^5.0.18",
@@ -76,7 +76,7 @@
76
76
  "@testing-library/react": "^14.0.0",
77
77
  "@types/mui-datatables": "^4.3.12",
78
78
  "ahooks": "^3.7.10",
79
- "axios": "^1.7.2",
79
+ "axios": "^1.7.5",
80
80
  "base64-url": "^2.3.3",
81
81
  "copy-to-clipboard": "^3.3.2",
82
82
  "core-js": "^3.25.5",
@@ -11,8 +11,8 @@ import Dialog from './dialog';
11
11
  * title: React.ReactNode,
12
12
  * open: boolean,
13
13
  * children: React.ReactNode,
14
- * onConfirm: () => void | Promise<void>,
15
- * onCancel: () => void | Promise<void>,
14
+ * onConfirm: Function,
15
+ * onCancel: Function,
16
16
  * showCancelButton?: boolean,
17
17
  * showCloseButton?: boolean,
18
18
  * fullScreen?: boolean,
@@ -26,6 +26,11 @@ function Header({
26
26
  const style = { minWidth: brandWrapperMinWidth };
27
27
 
28
28
  useEffect(() => {
29
+ const { searchParams } = new URL(window.location.href);
30
+ if (searchParams.get('inviter')) {
31
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
32
+ }
33
+
29
34
  if (logoRef.current) {
30
35
  setBrandWrapperMinWidth(`${logoRef.current.offsetWidth}px`);
31
36
  }
@@ -66,6 +66,13 @@ function Dashboard({ children, title, headerProps, links = [], fullWidth, dense,
66
66
  ...headerProps,
67
67
  };
68
68
 
69
+ useEffect(() => {
70
+ const { searchParams } = new URL(window.location.href);
71
+ if (searchParams.get('inviter')) {
72
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
73
+ }
74
+ }, []);
75
+
69
76
  return (
70
77
  <Wrapper {...rest} className={classes}>
71
78
  <Helmet title={title} key={title} />
@@ -1,4 +1,4 @@
1
- import { useState } from 'react';
1
+ import { useEffect, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import Helmet from 'react-helmet';
4
4
  import {
@@ -43,6 +43,13 @@ export default function Layout({
43
43
  setDrawerOpen(!drawerOpen);
44
44
  };
45
45
 
46
+ useEffect(() => {
47
+ const { searchParams } = new URL(window.location.href);
48
+ if (searchParams.get('inviter')) {
49
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
50
+ }
51
+ }, []);
52
+
46
53
  if (contentOnly) {
47
54
  return <Container>{children}</Container>;
48
55
  }
@@ -1,13 +1,16 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import { useRef } from 'react';
3
- import { useMemoizedFn, useReactive } from 'ahooks';
3
+ import { useCreation, useMemoizedFn, useReactive } from 'ahooks';
4
4
  import { Box, ClickAwayListener, Divider, Fade, IconButton, MenuItem, MenuList, Paper, Popper } from '@mui/material';
5
5
  import { Icon } from '@iconify/react';
6
6
  import PersonOutlineRoundedIcon from '@iconify-icons/material-symbols/person-outline-rounded';
7
7
  import FilterVintageOutlineRoundedIcon from '@iconify-icons/material-symbols/filter-vintage-outline-rounded';
8
8
  import AccountCircleOffOutlineRoundedIcon from '@iconify-icons/material-symbols/account-circle-off-outline-rounded';
9
+ import InviteIcon from '@iconify-icons/material-symbols/featured-seasonal-and-gifts-rounded';
10
+ import Copy from 'copy-to-clipboard';
9
11
  import noop from 'lodash/noop';
10
12
 
13
+ import Toast from '../../Toast';
11
14
  import DidAvatar from '../../Avatar';
12
15
  import { getUserAvatar } from '../../Util';
13
16
  import UserInfo from './user-info';
@@ -17,10 +20,19 @@ import SessionPermission from '../../SessionPermission';
17
20
  import { translations } from '../libs/translation';
18
21
  import { translate } from '../../Locale/util';
19
22
 
23
+ const getInviteLink = (inviter) => {
24
+ const url = new URL(window.location.href);
25
+ url.searchParams.set('inviter', inviter);
26
+ return url.toString();
27
+ };
28
+
20
29
  export default function LoggedIn({ session, dark, onBindWallet, isBlocklet, locale, size }) {
21
30
  const t = useMemoizedFn((key, data = {}) => {
22
31
  return translate(translations, key, locale, 'en', data);
23
32
  });
33
+ const isInviteEnabled = useCreation(() => {
34
+ return !!globalThis?.blocklet?.settings?.invite?.enabled;
35
+ });
24
36
  const popperAnchorRef = useRef(null);
25
37
  const currentState = useReactive({
26
38
  open: false,
@@ -66,6 +78,14 @@ export default function LoggedIn({ session, dark, onBindWallet, isBlocklet, loca
66
78
  onTogglePopper(false);
67
79
  session.bindWallet(onBindWallet);
68
80
  });
81
+
82
+ const handleOpenInvite = useMemoizedFn(() => {
83
+ onTogglePopper(false);
84
+ const link = getInviteLink(session.user.did);
85
+ Copy(link);
86
+ Toast.success(t('inviteCopied'));
87
+ });
88
+
69
89
  return (
70
90
  <>
71
91
  <IconButton
@@ -132,6 +152,14 @@ export default function LoggedIn({ session, dark, onBindWallet, isBlocklet, loca
132
152
  href={PROFILE_URL}
133
153
  sx={{ display: 'block', textDecoration: 'none', color: 'inherit' }}
134
154
  />
155
+ {isInviteEnabled && (
156
+ <SessionMenuItem
157
+ icon={InviteIcon}
158
+ title={t('invite')}
159
+ onClick={handleOpenInvite}
160
+ sx={{ display: 'block', color: 'inherit' }}
161
+ />
162
+ )}
135
163
  <Divider sx={{ m: '0!important', borderColor: colors.strokeSep }} />
136
164
  </>
137
165
  ) : null}
@@ -4,6 +4,9 @@ export const translations = {
4
4
  connectDIDWallet: 'Connect your DID Wallet for enhanced security',
5
5
  switch: 'Switch',
6
6
  profile: 'Profile',
7
+ invite: 'Invite friends',
8
+ inviteCopied:
9
+ 'Your invite link has been copied to the clipboard. Send it to your friends to complete the invitation',
7
10
  dashboard: 'Dashboard',
8
11
  logout: 'Sign Out',
9
12
  addAnotherAccount: 'Add another account',
@@ -12,6 +15,8 @@ export const translations = {
12
15
  connectDIDWallet: '连接你的 DID Wallet 获得更高的安全性',
13
16
  switch: '切换',
14
17
  profile: '个人中心',
18
+ invite: '邀请好友',
19
+ inviteCopied: '你的专属链接已经复制到剪贴板,发送给朋友即可完成邀请',
15
20
  dashboard: '控制台',
16
21
  logout: '退出登录',
17
22
  addAnotherAccount: '添加账户',