@arcblock/ux 2.1.18 → 2.1.21
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/ActionButton/index.js +16 -8
- package/lib/ActivityIndicator/index.js +49 -36
- package/lib/Alert/index.js +25 -17
- package/lib/AnimationWaiter/index.js +44 -35
- package/lib/Async/index.js +15 -3
- package/lib/Badge/index.js +14 -4
- package/lib/Blocklet/blocklet.js +81 -62
- package/lib/BlockletNFT/index.js +95 -76
- package/lib/Button/wrap.js +13 -9
- package/lib/Center/index.js +6 -5
- package/lib/ClickToCopy/index.js +31 -21
- package/lib/CodeBlock/index.js +35 -27
- package/lib/ContactForm/index.js +46 -41
- package/lib/CookieConsent/index.js +33 -21
- package/lib/CountDown/index.js +50 -34
- package/lib/Datatable/CustomToolbar.js +138 -97
- package/lib/Datatable/DatatableContext.js +9 -12
- package/lib/Datatable/TableSearch.js +44 -27
- package/lib/Datatable/index.js +44 -28
- package/lib/Dialog/confirm.js +26 -13
- package/lib/Dialog/dialog.js +42 -26
- package/lib/DriftBot/index.js +2 -2
- package/lib/Earth/index.js +121 -107
- package/lib/Empty/index.js +19 -10
- package/lib/ErrorBoundary/fallback.js +18 -12
- package/lib/Footer/index.js +32 -26
- package/lib/Header/header.js +37 -21
- package/lib/Header/responsive-header.js +40 -30
- package/lib/Icon/image.js +22 -15
- package/lib/Icon/index.js +17 -7
- package/lib/Img/index.js +34 -32
- package/lib/InfoRow/index.js +23 -13
- package/lib/Layout/dashboard/index.js +66 -54
- package/lib/Layout/dashboard/sidebar.js +39 -26
- package/lib/Layout/dashboard-legacy/header.js +56 -38
- package/lib/Layout/dashboard-legacy/index.js +54 -44
- package/lib/Layout/dashboard-legacy/sidebar.js +48 -38
- package/lib/Layout/index.js +147 -111
- package/lib/Locale/context.js +8 -10
- package/lib/Locale/selector.js +55 -41
- package/lib/Logo/index.js +50 -30
- package/lib/Metric/index.js +30 -23
- package/lib/NFTDisplay/aspect-ratio-container.js +15 -6
- package/lib/NFTDisplay/broken.js +3 -3
- package/lib/NFTDisplay/index.js +29 -28
- package/lib/NFTDisplay/loading.js +6 -5
- package/lib/NFTDisplay/svg-embedder/img.js +10 -4
- package/lib/NFTDisplay/svg-embedder/inline-svg.js +14 -6
- package/lib/NavMenu/nav-menu.js +60 -49
- package/lib/PageScroller/index.js +29 -27
- package/lib/PageScroller/usePrevValue.js +1 -5
- package/lib/PricingTable/PricingPlan.js +46 -36
- package/lib/PricingTable/index.js +22 -20
- package/lib/QRCode/index.js +6 -9
- package/lib/RelativeTime/index.js +14 -5
- package/lib/Result/common.js +49 -44
- package/lib/Result/index.js +6 -6
- package/lib/Result/result.js +29 -18
- package/lib/Screenshot/index.js +32 -21
- package/lib/Spinner/index.js +3 -3
- package/lib/SplitButton/index.js +40 -24
- package/lib/Switch/index.js +12 -6
- package/lib/Tabs/index.js +18 -12
- package/lib/Tag/index.js +14 -4
- package/lib/Terminal/Player.js +108 -92
- package/lib/Terminal/index.js +3 -1
- package/lib/TextCollapse/index.js +18 -8
- package/lib/Toast/index.js +17 -14
- package/lib/Video/index.js +31 -25
- package/lib/Wallet/Action.js +37 -25
- package/lib/Wallet/Download.js +236 -181
- package/lib/Wallet/Open.js +6 -5
- package/lib/WechatPrompt/index.js +40 -28
- package/lib/withTheme/index.js +23 -9
- package/lib/withTracker/error_boundary.js +10 -7
- package/lib/withTracker/index.js +8 -4
- package/package.json +4 -4
- package/src/ActionButton/index.js +3 -4
- package/src/ActivityIndicator/index.js +4 -7
- package/src/Alert/index.js +4 -10
- package/src/AnimationWaiter/index.js +4 -2
- package/src/Async/index.js +4 -8
- package/src/Badge/index.js +2 -2
- package/src/Blocklet/blocklet.js +16 -27
- package/src/Blocklet/utils.js +3 -3
- package/src/BlockletNFT/index.js +7 -15
- package/src/Button/wrap.js +2 -2
- package/src/Center/index.js +0 -1
- package/src/ClickToCopy/index.js +5 -12
- package/src/CodeBlock/index.js +2 -7
- package/src/Colors/index.js +1 -0
- package/src/ContactForm/index.js +16 -16
- package/src/CookieConsent/index.js +3 -2
- package/src/CountDown/index.js +8 -8
- package/src/Datatable/CustomToolbar.js +8 -9
- package/src/Datatable/DatatableContext.js +3 -3
- package/src/Datatable/TableSearch.js +18 -13
- package/src/Datatable/index.js +13 -12
- package/src/Datatable/utils.js +19 -23
- package/src/Dialog/confirm.js +0 -1
- package/src/Dialog/dialog.js +7 -27
- package/src/Dialog/index.js +1 -0
- package/src/DriftBot/index.js +2 -2
- package/src/Earth/index.js +26 -44
- package/src/Empty/index.js +0 -1
- package/src/ErrorBoundary/fallback.js +2 -3
- package/src/Footer/index.js +3 -7
- package/src/Header/header.js +4 -5
- package/src/Header/responsive-header.js +4 -10
- package/src/Icon/image.js +0 -1
- package/src/Icon/index.js +8 -8
- package/src/Img/index.js +6 -6
- package/src/InfoRow/index.js +22 -21
- package/src/Layout/dashboard/index.js +9 -4
- package/src/Layout/dashboard/sidebar.js +4 -10
- package/src/Layout/dashboard-legacy/header.js +9 -15
- package/src/Layout/dashboard-legacy/index.js +4 -11
- package/src/Layout/dashboard-legacy/sidebar.js +7 -7
- package/src/Layout/index.js +12 -26
- package/src/Locale/browser-lang.js +2 -2
- package/src/Locale/context.js +7 -11
- package/src/Locale/selector.js +8 -8
- package/src/Logo/index.js +4 -6
- package/src/Metric/index.js +9 -10
- package/src/NFTDisplay/aspect-ratio-container.js +0 -1
- package/src/NFTDisplay/broken.js +0 -1
- package/src/NFTDisplay/index.js +10 -8
- package/src/NFTDisplay/loading.js +0 -1
- package/src/NFTDisplay/svg-embedder/img.js +1 -2
- package/src/NFTDisplay/svg-embedder/inline-svg.js +0 -1
- package/src/NavMenu/index.js +1 -0
- package/src/NavMenu/nav-menu.js +14 -27
- package/src/NavMenu/style.js +3 -3
- package/src/PageScroller/index.js +19 -35
- package/src/PageScroller/usePrevValue.js +1 -1
- package/src/PricingTable/PricingPlan.js +31 -30
- package/src/PricingTable/index.js +4 -5
- package/src/QRCode/index.js +3 -2
- package/src/RelativeTime/index.js +1 -5
- package/src/Result/common.js +19 -20
- package/src/Result/index.js +5 -6
- package/src/Result/result.js +2 -3
- package/src/Result/translations.js +1 -2
- package/src/Screenshot/index.js +10 -10
- package/src/Spinner/index.js +0 -1
- package/src/SplitButton/index.js +6 -19
- package/src/Switch/index.js +40 -41
- package/src/Tabs/index.js +2 -9
- package/src/Tag/index.js +2 -2
- package/src/Terminal/Player.js +7 -8
- package/src/Terminal/index.js +4 -3
- package/src/Terminal/util.js +3 -3
- package/src/TextCollapse/index.js +4 -10
- package/src/Theme/index.js +1 -8
- package/src/Toast/index.js +6 -10
- package/src/Util/index.js +15 -27
- package/src/Video/index.js +2 -8
- package/src/Wallet/Action.js +5 -6
- package/src/Wallet/Download.js +6 -7
- package/src/Wallet/Open.js +1 -2
- package/src/WechatPrompt/index.js +2 -7
- package/src/withTheme/index.js +5 -5
- package/src/withTracker/error_boundary.js +3 -3
- package/src/withTracker/index.js +2 -2
package/src/NFTDisplay/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
+
import { useRef, useEffect, useState } from 'react';
|
|
2
3
|
import PropTypes from 'prop-types';
|
|
3
4
|
import styled from 'styled-components';
|
|
4
5
|
import clsx from 'clsx';
|
|
@@ -34,7 +35,7 @@ function fromBase64(v) {
|
|
|
34
35
|
// };
|
|
35
36
|
|
|
36
37
|
// 仅针对非 url type 的情况
|
|
37
|
-
const getSvgEmbedder = preferredSvgEmbedder => {
|
|
38
|
+
const getSvgEmbedder = (preferredSvgEmbedder) => {
|
|
38
39
|
const embedders = {
|
|
39
40
|
img: ImgSvgEmbedder,
|
|
40
41
|
svg: InlineSvgEmbedder,
|
|
@@ -62,14 +63,14 @@ function NFTDisplay({
|
|
|
62
63
|
onCompleted,
|
|
63
64
|
...rest
|
|
64
65
|
}) {
|
|
65
|
-
const wrapRoot = children => (
|
|
66
|
+
const wrapRoot = (children) => (
|
|
66
67
|
<Root as={component} {...rest} className={clsx(className, { 'nft-display--inset': inset })}>
|
|
67
68
|
{children}
|
|
68
69
|
</Root>
|
|
69
70
|
);
|
|
70
71
|
|
|
71
72
|
try {
|
|
72
|
-
const parsed =
|
|
73
|
+
const parsed = useRef(data);
|
|
73
74
|
// 如果是 raw data 先解析
|
|
74
75
|
if (typeof parsed.current === 'string') {
|
|
75
76
|
parsed.current = JSON.parse(data);
|
|
@@ -88,19 +89,21 @@ function NFTDisplay({
|
|
|
88
89
|
const [minimumLoadingReady, setMinimumLoadingReady] = useState(minimumLoadingTime <= 0);
|
|
89
90
|
// console.log('[debug] render', {type, minimumLoadingTime}, JSON.stringify(state))
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
useEffect(() => {
|
|
92
93
|
let timer;
|
|
93
94
|
if (minimumLoadingTime > 0) {
|
|
94
95
|
timer = setTimeout(() => setMinimumLoadingReady(true), minimumLoadingTime);
|
|
95
96
|
}
|
|
96
97
|
return () => clearTimeout(timer);
|
|
98
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
97
99
|
}, []);
|
|
98
100
|
|
|
99
101
|
// onCompleted
|
|
100
|
-
|
|
102
|
+
useEffect(() => {
|
|
101
103
|
if ((!state.loading && minimumLoadingReady) || state.error) {
|
|
102
104
|
onCompleted();
|
|
103
105
|
}
|
|
106
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
104
107
|
}, [state, minimumLoadingReady]);
|
|
105
108
|
|
|
106
109
|
if (state.error) {
|
|
@@ -168,8 +171,7 @@ function NFTDisplay({
|
|
|
168
171
|
|
|
169
172
|
return wrapRoot(
|
|
170
173
|
<>
|
|
171
|
-
{(state.loading || !minimumLoadingReady) &&
|
|
172
|
-
(renderLoading ? renderLoading() : <DefaultLoading />)}
|
|
174
|
+
{(state.loading || !minimumLoadingReady) && (renderLoading ? renderLoading() : <DefaultLoading />)}
|
|
173
175
|
{renderNFT()}
|
|
174
176
|
</>
|
|
175
177
|
);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import PropTypes from 'prop-types';
|
|
3
2
|
import InlineSvgEmbedder from './inline-svg';
|
|
4
3
|
|
|
5
|
-
const svgToImgUrl = svg => {
|
|
4
|
+
const svgToImgUrl = (svg) => {
|
|
6
5
|
// fix: #225, https://stackoverflow.com/a/52135328)
|
|
7
6
|
const blob = new Blob([svg], { type: 'image/svg+xml' });
|
|
8
7
|
return URL.createObjectURL(blob);
|
package/src/NavMenu/index.js
CHANGED
package/src/NavMenu/nav-menu.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Children, useEffect, createContext, useContext, useMemo, useState, useRef } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
@@ -9,9 +9,7 @@ const NavMenuContext = createContext();
|
|
|
9
9
|
// 过滤 children 中的 Item/Sub, 忽略其它类型的 element
|
|
10
10
|
function filterItems(children) {
|
|
11
11
|
if (children) {
|
|
12
|
-
return
|
|
13
|
-
child => child.type === Item || child.type === Sub
|
|
14
|
-
);
|
|
12
|
+
return Children.toArray(children).filter((child) => child.type === Item || child.type === Sub);
|
|
15
13
|
}
|
|
16
14
|
return null;
|
|
17
15
|
}
|
|
@@ -24,17 +22,7 @@ function useUniqueId(id) {
|
|
|
24
22
|
/**
|
|
25
23
|
* NavMenu, 导航组件, 可用于 header/footer/sidebar
|
|
26
24
|
*/
|
|
27
|
-
function NavMenu({
|
|
28
|
-
items,
|
|
29
|
-
mode,
|
|
30
|
-
children,
|
|
31
|
-
defaultActiveId,
|
|
32
|
-
textColor,
|
|
33
|
-
activeTextColor,
|
|
34
|
-
bgColor,
|
|
35
|
-
onSelected,
|
|
36
|
-
...rest
|
|
37
|
-
}) {
|
|
25
|
+
function NavMenu({ items, mode, children, defaultActiveId, textColor, activeTextColor, bgColor, onSelected, ...rest }) {
|
|
38
26
|
// eslint-disable-next-line no-param-reassign
|
|
39
27
|
children = filterItems(children);
|
|
40
28
|
if (!items?.length && !children?.length) {
|
|
@@ -45,18 +33,18 @@ function NavMenu({
|
|
|
45
33
|
return {
|
|
46
34
|
...state,
|
|
47
35
|
mode,
|
|
48
|
-
activate: id => {
|
|
49
|
-
setState(prev => ({ ...prev, activeId: id }));
|
|
36
|
+
activate: (id) => {
|
|
37
|
+
setState((prev) => ({ ...prev, activeId: id }));
|
|
50
38
|
onSelected?.(id);
|
|
51
39
|
},
|
|
52
|
-
open: id => {
|
|
53
|
-
setState(prev => ({ ...prev, openedIds: [...prev.openedIds, id] }));
|
|
40
|
+
open: (id) => {
|
|
41
|
+
setState((prev) => ({ ...prev, openedIds: [...prev.openedIds, id] }));
|
|
54
42
|
},
|
|
55
|
-
close: id => {
|
|
56
|
-
setState(prev => ({ ...prev, openedIds: prev.openedIds.filter(item => item !== id) }));
|
|
43
|
+
close: (id) => {
|
|
44
|
+
setState((prev) => ({ ...prev, openedIds: prev.openedIds.filter((item) => item !== id) }));
|
|
57
45
|
},
|
|
58
46
|
};
|
|
59
|
-
}, [state]);
|
|
47
|
+
}, [state, mode, onSelected]);
|
|
60
48
|
const classes = clsx('navmenu', `navmenu--${mode}`, rest.className);
|
|
61
49
|
const renderItem = (item, index) => {
|
|
62
50
|
if (item.children) {
|
|
@@ -116,10 +104,11 @@ function Item({ id: _id, icon, label, active, onClick, ...rest }) {
|
|
|
116
104
|
const id = useUniqueId(_id);
|
|
117
105
|
const { activeId, activate } = useContext(NavMenuContext);
|
|
118
106
|
const classes = clsx('navmenu-item', { 'navmenu-item--active': activeId === id }, rest.className);
|
|
119
|
-
|
|
107
|
+
useEffect(() => {
|
|
120
108
|
if (active) {
|
|
121
109
|
activate(id);
|
|
122
110
|
}
|
|
111
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
123
112
|
}, [active]);
|
|
124
113
|
const handleClick = () => {
|
|
125
114
|
onClick?.();
|
|
@@ -169,16 +158,14 @@ function Sub({ id: _id, icon, label, children, expandIcon, ...rest }) {
|
|
|
169
158
|
// inline mode, 避免点击子菜单项时触发父菜单的 open/close
|
|
170
159
|
const containerProps = isInlineMode
|
|
171
160
|
? {
|
|
172
|
-
onClick: e => e.stopPropagation(),
|
|
161
|
+
onClick: (e) => e.stopPropagation(),
|
|
173
162
|
}
|
|
174
163
|
: {};
|
|
175
164
|
return (
|
|
176
165
|
<li {...rest} className={classes} {...props}>
|
|
177
166
|
{icon && <span className="navmenu-sub-icon">{icon}</span>}
|
|
178
167
|
<span className="navmenu-sub-label">{label}</span>
|
|
179
|
-
{expandIcon && (
|
|
180
|
-
<span className="navmenu-sub-expand-icon">{expandIcon?.({ isOpen }) || expandIcon}</span>
|
|
181
|
-
)}
|
|
168
|
+
{expandIcon && <span className="navmenu-sub-expand-icon">{expandIcon?.({ isOpen }) || expandIcon}</span>}
|
|
182
169
|
<div className="navmenu-sub-container" {...containerProps}>
|
|
183
170
|
<ul className="navmenu-sub-list">{filterItems(children)}</ul>
|
|
184
171
|
</div>
|
package/src/NavMenu/style.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styled from 'styled-components';
|
|
2
2
|
|
|
3
3
|
const NavMenuBase = styled.nav`
|
|
4
|
-
background-color: ${props => props.$bgColor};
|
|
4
|
+
background-color: ${(props) => props.$bgColor};
|
|
5
5
|
font-size: 14px;
|
|
6
6
|
ul {
|
|
7
7
|
list-style: none;
|
|
@@ -19,12 +19,12 @@ const NavMenuBase = styled.nav`
|
|
|
19
19
|
/* active/hover */
|
|
20
20
|
.navmenu-item,
|
|
21
21
|
.navmenu-sub {
|
|
22
|
-
color: ${props => props.$textColor};
|
|
22
|
+
color: ${(props) => props.$textColor};
|
|
23
23
|
}
|
|
24
24
|
.navmenu-item--active,
|
|
25
25
|
.navmenu-item:hover,
|
|
26
26
|
.navmenu-sub--opened {
|
|
27
|
-
color: ${props => props.$activeTextColor};
|
|
27
|
+
color: ${(props) => props.$activeTextColor};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
.navmenu-item {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
|
|
2
|
-
import
|
|
2
|
+
import { Children, cloneElement, useCallback, useEffect, useRef, useState } from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import isEqual from 'lodash/isEqual';
|
|
5
5
|
import isNil from 'lodash/isNil';
|
|
@@ -31,7 +31,7 @@ let isBodyScrollEnabled = true;
|
|
|
31
31
|
let isTransitionAfterComponentsToRenderChanged = false;
|
|
32
32
|
const containers = [];
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
function PageScroller({
|
|
35
35
|
animationTimer,
|
|
36
36
|
blockScrollDown,
|
|
37
37
|
blockScrollUp,
|
|
@@ -43,26 +43,21 @@ const PageScroller = ({
|
|
|
43
43
|
onChange,
|
|
44
44
|
renderAllPagesOnFirstRender,
|
|
45
45
|
transitionTimingFunction,
|
|
46
|
-
})
|
|
46
|
+
}) {
|
|
47
47
|
const [componentIndex, setComponentIndex] = useState(DEFAULT_COMPONENT_INDEX);
|
|
48
|
-
const [componentsToRenderLength, setComponentsToRenderLength] = useState(
|
|
49
|
-
DEFAULT_COMPONENTS_TO_RENDER_LENGTH
|
|
50
|
-
);
|
|
48
|
+
const [componentsToRenderLength, setComponentsToRenderLength] = useState(DEFAULT_COMPONENTS_TO_RENDER_LENGTH);
|
|
51
49
|
const prevComponentIndex = usePrevious(componentIndex);
|
|
52
50
|
const pageContainer = useRef(null);
|
|
53
51
|
|
|
54
52
|
const addNextComponent = useCallback(
|
|
55
|
-
componentsToRenderOnMountLength => {
|
|
53
|
+
(componentsToRenderOnMountLength) => {
|
|
56
54
|
let tempComponentsToRenderLength = 0;
|
|
57
55
|
|
|
58
56
|
if (!isNil(componentsToRenderOnMountLength)) {
|
|
59
57
|
tempComponentsToRenderLength = componentsToRenderOnMountLength;
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
tempComponentsToRenderLength = Math.max(
|
|
63
|
-
tempComponentsToRenderLength,
|
|
64
|
-
componentsToRenderLength
|
|
65
|
-
);
|
|
60
|
+
tempComponentsToRenderLength = Math.max(tempComponentsToRenderLength, componentsToRenderLength);
|
|
66
61
|
|
|
67
62
|
if (tempComponentsToRenderLength <= componentIndex + 1) {
|
|
68
63
|
if (!isNil(children[componentIndex + 1])) {
|
|
@@ -77,7 +72,7 @@ const PageScroller = ({
|
|
|
77
72
|
|
|
78
73
|
const checkRenderOnMount = useCallback(() => {
|
|
79
74
|
if (renderAllPagesOnFirstRender) {
|
|
80
|
-
setComponentsToRenderLength(
|
|
75
|
+
setComponentsToRenderLength(Children.count(children));
|
|
81
76
|
} else if (!isNil(children[DEFAULT_COMPONENT_INDEX + 1])) {
|
|
82
77
|
addNextComponent(DEFAULT_COMPONENTS_TO_RENDER_LENGTH + 1);
|
|
83
78
|
}
|
|
@@ -113,7 +108,7 @@ const PageScroller = ({
|
|
|
113
108
|
containers[i] = true;
|
|
114
109
|
newComponentsToRender.push(
|
|
115
110
|
<div key={i} style={{ height: '100%', width: '100%' }}>
|
|
116
|
-
{
|
|
111
|
+
{cloneElement(children[i], { ...children[i].props })}
|
|
117
112
|
</div>
|
|
118
113
|
);
|
|
119
114
|
i++;
|
|
@@ -131,7 +126,7 @@ const PageScroller = ({
|
|
|
131
126
|
|
|
132
127
|
setTimeout(() => {
|
|
133
128
|
if (isMounted) {
|
|
134
|
-
setComponentIndex(prevState => prevState + 1);
|
|
129
|
+
setComponentIndex((prevState) => prevState + 1);
|
|
135
130
|
}
|
|
136
131
|
}, animationTimer + ANIMATION_TIMER_BUFFER);
|
|
137
132
|
} else {
|
|
@@ -141,14 +136,7 @@ const PageScroller = ({
|
|
|
141
136
|
}
|
|
142
137
|
}
|
|
143
138
|
}
|
|
144
|
-
}, [
|
|
145
|
-
animationTimer,
|
|
146
|
-
blockScrollDown,
|
|
147
|
-
componentIndex,
|
|
148
|
-
disableScroll,
|
|
149
|
-
enableDocumentScroll,
|
|
150
|
-
onScrollUnavailable,
|
|
151
|
-
]);
|
|
139
|
+
}, [animationTimer, blockScrollDown, componentIndex, disableScroll, enableDocumentScroll, onScrollUnavailable]);
|
|
152
140
|
|
|
153
141
|
const scrollWindowUp = useCallback(() => {
|
|
154
142
|
if (!isScrolling && !blockScrollUp) {
|
|
@@ -159,7 +147,7 @@ const PageScroller = ({
|
|
|
159
147
|
|
|
160
148
|
setTimeout(() => {
|
|
161
149
|
if (isMounted) {
|
|
162
|
-
setComponentIndex(prevState => prevState - 1);
|
|
150
|
+
setComponentIndex((prevState) => prevState - 1);
|
|
163
151
|
}
|
|
164
152
|
}, animationTimer + ANIMATION_TIMER_BUFFER);
|
|
165
153
|
} else {
|
|
@@ -169,17 +157,10 @@ const PageScroller = ({
|
|
|
169
157
|
}
|
|
170
158
|
}
|
|
171
159
|
}
|
|
172
|
-
}, [
|
|
173
|
-
animationTimer,
|
|
174
|
-
blockScrollUp,
|
|
175
|
-
componentIndex,
|
|
176
|
-
disableScroll,
|
|
177
|
-
enableDocumentScroll,
|
|
178
|
-
onScrollUnavailable,
|
|
179
|
-
]);
|
|
160
|
+
}, [animationTimer, blockScrollUp, componentIndex, disableScroll, enableDocumentScroll, onScrollUnavailable]);
|
|
180
161
|
|
|
181
162
|
const touchMove = useCallback(
|
|
182
|
-
event => {
|
|
163
|
+
(event) => {
|
|
183
164
|
if (!isNull(previousTouchMove)) {
|
|
184
165
|
if (event.touches[0].clientY > previousTouchMove) {
|
|
185
166
|
scrollWindowUp();
|
|
@@ -194,7 +175,7 @@ const PageScroller = ({
|
|
|
194
175
|
);
|
|
195
176
|
|
|
196
177
|
const wheelScroll = useCallback(
|
|
197
|
-
event => {
|
|
178
|
+
(event) => {
|
|
198
179
|
if (event.deltaY < 0) {
|
|
199
180
|
scrollWindowUp();
|
|
200
181
|
} else {
|
|
@@ -205,7 +186,7 @@ const PageScroller = ({
|
|
|
205
186
|
);
|
|
206
187
|
|
|
207
188
|
const keyPress = useCallback(
|
|
208
|
-
event => {
|
|
189
|
+
(event) => {
|
|
209
190
|
if (isEqual(event.keyCode, KEY_UP)) {
|
|
210
191
|
scrollWindowUp();
|
|
211
192
|
}
|
|
@@ -222,6 +203,7 @@ const PageScroller = ({
|
|
|
222
203
|
return () => {
|
|
223
204
|
if (pageContainer.current?.removeEventListener) {
|
|
224
205
|
pageContainer.current.removeEventListener(Events.TOUCHMOVE, touchMove);
|
|
206
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
225
207
|
pageContainer.current.removeEventListener(Events.KEYDOWN, keyPress);
|
|
226
208
|
}
|
|
227
209
|
};
|
|
@@ -234,6 +216,7 @@ const PageScroller = ({
|
|
|
234
216
|
return () => {
|
|
235
217
|
isMounted = false;
|
|
236
218
|
};
|
|
219
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
237
220
|
}, []);
|
|
238
221
|
|
|
239
222
|
useEffect(() => {
|
|
@@ -282,6 +265,7 @@ const PageScroller = ({
|
|
|
282
265
|
}
|
|
283
266
|
}
|
|
284
267
|
}
|
|
268
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
285
269
|
}, [customPageNumber]);
|
|
286
270
|
|
|
287
271
|
useEffect(() => {
|
|
@@ -312,7 +296,7 @@ const PageScroller = ({
|
|
|
312
296
|
</div>
|
|
313
297
|
</div>
|
|
314
298
|
);
|
|
315
|
-
}
|
|
299
|
+
}
|
|
316
300
|
|
|
317
301
|
PageScroller.propTypes = {
|
|
318
302
|
animationTimer: PropTypes.number,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import PropTypes from 'prop-types';
|
|
3
2
|
import styled from 'styled-components';
|
|
4
3
|
|
|
@@ -7,36 +6,38 @@ import Button from '@mui/material/Button';
|
|
|
7
6
|
import CardContent from '@mui/material/CardContent';
|
|
8
7
|
import Typography from '@mui/material/Typography';
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<
|
|
13
|
-
<div className="
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<
|
|
17
|
-
<div className="plan-
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
</div>
|
|
22
|
-
<div className="plan-services">
|
|
23
|
-
{plan.featureList.map(line => (
|
|
24
|
-
<Typography component="p" variant="body1" align="center" key={line}>
|
|
25
|
-
{line}
|
|
9
|
+
function PricingPlan({ plan }) {
|
|
10
|
+
return (
|
|
11
|
+
<PlanCard shadow>
|
|
12
|
+
<div className="card-header">
|
|
13
|
+
<div className="title">{plan.name}</div>
|
|
14
|
+
</div>
|
|
15
|
+
<CardContent className="card-content">
|
|
16
|
+
<div className="plan-content">
|
|
17
|
+
<div className="plan-pricing">
|
|
18
|
+
<Typography component="h2" variant="h5" className="price-number">
|
|
19
|
+
{plan.price}
|
|
26
20
|
</Typography>
|
|
27
|
-
|
|
21
|
+
</div>
|
|
22
|
+
<div className="plan-services">
|
|
23
|
+
{plan.featureList.map((line) => (
|
|
24
|
+
<Typography component="p" variant="body1" align="center" key={line}>
|
|
25
|
+
{line}
|
|
26
|
+
</Typography>
|
|
27
|
+
))}
|
|
28
|
+
</div>
|
|
28
29
|
</div>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
</
|
|
37
|
-
</
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
<div className="plan-actions">
|
|
31
|
+
{plan.showButton && (
|
|
32
|
+
<Button fullWidth variant="outlined" color="primary" component="a" href={plan.buttonLink}>
|
|
33
|
+
{plan.buttonText}
|
|
34
|
+
</Button>
|
|
35
|
+
)}
|
|
36
|
+
</div>
|
|
37
|
+
</CardContent>
|
|
38
|
+
</PlanCard>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
40
41
|
|
|
41
42
|
export default PricingPlan;
|
|
42
43
|
|
|
@@ -53,7 +54,7 @@ const PlanCard = styled(Card)`
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
&& {
|
|
56
|
-
${props => (props.shadow ? '' : 'box-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.1)')}
|
|
57
|
+
${(props) => (props.shadow ? '' : 'box-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.1)')}
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
.card-header {
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import PropTypes from 'prop-types';
|
|
3
2
|
import styled from 'styled-components';
|
|
4
3
|
import Grid from '@mui/material/Grid';
|
|
5
4
|
|
|
6
5
|
import PricingPlan from './PricingPlan';
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
function PricingTable({ plans }) {
|
|
9
8
|
if (plans && plans.length > 0) {
|
|
10
9
|
return (
|
|
11
10
|
<Div variant="even">
|
|
12
11
|
<Grid container spacing={2} justifyContent="center">
|
|
13
|
-
{plans.map(x => (
|
|
12
|
+
{plans.map((x) => (
|
|
14
13
|
<Grid item className="plan-item" key={x.id} xs={12} sm={6} md={3}>
|
|
15
14
|
<PricingPlan plan={x} />
|
|
16
15
|
</Grid>
|
|
@@ -20,7 +19,7 @@ const PricingTable = ({ plans }) => {
|
|
|
20
19
|
);
|
|
21
20
|
}
|
|
22
21
|
return null;
|
|
23
|
-
}
|
|
22
|
+
}
|
|
24
23
|
|
|
25
24
|
export default PricingTable;
|
|
26
25
|
|
|
@@ -31,7 +30,7 @@ PricingTable.propTypes = {
|
|
|
31
30
|
const Div = styled.div`
|
|
32
31
|
padding: 100px 0;
|
|
33
32
|
text-align: center;
|
|
34
|
-
background-color: ${props => (props.variant === 'even' ? '#fbfbfb' : '#ffffff')};
|
|
33
|
+
background-color: ${(props) => (props.variant === 'even' ? '#fbfbfb' : '#ffffff')};
|
|
35
34
|
@media (max-width: 320px) {
|
|
36
35
|
padding: 50px 0;
|
|
37
36
|
}
|
package/src/QRCode/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useRef, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import QRCodeStyling from '@solana/qr-code-styling';
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ const defaults = {
|
|
|
18
18
|
// 该组件用于生成与 android wallet 样式风格相似的 qrcode
|
|
19
19
|
// 注意: 依赖的 @solana/qr-code-styling 是一份 fork 版本, 原版本的 margin 配置存在 bug
|
|
20
20
|
function QRCode({ data, size, image, config, ...rest }) {
|
|
21
|
-
const ref =
|
|
21
|
+
const ref = useRef(null);
|
|
22
22
|
const options = useMemo(() => {
|
|
23
23
|
return {
|
|
24
24
|
...defaults,
|
|
@@ -47,6 +47,7 @@ function QRCode({ data, size, image, config, ...rest }) {
|
|
|
47
47
|
useEffect(() => {
|
|
48
48
|
if (!qrCode) return;
|
|
49
49
|
qrCode.update(options);
|
|
50
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
50
51
|
}, [data, size, image, config]);
|
|
51
52
|
|
|
52
53
|
return <div ref={ref} {...rest} />;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import PropTypes from 'prop-types';
|
|
3
2
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
4
3
|
import dayjs from 'dayjs';
|
|
@@ -53,10 +52,7 @@ export default function RelativeTime({ value, locale, withoutSuffix, from, to, .
|
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
return (
|
|
56
|
-
<Tooltip
|
|
57
|
-
title={formatToDatetime(value, { locale: localeOption })}
|
|
58
|
-
placement="top-end"
|
|
59
|
-
enterTouchDelay={0}>
|
|
55
|
+
<Tooltip title={formatToDatetime(value, { locale: localeOption })} placement="top-end" enterTouchDelay={0}>
|
|
60
56
|
<span {...rest}>{innerContent}</span>
|
|
61
57
|
</Tooltip>
|
|
62
58
|
);
|
package/src/Result/common.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable react/prop-types */
|
|
2
2
|
/* eslint-disable no-param-reassign */
|
|
3
|
-
import React from 'react';
|
|
4
3
|
import useTheme from '@mui/styles/useTheme';
|
|
5
4
|
import InfoIcon from '@mui/icons-material/Info';
|
|
6
5
|
import CancelRoundedIcon from '@mui/icons-material/CancelRounded';
|
|
@@ -9,14 +8,14 @@ import translations from './translations';
|
|
|
9
8
|
import { useLocaleContext } from '../Locale/context';
|
|
10
9
|
|
|
11
10
|
// 优先使用显式指定的 locale, 再尝试使用 context 中的 locale, 最后使用默认 'en'
|
|
12
|
-
const useLocale = locale => {
|
|
11
|
+
const useLocale = (locale) => {
|
|
13
12
|
locale = ['zh', 'en'].includes(locale) ? locale : '';
|
|
14
13
|
const { locale: localeFromContext } = useLocaleContext() || { locale: 'en' };
|
|
15
14
|
return locale || localeFromContext;
|
|
16
15
|
};
|
|
17
16
|
|
|
18
17
|
// 404
|
|
19
|
-
export
|
|
18
|
+
export function PageNotFound({ locale, ...rest }) {
|
|
20
19
|
locale = useLocale(locale);
|
|
21
20
|
return (
|
|
22
21
|
<Result
|
|
@@ -26,11 +25,11 @@ export const PageNotFound = ({ locale, ...rest }) => {
|
|
|
26
25
|
{...rest}
|
|
27
26
|
/>
|
|
28
27
|
);
|
|
29
|
-
}
|
|
28
|
+
}
|
|
30
29
|
PageNotFound.status = '404';
|
|
31
30
|
|
|
32
31
|
// 403
|
|
33
|
-
export
|
|
32
|
+
export function Forbidden({ locale, ...rest }) {
|
|
34
33
|
locale = useLocale(locale);
|
|
35
34
|
return (
|
|
36
35
|
<Result
|
|
@@ -40,11 +39,11 @@ export const Forbidden = ({ locale, ...rest }) => {
|
|
|
40
39
|
{...rest}
|
|
41
40
|
/>
|
|
42
41
|
);
|
|
43
|
-
}
|
|
42
|
+
}
|
|
44
43
|
Forbidden.status = '403';
|
|
45
44
|
|
|
46
45
|
// 500
|
|
47
|
-
export
|
|
46
|
+
export function InternalServerError({ locale, ...rest }) {
|
|
48
47
|
locale = useLocale(locale);
|
|
49
48
|
return (
|
|
50
49
|
<Result
|
|
@@ -54,11 +53,11 @@ export const InternalServerError = ({ locale, ...rest }) => {
|
|
|
54
53
|
{...rest}
|
|
55
54
|
/>
|
|
56
55
|
);
|
|
57
|
-
}
|
|
56
|
+
}
|
|
58
57
|
InternalServerError.status = '500';
|
|
59
58
|
|
|
60
59
|
// 通用错误
|
|
61
|
-
export
|
|
60
|
+
export function Error({ locale, ...rest }) {
|
|
62
61
|
locale = useLocale(locale);
|
|
63
62
|
return (
|
|
64
63
|
<Result
|
|
@@ -68,11 +67,11 @@ export const Error = ({ locale, ...rest }) => {
|
|
|
68
67
|
{...rest}
|
|
69
68
|
/>
|
|
70
69
|
);
|
|
71
|
-
}
|
|
70
|
+
}
|
|
72
71
|
Error.status = 'error';
|
|
73
72
|
|
|
74
73
|
// under maintenance
|
|
75
|
-
export
|
|
74
|
+
export function Maintenance({ locale, ...rest }) {
|
|
76
75
|
locale = useLocale(locale);
|
|
77
76
|
return (
|
|
78
77
|
<Result
|
|
@@ -82,11 +81,11 @@ export const Maintenance = ({ locale, ...rest }) => {
|
|
|
82
81
|
{...rest}
|
|
83
82
|
/>
|
|
84
83
|
);
|
|
85
|
-
}
|
|
84
|
+
}
|
|
86
85
|
Maintenance.status = 'maintenance';
|
|
87
86
|
|
|
88
87
|
// coming soon
|
|
89
|
-
export
|
|
88
|
+
export function ComingSoon({ locale, ...rest }) {
|
|
90
89
|
locale = useLocale(locale);
|
|
91
90
|
return (
|
|
92
91
|
<Result
|
|
@@ -96,21 +95,21 @@ export const ComingSoon = ({ locale, ...rest }) => {
|
|
|
96
95
|
{...rest}
|
|
97
96
|
/>
|
|
98
97
|
);
|
|
99
|
-
}
|
|
98
|
+
}
|
|
100
99
|
ComingSoon.status = 'coming-soon';
|
|
101
100
|
|
|
102
101
|
// info, 与其它 status 不同, title/description 需要使用方自己传入
|
|
103
|
-
export
|
|
102
|
+
export function Info(props) {
|
|
104
103
|
return <Result icon={<StyledInfoIcon />} {...props} />;
|
|
105
|
-
}
|
|
104
|
+
}
|
|
106
105
|
Info.status = 'info';
|
|
107
106
|
|
|
108
|
-
|
|
107
|
+
function StyledErrorIcon(props) {
|
|
109
108
|
const theme = useTheme();
|
|
110
109
|
return <CancelRoundedIcon style={{ color: theme.palette.error.main, fontSize: 72 }} {...props} />;
|
|
111
|
-
}
|
|
110
|
+
}
|
|
112
111
|
|
|
113
|
-
|
|
112
|
+
function StyledInfoIcon(props) {
|
|
114
113
|
const theme = useTheme();
|
|
115
114
|
return <InfoIcon style={{ color: theme.palette.info.main, fontSize: 72 }} {...props} />;
|
|
116
|
-
}
|
|
115
|
+
}
|