@arcblock/ux 1.16.0 → 1.16.4

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 (90) hide show
  1. package/lib/CodeBlock/index.js +3 -1
  2. package/package.json +6 -5
  3. package/src/ActionButton/index.js +65 -0
  4. package/src/ActivityIndicator/index.js +186 -0
  5. package/src/Alert/index.js +104 -0
  6. package/src/Async/index.js +39 -0
  7. package/src/Badge/index.js +71 -0
  8. package/src/Blocklet/index.js +335 -0
  9. package/src/Button/index.js +4 -0
  10. package/src/Button/wrap.js +88 -0
  11. package/src/ButtonGroup/index.js +19 -0
  12. package/src/Center/index.js +17 -0
  13. package/src/ClickToCopy/index.js +90 -0
  14. package/src/CodeBlock/index.js +160 -0
  15. package/src/Colors/index.js +1 -0
  16. package/src/Colors/themes/default.js +53 -0
  17. package/src/ContactForm/index.js +240 -0
  18. package/src/CookieConsent/index.js +90 -0
  19. package/src/CountDown/index.js +151 -0
  20. package/src/Dialog/confirm.js +76 -0
  21. package/src/Dialog/dialog.js +162 -0
  22. package/src/Dialog/index.js +2 -0
  23. package/src/DriftBot/index.js +81 -0
  24. package/src/Earth/countries.json +8057 -0
  25. package/src/Earth/index.js +511 -0
  26. package/src/Earth/util.js +69 -0
  27. package/src/Empty/index.js +41 -0
  28. package/src/Footer/index.js +84 -0
  29. package/src/Icon/image.js +55 -0
  30. package/src/Icon/index.js +69 -0
  31. package/src/Img/index.js +172 -0
  32. package/src/InfoRow/index.js +83 -0
  33. package/src/Layout/dashboard/header.js +145 -0
  34. package/src/Layout/dashboard/index.js +140 -0
  35. package/src/Layout/dashboard/sidebar.js +120 -0
  36. package/src/Layout/index.js +318 -0
  37. package/src/Locale/browser-lang.js +63 -0
  38. package/src/Locale/context.js +88 -0
  39. package/src/Locale/images/globe-dark.png +0 -0
  40. package/src/Locale/images/globe-light.png +0 -0
  41. package/src/Locale/selector.js +138 -0
  42. package/src/Logo/images/logo-dark-text.svg +3 -0
  43. package/src/Logo/images/logo-dark-top.svg +6 -0
  44. package/src/Logo/images/logo-light-text.svg +3 -0
  45. package/src/Logo/images/logo-light-top.svg +6 -0
  46. package/src/Logo/index.js +47 -0
  47. package/src/Metric/index.js +115 -0
  48. package/src/NFTDisplay/README.md +59 -0
  49. package/src/NFTDisplay/aspect-ratio-container.js +34 -0
  50. package/src/NFTDisplay/broken.js +18 -0
  51. package/src/NFTDisplay/index.js +230 -0
  52. package/src/NFTDisplay/loading.js +17 -0
  53. package/src/NFTDisplay/svg-embedder/img.js +36 -0
  54. package/src/NFTDisplay/svg-embedder/inline-svg.js +37 -0
  55. package/src/PageScroller/index.js +342 -0
  56. package/src/PageScroller/usePrevValue.js +12 -0
  57. package/src/PricingTable/PricingPlan.js +112 -0
  58. package/src/PricingTable/index.js +43 -0
  59. package/src/Screenshot/devices.css +1366 -0
  60. package/src/Screenshot/index.js +181 -0
  61. package/src/Spinner/index.js +33 -0
  62. package/src/Switch/index.js +78 -0
  63. package/src/Tabs/index.js +46 -0
  64. package/src/Tag/index.js +73 -0
  65. package/src/Terminal/Player.js +364 -0
  66. package/src/Terminal/index.js +150 -0
  67. package/src/Terminal/player.css +378 -0
  68. package/src/Terminal/util.js +167 -0
  69. package/src/Terminal/xterm.css +171 -0
  70. package/src/TextCollapse/index.js +92 -0
  71. package/src/Theme/index.js +169 -0
  72. package/src/Theme/responsiveFontSizes.js +94 -0
  73. package/src/Toast/index.js +118 -0
  74. package/src/Util/index.js +264 -0
  75. package/src/Video/index.js +72 -0
  76. package/src/Wallet/Action.js +105 -0
  77. package/src/Wallet/Download.js +130 -0
  78. package/src/Wallet/Open.js +50 -0
  79. package/src/Wallet/images/abtwallet.png +0 -0
  80. package/src/Wallet/images/android_download.svg +23 -0
  81. package/src/Wallet/images/app-store.svg +20 -0
  82. package/src/Wallet/images/google-play.svg +70 -0
  83. package/src/WechatPrompt/images/android.png +0 -0
  84. package/src/WechatPrompt/images/ios.png +0 -0
  85. package/src/WechatPrompt/index.js +81 -0
  86. package/src/index.js +63 -0
  87. package/src/withTheme/index.js +72 -0
  88. package/src/withTracker/README.md +34 -0
  89. package/src/withTracker/error_boundary.js +34 -0
  90. package/src/withTracker/index.js +70 -0
@@ -0,0 +1,120 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import withTheme from '@material-ui/core/styles/withTheme';
5
+
6
+ import { withRouter, Link } from 'react-router-dom';
7
+ import Button from '@material-ui/core/Button';
8
+ import Typography from '@material-ui/core/Typography';
9
+ import teal from '@material-ui/core/colors/teal';
10
+
11
+ import ImageIcon from '../../Icon/image';
12
+ import Logo from '../../Logo';
13
+
14
+ function Sidebar({ location, theme, images, links, prefix, addons, ...rest }) {
15
+ const isSelected = (url, name) => {
16
+ const pattern = new RegExp(`/${name}`);
17
+ return pattern.test(location.pathname);
18
+ };
19
+
20
+ return (
21
+ <MenuItems {...rest}>
22
+ <Link to="/" className="sidebar-logo">
23
+ <Logo showText={false} size={20} />
24
+ </Link>
25
+ {links.map(({ url, name, title, showBadge }) => {
26
+ const selected = isSelected(url, name);
27
+ return (
28
+ <MenuItem component={Link} key={url} selected={selected} to={url}>
29
+ <ImageIcon
30
+ name={images[name]}
31
+ size={36}
32
+ color={selected ? '#00c2c4' : theme.typography.color.main}
33
+ prefix={prefix}
34
+ showBadge={showBadge}
35
+ />
36
+ <Typography component="span" className="menu-title">
37
+ {title}
38
+ </Typography>
39
+ </MenuItem>
40
+ );
41
+ })}
42
+ <div style={{ flex: 1 }} />
43
+ {addons}
44
+ </MenuItems>
45
+ );
46
+ }
47
+
48
+ Sidebar.propTypes = {
49
+ location: PropTypes.object.isRequired,
50
+ theme: PropTypes.object.isRequired,
51
+ images: PropTypes.object.isRequired,
52
+ links: PropTypes.array.isRequired,
53
+ prefix: PropTypes.string,
54
+ addons: PropTypes.any,
55
+ };
56
+
57
+ Sidebar.defaultProps = {
58
+ prefix: '/images',
59
+ addons: null,
60
+ };
61
+
62
+ const MenuItems = React.memo(styled.div`
63
+ flex: 1;
64
+ display: flex;
65
+ flex-direction: column;
66
+
67
+ && .sidebar-logo {
68
+ display: none;
69
+ border-bottom: 1px solid #eee;
70
+ background: ${props => props.theme.palette.background.default};
71
+ position: sticky;
72
+ top: 0;
73
+ z-index: 1;
74
+ padding: 10px 0;
75
+ text-align: center;
76
+ font-size: 0;
77
+ }
78
+ @media (max-width: ${props => props.theme.breakpoints.values.md}px) {
79
+ && .sidebar-logo {
80
+ display: block;
81
+ }
82
+ }
83
+ `);
84
+
85
+ const gradient = 'linear-gradient(32deg, rgba(144, 255, 230, 0.1), rgba(144, 255, 230, 0))';
86
+
87
+ const MenuItem = styled(Button)`
88
+ && {
89
+ display: block;
90
+ width: 100%;
91
+ transition: all 200ms ease-in-out;
92
+ background: ${props => (props.selected ? gradient : '')};
93
+ padding: 24px 0;
94
+ border-left: 2px solid ${props => (props.selected ? teal.A700 : 'transparent')};
95
+
96
+ &:hover {
97
+ background: ${gradient};
98
+ border-left-color: ${teal.A700};
99
+ }
100
+
101
+ .menu-title {
102
+ margin-top: 8px;
103
+ font-size: 12px;
104
+ font-weight: 500;
105
+ text-align: center;
106
+ text-transform: capitalize;
107
+ letter-spacing: normal;
108
+ width: 80%;
109
+ }
110
+
111
+ .MuiButton-label {
112
+ display: flex;
113
+ flex-direction: column;
114
+ justify-content: center;
115
+ align-items: center;
116
+ }
117
+ }
118
+ `;
119
+
120
+ export default withRouter(withTheme(Sidebar));
@@ -0,0 +1,318 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import Helmet from 'react-helmet';
5
+ import Link from '@material-ui/core/Link';
6
+
7
+ import AppBar from '@material-ui/core/AppBar';
8
+ import Container from '@material-ui/core/Container';
9
+ import Drawer from '@material-ui/core/Drawer';
10
+ import Divider from '@material-ui/core/Divider';
11
+ import Toolbar from '@material-ui/core/Toolbar';
12
+ import Typography from '@material-ui/core/Typography';
13
+ import List from '@material-ui/core/List';
14
+ import ListItem from '@material-ui/core/ListItem';
15
+ import ListItemText from '@material-ui/core/ListItemText';
16
+ import IconButton from '@material-ui/core/IconButton';
17
+ import MenuIcon from '@material-ui/icons/Menu';
18
+
19
+ import Footer from '../Footer';
20
+ import OpenInWallet from '../Wallet/Open';
21
+ import Icon from '../Icon';
22
+ import Logo from '../Logo';
23
+
24
+ export default function Layout({
25
+ title,
26
+ brand,
27
+ description,
28
+ links,
29
+ logo,
30
+ showLogo,
31
+ addons,
32
+ footer,
33
+ baseUrl,
34
+ homeUrl,
35
+ children,
36
+ variant,
37
+ contentOnly,
38
+ ...rest
39
+ }) {
40
+ const [drawerOpen, setDrawerOpen] = React.useState(false);
41
+ const onToggleDrawer = () => {
42
+ setDrawerOpen(!drawerOpen);
43
+ };
44
+
45
+ if (contentOnly) {
46
+ return <Container>{children}</Container>;
47
+ }
48
+
49
+ let activeLink = '';
50
+ const { pathname: currentPath } = new URL(window.location);
51
+ links.forEach(link => {
52
+ if (currentPath.startsWith(link.url) && link.url.length > activeLink.length) {
53
+ activeLink = link.url;
54
+ }
55
+ });
56
+
57
+ const drawer = (
58
+ <div>
59
+ <Toolbar className="toolbar toolbar--drawer">
60
+ {showLogo ? <div className="menu-logo">{logo}</div> : <></>}
61
+ <div style={{ flexGrow: 1, overflow: 'hidden', textOverflow: 'ellipsis' }}>{brand}</div>
62
+ </Toolbar>
63
+ <Divider />
64
+ <List>
65
+ {links.map(x => (
66
+ <Link className="nav-link" key={x.url} href={x.url}>
67
+ <ListItem button className={activeLink === x.url ? 'drawer-highlight-nav' : ''}>
68
+ <ListItemText>
69
+ {x.icon && (
70
+ <Icon
71
+ name={x.icon}
72
+ size={18 * (x.iconZoom || 1)}
73
+ color="inherit"
74
+ style={{ marginRight: '5px' }}
75
+ />
76
+ )}
77
+ {x.title}
78
+ </ListItemText>
79
+ </ListItem>
80
+ </Link>
81
+ ))}
82
+ </List>
83
+ </div>
84
+ );
85
+
86
+ return (
87
+ <>
88
+ <Div {...rest}>
89
+ <Helmet title={title} />
90
+ <AppBar
91
+ position="fixed"
92
+ className={`appbar appbar--${variant}`}
93
+ color="default"
94
+ style={{ height: 56 }}>
95
+ <Container disableGutters>
96
+ <Toolbar className="toolbar">
97
+ <IconButton
98
+ color="inherit"
99
+ aria-label="open drawer"
100
+ edge="start"
101
+ onClick={onToggleDrawer}
102
+ className="menu-button">
103
+ <MenuIcon />
104
+ </IconButton>
105
+ {showLogo ? <div className="menu-logo">{logo}</div> : <></>}
106
+ <Typography
107
+ href={homeUrl}
108
+ component="a"
109
+ variant="h5"
110
+ color="inherit"
111
+ noWrap
112
+ display="block"
113
+ className="brand">
114
+ {brand}
115
+ </Typography>
116
+ {description && (
117
+ <Typography
118
+ component="small"
119
+ variant="subtitle2"
120
+ color="inherit"
121
+ noWrap
122
+ className="description">
123
+ {description}
124
+ </Typography>
125
+ )}
126
+ <div style={{ flexGrow: 1 }} />
127
+ <div className="nav-links">
128
+ {links.map(x => (
129
+ <Link
130
+ key={x.url}
131
+ href={x.url}
132
+ className={`nav-link ${activeLink === x.url ? 'highlight-nav' : ''}`}
133
+ color={x.color}>
134
+ {x.icon && (
135
+ <Icon
136
+ name={x.icon}
137
+ size={20 * (x.iconZoom || 1)}
138
+ color="inherit"
139
+ style={{ marginRight: '5px' }}
140
+ />
141
+ )}
142
+ {x.title}
143
+ </Link>
144
+ ))}
145
+ </div>
146
+ {addons}
147
+ </Toolbar>
148
+ </Container>
149
+ </AppBar>
150
+ <div className="toolbar" />
151
+ <Container style={{ marginTop: 16, flex: 1 }}>{children}</Container>
152
+ {footer}
153
+ {!!baseUrl && <OpenInWallet locale="zh" link={baseUrl} />}
154
+ </Div>
155
+ <DrawerDiv>
156
+ <Drawer
157
+ variant="temporary"
158
+ open={drawerOpen}
159
+ onClose={onToggleDrawer}
160
+ classes={{
161
+ paper: 'drawer-paper',
162
+ }}
163
+ ModalProps={{
164
+ keepMounted: true, // Better open performance on mobile.
165
+ disablePortal: true,
166
+ }}>
167
+ {drawer}
168
+ </Drawer>
169
+ </DrawerDiv>
170
+ </>
171
+ );
172
+ }
173
+
174
+ Layout.propTypes = {
175
+ title: PropTypes.string.isRequired,
176
+ brand: PropTypes.any.isRequired,
177
+ description: PropTypes.any,
178
+ addons: PropTypes.any,
179
+ showLogo: PropTypes.bool,
180
+ logo: PropTypes.any,
181
+ links: PropTypes.array,
182
+ children: PropTypes.any.isRequired,
183
+ baseUrl: PropTypes.string,
184
+ homeUrl: PropTypes.string,
185
+ variant: PropTypes.oneOf(['shadow', 'border']),
186
+ footer: PropTypes.any,
187
+ contentOnly: PropTypes.bool,
188
+ };
189
+
190
+ Layout.defaultProps = {
191
+ contentOnly: false,
192
+ baseUrl: '',
193
+ homeUrl: '/',
194
+ links: [],
195
+ showLogo: false,
196
+ logo: <Logo showText={false} style={{ width: '40px', height: '40px' }} />,
197
+ variant: 'shadow',
198
+ addons: undefined,
199
+ description: undefined,
200
+ footer: (
201
+ <Container>
202
+ <Footer />
203
+ </Container>
204
+ ),
205
+ };
206
+
207
+ const Div = styled.div`
208
+ width: 100%;
209
+ min-height: 100vh;
210
+ display: flex;
211
+ flex-direction: column;
212
+ .appbar {
213
+ &.appbar--border {
214
+ box-shadow: none;
215
+ &::before {
216
+ content: '';
217
+ position: absolute;
218
+ left: 0;
219
+ right: 0;
220
+ height: 1px;
221
+ bottom: -1px;
222
+ display: block;
223
+ background-color: rgba(0, 0, 0, 0.12);
224
+ }
225
+ }
226
+ }
227
+
228
+ .toolbar {
229
+ min-height: 56px;
230
+ background: inherit;
231
+ white-space: nowrap;
232
+ .menu-logo {
233
+ font-size: 0;
234
+ margin-right: 8px;
235
+ }
236
+
237
+ .nav-links {
238
+ display: flex;
239
+ align-items: center;
240
+ .nav-link {
241
+ margin: 8px 12px;
242
+ font-size: 16px;
243
+ display: flex;
244
+ align-items: center;
245
+ }
246
+
247
+ .highlight-nav {
248
+ font-weight: bolder;
249
+ }
250
+ }
251
+ .brand {
252
+ cursor: pointer;
253
+ text-decoration: none;
254
+ overflow: hidden;
255
+ text-overflow: ellipsis;
256
+ flex-shrink: 1;
257
+ }
258
+ .description {
259
+ color: #999;
260
+ font-size: 15px;
261
+ margin-left: 10px;
262
+ font-weight: normal;
263
+ flex-shrink: 999999;
264
+ }
265
+ }
266
+
267
+ @media (min-width: ${props => props.theme.breakpoints.values.md}px) {
268
+ .toolbar {
269
+ .menu-button {
270
+ display: none;
271
+ }
272
+ .menu-logo {
273
+ & + .brand {
274
+ padding-left: 45px;
275
+ margin-left: -45px;
276
+ }
277
+ }
278
+ }
279
+ }
280
+
281
+ @media (max-width: ${props => props.theme.breakpoints.values.md - 1}px) {
282
+ .toolbar {
283
+ .nav-links,
284
+ .menu-logo,
285
+ .description {
286
+ display: none;
287
+ }
288
+ }
289
+ }
290
+ `;
291
+
292
+ const DrawerDiv = styled.nav`
293
+ width: 240px;
294
+ .drawer-paper {
295
+ width: 240px;
296
+ }
297
+ .toolbar {
298
+ min-height: 56px;
299
+ }
300
+
301
+ a:hover,
302
+ a:active,
303
+ a:visited,
304
+ a:focus {
305
+ text-decoration: none;
306
+ }
307
+
308
+ .drawer-highlight-nav {
309
+ background-color: #eee;
310
+ }
311
+
312
+ .toolbar--drawer {
313
+ font-size: 18px;
314
+ .menu-logo {
315
+ display: inline-flex;
316
+ }
317
+ }
318
+ `;
@@ -0,0 +1,63 @@
1
+ /* eslint-disable no-param-reassign */
2
+ function startsWith(string, target, position) {
3
+ const { length } = string;
4
+ position = position == null ? 0 : position;
5
+ if (position < 0) {
6
+ position = 0;
7
+ } else if (position > length) {
8
+ position = length;
9
+ }
10
+ target = `${target}`;
11
+ // eslint-disable-next-line eqeqeq
12
+ return string.slice(position, position + target.length) == target;
13
+ }
14
+
15
+ function getBrowserLang() {
16
+ if (typeof window === 'undefined') {
17
+ return null;
18
+ }
19
+
20
+ const lang =
21
+ (window.navigator.languages && window.navigator.languages[0]) ||
22
+ window.navigator.language ||
23
+ window.navigator.browserLanguage ||
24
+ window.navigator.userLanguage ||
25
+ window.navigator.systemLanguage ||
26
+ null;
27
+
28
+ return lang;
29
+ }
30
+
31
+ function normalizeCode(code) {
32
+ return (code || '').toLowerCase().replace(/-/, '_');
33
+ }
34
+
35
+ function getPreferredLanguage(options) {
36
+ if (!options) {
37
+ return getBrowserLang();
38
+ }
39
+
40
+ const { languages, fallback } = options;
41
+ if (!options.languages) {
42
+ return fallback;
43
+ }
44
+
45
+ // some browsers report language as en-US instead of en_US
46
+ const browserLanguage = normalizeCode(getBrowserLang());
47
+
48
+ if (!browserLanguage) {
49
+ return fallback;
50
+ }
51
+
52
+ const match = languages.filter(lang => normalizeCode(lang) === browserLanguage);
53
+
54
+ if (match.length > 0) {
55
+ return match[0] || fallback;
56
+ }
57
+
58
+ // en == en_US
59
+ const matchCodeOnly = languages.filter(lang => startsWith(browserLanguage, lang));
60
+ return matchCodeOnly[0] || fallback;
61
+ }
62
+
63
+ export default getPreferredLanguage;
@@ -0,0 +1,88 @@
1
+ /* eslint-disable no-prototype-builtins */
2
+ import React, { useState, useEffect, useContext } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import Cookie from 'js-cookie';
5
+
6
+ import browserLang from './browser-lang';
7
+ import { getCookieOptions } from '../Util';
8
+
9
+ const cookieName = 'nf_lang';
10
+ const languages = [
11
+ { value: 'en', text: 'English' },
12
+ { value: 'zh', text: '简体中文' },
13
+ ];
14
+ const langParams = {
15
+ languages: ['zh', 'en'],
16
+ fallback: 'en',
17
+ };
18
+
19
+ // 跨应用传递多语言选择的方式是在 query string 中添加 locale 参数,LocaleSelector 要高优先级遵守这个参数
20
+ const getLocaleFromSearchParams = (url = window.location.href) => {
21
+ const locale = new URL(url).searchParams.get('locale');
22
+ if (languages.find(x => x.value === locale)) {
23
+ return locale;
24
+ }
25
+ return null;
26
+ };
27
+
28
+ const getLocale = locale =>
29
+ locale || getLocaleFromSearchParams() || Cookie.get(cookieName) || browserLang(langParams);
30
+ const setLocale = locale => Cookie.set(cookieName, locale, getCookieOptions());
31
+
32
+ const replace = (template, data) =>
33
+ template.replace(/{(\w*)}/g, (m, key) => (data.hasOwnProperty(key) ? data[key] : ''));
34
+
35
+ const LocaleContext = React.createContext();
36
+ const { Provider, Consumer } = LocaleContext;
37
+
38
+ function LocaleProvider({ children, locale, translations, ...rest }) {
39
+ const [currentLocale, setCurrentLocale] = useState(getLocale(locale));
40
+
41
+ useEffect(() => {
42
+ setLocale(currentLocale);
43
+ }, [currentLocale]);
44
+
45
+ const changeLocale = newLocale => {
46
+ setCurrentLocale(newLocale);
47
+ };
48
+
49
+ const translate = (key, data) => {
50
+ if (!translations[currentLocale] || !translations[currentLocale][key]) {
51
+ console.warn(`Warning: no ${key} translation of ${currentLocale}`);
52
+ return key;
53
+ }
54
+
55
+ return replace(translations[currentLocale][key], data);
56
+ };
57
+
58
+ return (
59
+ <Provider value={{ locale: currentLocale, changeLocale, t: translate, ...rest }}>
60
+ {children}
61
+ </Provider>
62
+ );
63
+ }
64
+
65
+ function useLocaleContext() {
66
+ const context = useContext(LocaleContext);
67
+ return context;
68
+ }
69
+
70
+ LocaleProvider.propTypes = {
71
+ children: PropTypes.any.isRequired,
72
+ translations: PropTypes.object.isRequired,
73
+ locale: PropTypes.string,
74
+ };
75
+
76
+ LocaleProvider.defaultProps = {
77
+ locale: '',
78
+ };
79
+
80
+ export {
81
+ LocaleProvider,
82
+ Consumer as LocaleConsumer,
83
+ LocaleContext,
84
+ useLocaleContext,
85
+ setLocale,
86
+ getLocale,
87
+ languages,
88
+ };
Binary file