@arcblock/ux 2.10.65 → 2.10.67
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/ActionButton/index.d.ts +1 -1
- package/lib/Alert/index.d.ts +1 -1
- package/lib/AnimationWaiter/index.d.ts +27 -15
- package/lib/AnimationWaiter/index.js +15 -14
- package/lib/Async/index.d.ts +50 -17
- package/lib/Badge/index.d.ts +1 -1
- package/lib/Badge/index.js +7 -1
- package/lib/BlockletContext/index.d.ts +12 -28
- package/lib/BlockletContext/index.js +3 -21
- package/lib/Button/wrap.d.ts +5 -3
- package/lib/Button/wrap.js +2 -1
- package/lib/ButtonGroup/index.d.ts +12 -2
- package/lib/ButtonGroup/index.js +13 -3
- package/lib/CardSelector/index.d.ts +11 -33
- package/lib/CardSelector/index.js +16 -32
- package/lib/Center/index.d.ts +6 -21
- package/lib/Center/index.js +2 -17
- package/lib/ClickToCopy/copy-button.d.ts +9 -26
- package/lib/ClickToCopy/copy-button.js +5 -17
- package/lib/ClickToCopy/hook.d.ts +11 -5
- package/lib/ClickToCopy/hook.js +3 -3
- package/lib/ClickToCopy/index.d.ts +18 -29
- package/lib/ClickToCopy/index.js +0 -13
- package/lib/CodeBlock/LightBox.d.ts +1 -1
- package/lib/CodeBlock/index.d.ts +7 -26
- package/lib/CodeBlock/index.js +4 -17
- package/lib/Colors/index.d.ts +2 -2
- package/lib/Colors/themes/default.d.ts +54 -61
- package/lib/Colors/themes/temp.d.ts +35 -35
- package/lib/ContactForm/index.d.ts +26 -30
- package/lib/ContactForm/index.js +7 -17
- package/lib/Dialog/confirm.d.ts +3 -3
- package/lib/Dialog/confirm.js +2 -2
- package/lib/Earth/index.d.ts +10 -1
- package/lib/Header/auto-hidden.d.ts +6 -11
- package/lib/Header/auto-hidden.js +0 -5
- package/lib/Header/header.d.ts +20 -51
- package/lib/Header/header.js +10 -42
- package/lib/Header/index.d.ts +2 -2
- package/lib/Header/responsive-header.d.ts +10 -22
- package/lib/Header/responsive-header.js +1 -13
- package/lib/Icon/image.d.ts +8 -36
- package/lib/Icon/image.js +6 -24
- package/lib/Icon/index.d.ts +9 -1
- package/lib/Icon/index.js +6 -25
- package/lib/NavMenu/index.d.ts +1 -1
- package/lib/NavMenu/nav-menu.d.ts +37 -51
- package/lib/NavMenu/nav-menu.js +47 -102
- package/lib/NavMenu/style.d.ts +8 -2
- package/lib/NavMenu/style.js +3 -1
- package/lib/PageScroller/index.d.ts +13 -1
- package/lib/Passport/passport.js +1 -1
- package/lib/PricingTable/index.d.ts +3 -1
- package/lib/RelativeTime/index.d.ts +1 -1
- package/lib/Screenshot/BaseScreenshot/index.js +1 -1
- package/lib/SplitButton/index.d.ts +0 -19
- package/lib/SplitButton/index.js +7 -27
- package/lib/TextCollapse/index.d.ts +10 -1
- package/lib/Theme/index.d.ts +5 -13
- package/lib/Theme/index.js +4 -11
- package/lib/Theme/theme-provider.d.ts +16 -18
- package/lib/Theme/theme.d.ts +37 -11
- package/lib/Theme/theme.js +13 -22
- package/lib/Util/constant.d.ts +31 -31
- package/lib/Util/deprecate.d.ts +7 -5
- package/lib/Util/federated.d.ts +21 -21
- package/lib/Util/federated.js +1 -1
- package/lib/Util/index.d.ts +59 -60
- package/lib/Util/index.js +16 -43
- package/lib/Util/passport.d.ts +6 -6
- package/lib/Util/wallet.d.ts +15 -3
- package/lib/WebWalletSWKeeper/index.js +1 -1
- package/lib/global.d.ts +13 -0
- package/lib/index.d.ts +4 -2
- package/lib/index.js +2 -2
- package/lib/type.d.ts +31 -1
- package/package.json +5 -5
- package/src/AnimationWaiter/index.jsx +15 -14
- package/src/Async/{index.jsx → index.tsx} +13 -4
- package/src/Badge/index.jsx +8 -1
- package/src/BlockletContext/{index.jsx → index.tsx} +17 -22
- package/src/Button/wrap.jsx +2 -1
- package/src/ButtonGroup/index.js +13 -3
- package/src/CardSelector/{index.jsx → index.tsx} +32 -33
- package/src/Center/index.tsx +33 -0
- package/src/ClickToCopy/{copy-button.jsx → copy-button.tsx} +15 -16
- package/src/ClickToCopy/{hook.js → hook.ts} +5 -5
- package/src/ClickToCopy/{index.jsx → index.tsx} +12 -17
- package/src/CodeBlock/{index.jsx → index.tsx} +15 -17
- package/src/ContactForm/{index.jsx → index.tsx} +47 -29
- package/src/Dialog/confirm.jsx +2 -2
- package/src/Header/{auto-hidden.jsx → auto-hidden.tsx} +6 -7
- package/src/Header/{header.jsx → header.tsx} +32 -46
- package/src/Header/{responsive-header.jsx → responsive-header.tsx} +9 -15
- package/src/Icon/{image.jsx → image.tsx} +19 -22
- package/src/Icon/{index.jsx → index.tsx} +22 -24
- package/src/NavMenu/{nav-menu.jsx → nav-menu.tsx} +161 -144
- package/src/NavMenu/{style.js → style.ts} +9 -1
- package/src/Passport/passport.jsx +1 -1
- package/src/Screenshot/BaseScreenshot/index.jsx +1 -1
- package/src/SplitButton/index.tsx +10 -23
- package/src/Theme/{index.js → index.ts} +6 -12
- package/src/Theme/{theme-provider.jsx → theme-provider.tsx} +10 -2
- package/src/Theme/{theme.js → theme.ts} +54 -23
- package/src/Util/{deprecate.jsx → deprecate.tsx} +8 -4
- package/src/Util/{federated.js → federated.ts} +3 -3
- package/src/Util/{index.js → index.ts} +85 -59
- package/src/Util/{passport.js → passport.ts} +2 -2
- package/src/Util/{wallet.js → wallet.ts} +1 -1
- package/src/WebWalletSWKeeper/index.jsx +1 -1
- package/src/global.d.ts +13 -0
- package/src/{index.js → index.ts} +2 -2
- package/src/type.d.ts +31 -1
- package/src/Center/index.jsx +0 -41
- /package/src/CodeBlock/{LightBox.jsx → LightBox.tsx} +0 -0
- /package/src/Colors/{index.js → index.ts} +0 -0
- /package/src/Colors/themes/{default.js → default.ts} +0 -0
- /package/src/Colors/themes/{temp.js → temp.ts} +0 -0
- /package/src/Header/{index.js → index.ts} +0 -0
- /package/src/NavMenu/{index.js → index.ts} +0 -0
- /package/src/Util/{constant.js → constant.ts} +0 -0
@@ -9,17 +9,18 @@ import { styled } from '../Theme';
|
|
9
9
|
/**
|
10
10
|
* 用于长时间等待的用的动画组件
|
11
11
|
* 动画会随着时间的变化而逐步加快播放速度,好适应用户的等待心理
|
12
|
-
* @param {
|
13
|
-
* @param {
|
14
|
-
* @param {
|
15
|
-
* @param {
|
16
|
-
* @param {
|
17
|
-
* @param {
|
18
|
-
* @param {
|
19
|
-
* @param {
|
20
|
-
* @param {
|
21
|
-
* @param {
|
22
|
-
* @
|
12
|
+
* @param {object} props - 组件属性
|
13
|
+
* @param {object} [props.animationData] - lottie json 动画数据
|
14
|
+
* @param {number|string} [props.size] - 动画的尺寸,单位px
|
15
|
+
* @param {string|React.ReactNode[]} [props.message] - 动画下方的文字;数组情况下会在一定时间切换文案
|
16
|
+
* @param {number} [props.messageDuration=5000] - 动画下方的文字为数组时,每个文案的持续时间(毫秒)
|
17
|
+
* @param {boolean} [props.messageLoop=true] - 动画下方的文字为数组时,文案是否循环播放
|
18
|
+
* @param {React.ReactNode[]} [props.tips=[]] - 底部的提示元素
|
19
|
+
* @param {number} [props.tipsDuration=5000] - 底部提示的切换时间(毫秒)
|
20
|
+
* @param {number} [props.speed=1] - 动画默认的播放速度
|
21
|
+
* @param {number} [props.maybeDuration=120000] - 整个动画大概的持续时间(毫秒),用于计算增量下的动画速度
|
22
|
+
* @param {number} [props.increaseSpeed=0] - 在 maybeDuration 时间下增加的速度
|
23
|
+
* @returns {JSX.Element}
|
23
24
|
*/
|
24
25
|
export default function AnimationWaiter({
|
25
26
|
animationData,
|
@@ -168,12 +169,12 @@ export default function AnimationWaiter({
|
|
168
169
|
}
|
169
170
|
|
170
171
|
AnimationWaiter.propTypes = {
|
171
|
-
animationData: PropTypes.
|
172
|
+
animationData: PropTypes.oneOfType([PropTypes.object, PropTypes.oneOf([null])]),
|
172
173
|
size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
173
|
-
message: PropTypes.
|
174
|
+
message: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.node)]),
|
174
175
|
messageDuration: PropTypes.number,
|
175
176
|
messageLoop: PropTypes.bool,
|
176
|
-
tips: PropTypes.
|
177
|
+
tips: PropTypes.arrayOf(PropTypes.node),
|
177
178
|
tipsDuration: PropTypes.number,
|
178
179
|
speed: PropTypes.number,
|
179
180
|
maybeDuration: PropTypes.number,
|
@@ -1,10 +1,19 @@
|
|
1
1
|
import * as React from 'react';
|
2
|
-
|
3
2
|
import CircularProgress from '@mui/material/CircularProgress';
|
4
3
|
|
5
|
-
export default function LoadAsyncComponent
|
6
|
-
|
7
|
-
|
4
|
+
export default function LoadAsyncComponent<T extends React.ComponentType<any>>(
|
5
|
+
importComponent: () => Promise<Record<string, T>>,
|
6
|
+
key = 'default',
|
7
|
+
showProgress = true
|
8
|
+
) {
|
9
|
+
type Props = React.ComponentProps<T>;
|
10
|
+
type State = {
|
11
|
+
Component: React.ComponentType<any> | null;
|
12
|
+
error: string | null;
|
13
|
+
};
|
14
|
+
|
15
|
+
class AsyncComponent extends React.Component<Props, State> {
|
16
|
+
constructor(props: Props) {
|
8
17
|
super(props);
|
9
18
|
|
10
19
|
this.state = {
|
package/src/Badge/index.jsx
CHANGED
@@ -74,7 +74,14 @@ Badge.defaultProps = {
|
|
74
74
|
};
|
75
75
|
|
76
76
|
export default withDeprecated(
|
77
|
-
forwardRef(
|
77
|
+
forwardRef(
|
78
|
+
/**
|
79
|
+
* @param {BadgeProps} props - Badge组件的属性
|
80
|
+
* @param {React.Ref<HTMLSpanElement>} ref - 转发的ref
|
81
|
+
* @returns {JSX.Element}
|
82
|
+
*/
|
83
|
+
(props, ref) => <Badge {...props} forwardedRef={ref} />
|
84
|
+
),
|
78
85
|
{ name: 'Badge', alternative: '@arcblock/ux/lib/Tag' }
|
79
86
|
);
|
80
87
|
|
@@ -1,20 +1,24 @@
|
|
1
|
-
import PropTypes from 'prop-types';
|
2
1
|
import { useMemoizedFn, useAsyncEffect } from 'ahooks';
|
3
2
|
import { createContext, useContext, useState } from 'react';
|
3
|
+
import type { Blocklet } from '../type';
|
4
4
|
|
5
|
-
const BlockletContext = createContext();
|
5
|
+
const BlockletContext = createContext<Blocklet | null>(null);
|
6
6
|
|
7
7
|
const { Provider, Consumer } = BlockletContext;
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
function BlockletProvider({
|
10
|
+
children,
|
11
|
+
baseUrl = '',
|
12
|
+
loading = null,
|
13
|
+
}: {
|
14
|
+
children: React.ReactNode;
|
15
|
+
/**
|
16
|
+
* baseUrl 为 blocklet origin + blocklet prefix
|
17
|
+
*/
|
18
|
+
baseUrl: string;
|
19
|
+
loading: React.ReactNode;
|
20
|
+
}) {
|
21
|
+
const [blockletData, setBlockletData] = useState<Blocklet | null>(null);
|
18
22
|
const getBlockleData = useMemoizedFn(async () => {
|
19
23
|
if (!baseUrl || window.location.href.startsWith(baseUrl)) {
|
20
24
|
throw new Error('no blocklet data');
|
@@ -24,8 +28,9 @@ function BlockletProvider({ children, baseUrl, loading }) {
|
|
24
28
|
url.searchParams.set('type', 'json');
|
25
29
|
const res = await fetch(url.href);
|
26
30
|
const jsonData = await res.json();
|
27
|
-
return jsonData;
|
31
|
+
return jsonData as Blocklet;
|
28
32
|
});
|
33
|
+
|
29
34
|
useAsyncEffect(async () => {
|
30
35
|
try {
|
31
36
|
const data = await getBlockleData();
|
@@ -45,14 +50,4 @@ function useBlockletContext() {
|
|
45
50
|
return { blocklet };
|
46
51
|
}
|
47
52
|
|
48
|
-
BlockletProvider.propTypes = {
|
49
|
-
baseUrl: PropTypes.string,
|
50
|
-
children: PropTypes.any.isRequired,
|
51
|
-
loading: PropTypes.any,
|
52
|
-
};
|
53
|
-
BlockletProvider.defaultProps = {
|
54
|
-
baseUrl: '',
|
55
|
-
loading: null,
|
56
|
-
};
|
57
|
-
|
58
53
|
export { BlockletContext, BlockletProvider, Consumer as BlockletConsumer, useBlockletContext };
|
package/src/Button/wrap.jsx
CHANGED
@@ -25,7 +25,8 @@ const extendedColors = {
|
|
25
25
|
* loading?: boolean,
|
26
26
|
* forwardedRef?: import('react').ForwardedRef<any>,
|
27
27
|
* color?: MuiButtonProps['color'] | 'reverse' | 'did'
|
28
|
-
* }
|
28
|
+
* }} CustomButtonProps
|
29
|
+
* @typedef { CustomButtonProps & Omit<MuiButtonProps, 'color'> } ButtonProps
|
29
30
|
*/
|
30
31
|
|
31
32
|
/**
|
package/src/ButtonGroup/index.js
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
import ButtonGroup from '@mui/material/ButtonGroup';
|
2
2
|
import wrap from '../Button/wrap';
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
/**
|
5
|
+
* @typedef {import('@mui/material').ButtonGroupProps} MuiButtonGroupProps
|
6
|
+
* @typedef {import('../Button/wrap').CustomButtonProps & Omit<MuiButtonGroupProps, 'color'>} ButtonGroupProps
|
7
|
+
*/
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @deprecated 建议直接使用 @mui/material/ButtonGroup
|
11
|
+
* @type {React.ForwardRefExoticComponent<React.PropsWithoutRef<ButtonGroupProps> & React.RefAttributes<HTMLButtonElement>>}
|
12
|
+
*/
|
13
|
+
const ButtonGroupComponent = wrap(ButtonGroup);
|
14
|
+
|
15
|
+
// 该定制组件原本目的是调整 ButtonGroup 的圆角, 但最新设计规范已经不再使用较大的圆角, 改为使用 mui button 默认的圆角
|
16
|
+
export default ButtonGroupComponent;
|
@@ -1,24 +1,42 @@
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
1
2
|
import { useState, useEffect, useRef } from 'react';
|
2
3
|
import styled from '@emotion/styled';
|
3
|
-
import PropTypes from 'prop-types';
|
4
4
|
import noop from 'lodash/noop';
|
5
5
|
|
6
|
-
export
|
6
|
+
export interface CardSelectorProps {
|
7
|
+
list?: Array<{ src: string; name: string }> | Array<(i: number) => React.ReactNode>;
|
8
|
+
width?: number;
|
9
|
+
height?: number;
|
10
|
+
cardSpace?: number;
|
11
|
+
onSelect?: (index: number) => void;
|
12
|
+
defaultIndex?: number;
|
13
|
+
}
|
14
|
+
|
15
|
+
export default function CardSelector({
|
16
|
+
list = [],
|
17
|
+
width = 300,
|
18
|
+
height = 400,
|
19
|
+
cardSpace = 40,
|
20
|
+
onSelect = noop,
|
21
|
+
defaultIndex = 0,
|
22
|
+
}: CardSelectorProps) {
|
7
23
|
const [selectedId, setSelectedId] = useState(0);
|
8
24
|
const [translateX, setTranslateX] = useState(0);
|
9
|
-
const outterCon = useRef(null);
|
25
|
+
const outterCon = useRef<HTMLDivElement | null>(null);
|
10
26
|
|
11
27
|
// 选择卡片
|
12
|
-
const selectedItem = (i) => {
|
28
|
+
const selectedItem = (i: number) => {
|
13
29
|
if (i < 0 || i > list.length - 1) {
|
14
30
|
return;
|
15
31
|
}
|
16
32
|
setSelectedId(i);
|
17
33
|
|
18
|
-
|
19
|
-
|
34
|
+
if (outterCon.current) {
|
35
|
+
// 外部容器大小
|
36
|
+
const outerWidth = outterCon.current.clientWidth;
|
20
37
|
|
21
|
-
|
38
|
+
setTranslateX(i * (width + cardSpace) - (outerWidth - width) / 2 + cardSpace * 0.5);
|
39
|
+
}
|
22
40
|
|
23
41
|
onSelect(i);
|
24
42
|
};
|
@@ -26,19 +44,18 @@ export default function CardSelector({ list, width, height, cardSpace, onSelect,
|
|
26
44
|
useEffect(() => {
|
27
45
|
selectedItem(defaultIndex);
|
28
46
|
|
29
|
-
|
30
|
-
outterCon.current.addEventListener('touchmove', func, { passive: false });
|
47
|
+
outterCon.current?.addEventListener('touchmove', (e) => e.preventDefault(), { passive: false });
|
31
48
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
32
49
|
}, []);
|
33
50
|
|
34
|
-
let startX;
|
51
|
+
let startX: number;
|
35
52
|
|
36
|
-
const touchstart = (e) => {
|
53
|
+
const touchstart: React.TouchEventHandler<HTMLDivElement> = (e) => {
|
37
54
|
const point = e.touches[0];
|
38
55
|
startX = point.clientX;
|
39
56
|
};
|
40
57
|
|
41
|
-
const touchend = (e) => {
|
58
|
+
const touchend: React.TouchEventHandler<HTMLDivElement> = (e) => {
|
42
59
|
const point = e.changedTouches[0];
|
43
60
|
const diffX = startX - point.clientX;
|
44
61
|
|
@@ -52,7 +69,7 @@ export default function CardSelector({ list, width, height, cardSpace, onSelect,
|
|
52
69
|
};
|
53
70
|
|
54
71
|
return (
|
55
|
-
<
|
72
|
+
<Container ref={outterCon} onTouchStart={touchstart} onTouchEnd={touchend}>
|
56
73
|
<div className="card-container" style={{ transform: `translate(${-translateX}px, 0)` }}>
|
57
74
|
{list.map((e, i) => {
|
58
75
|
if (e instanceof Function) {
|
@@ -79,11 +96,11 @@ export default function CardSelector({ list, width, height, cardSpace, onSelect,
|
|
79
96
|
);
|
80
97
|
})}
|
81
98
|
</div>
|
82
|
-
</
|
99
|
+
</Container>
|
83
100
|
);
|
84
101
|
}
|
85
102
|
|
86
|
-
const
|
103
|
+
const Container = styled.div`
|
87
104
|
overflow: hidden;
|
88
105
|
mask-image: linear-gradient(to left, transparent, black 3%, black 97%, transparent);
|
89
106
|
overflow: hidden;
|
@@ -118,21 +135,3 @@ const Contianer = styled.div`
|
|
118
135
|
}
|
119
136
|
}
|
120
137
|
`;
|
121
|
-
|
122
|
-
CardSelector.propTypes = {
|
123
|
-
list: PropTypes.array,
|
124
|
-
width: PropTypes.number,
|
125
|
-
height: PropTypes.number,
|
126
|
-
cardSpace: PropTypes.number,
|
127
|
-
onSelect: PropTypes.func,
|
128
|
-
defaultIndex: PropTypes.number,
|
129
|
-
};
|
130
|
-
|
131
|
-
CardSelector.defaultProps = {
|
132
|
-
list: '',
|
133
|
-
width: 300,
|
134
|
-
height: 400,
|
135
|
-
cardSpace: 40,
|
136
|
-
onSelect: noop,
|
137
|
-
defaultIndex: 0,
|
138
|
-
};
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import { styled } from '../Theme';
|
2
|
+
|
3
|
+
export default function Center({
|
4
|
+
children,
|
5
|
+
relative = 'screen',
|
6
|
+
}: {
|
7
|
+
children: React.ReactNode;
|
8
|
+
/**
|
9
|
+
* 容器相对尺寸,默认相对屏幕(screen),可设置为父容器(parent)
|
10
|
+
*/
|
11
|
+
relative?: 'screen' | 'parent';
|
12
|
+
}) {
|
13
|
+
let style = {};
|
14
|
+
|
15
|
+
if (relative === 'parent') {
|
16
|
+
style = {
|
17
|
+
width: '100%',
|
18
|
+
height: '100%',
|
19
|
+
};
|
20
|
+
}
|
21
|
+
|
22
|
+
return <Div style={style}>{children}</Div>;
|
23
|
+
}
|
24
|
+
|
25
|
+
const Div = styled('div')`
|
26
|
+
flex: 1;
|
27
|
+
width: 100vw;
|
28
|
+
height: 100vh;
|
29
|
+
|
30
|
+
display: flex;
|
31
|
+
justify-content: center;
|
32
|
+
align-items: center;
|
33
|
+
`;
|
@@ -1,11 +1,24 @@
|
|
1
|
-
|
1
|
+
/* eslint-disable no-unused-vars */
|
2
2
|
import Tooltip from '@mui/material/Tooltip';
|
3
3
|
import { green } from '@mui/material/colors';
|
4
4
|
import CopyIcon from '@mui/icons-material/ContentCopy';
|
5
5
|
import CheckIcon from '@mui/icons-material/Check';
|
6
6
|
import useCopy from './hook';
|
7
7
|
|
8
|
-
export
|
8
|
+
export interface CopyButtonProps extends React.HTMLAttributes<HTMLSpanElement> {
|
9
|
+
content?: string;
|
10
|
+
locale?: 'en' | 'zh';
|
11
|
+
render?: (props: { copyButton: React.ReactNode; containerRef: React.RefObject<HTMLElement> }) => React.ReactNode;
|
12
|
+
showTooltip?: boolean;
|
13
|
+
}
|
14
|
+
|
15
|
+
export default function CopyButton({
|
16
|
+
content = '',
|
17
|
+
locale = 'en',
|
18
|
+
render,
|
19
|
+
showTooltip = true,
|
20
|
+
...rest
|
21
|
+
}: CopyButtonProps) {
|
9
22
|
const { containerRef, copied, copy, texts } = useCopy({ content, locale });
|
10
23
|
const iconStyle = {
|
11
24
|
fontSize: '1em',
|
@@ -28,17 +41,3 @@ export default function CopyButton({ content, locale, render, showTooltip, ...re
|
|
28
41
|
}
|
29
42
|
return copyButton;
|
30
43
|
}
|
31
|
-
|
32
|
-
CopyButton.propTypes = {
|
33
|
-
content: PropTypes.string,
|
34
|
-
locale: PropTypes.oneOf(['en', 'zh']),
|
35
|
-
render: PropTypes.func,
|
36
|
-
showTooltip: PropTypes.bool,
|
37
|
-
};
|
38
|
-
|
39
|
-
CopyButton.defaultProps = {
|
40
|
-
content: '',
|
41
|
-
locale: 'en',
|
42
|
-
render: undefined,
|
43
|
-
showTooltip: true,
|
44
|
-
};
|
@@ -12,20 +12,20 @@ const translations = {
|
|
12
12
|
},
|
13
13
|
};
|
14
14
|
|
15
|
-
export default function useCopy({ content, locale = 'en' }) {
|
15
|
+
export default function useCopy({ content, locale = 'en' }: { content?: string; locale?: 'en' | 'zh' }) {
|
16
16
|
const [copied, setCopied] = useState(false);
|
17
|
-
const containerRef = useRef();
|
18
|
-
const copy = (e) => {
|
17
|
+
const containerRef = useRef<HTMLElement | null>(null);
|
18
|
+
const copy = (e: React.MouseEvent) => {
|
19
19
|
if (e) {
|
20
20
|
e.stopPropagation();
|
21
21
|
}
|
22
22
|
|
23
|
-
Copy(content || containerRef.current
|
23
|
+
Copy(content || (containerRef.current?.textContent ?? ''));
|
24
24
|
setCopied(true);
|
25
25
|
};
|
26
26
|
|
27
27
|
useEffect(() => {
|
28
|
-
let timer
|
28
|
+
let timer: ReturnType<typeof setTimeout>;
|
29
29
|
if (copied) {
|
30
30
|
timer = setTimeout(() => setCopied(false), 2000);
|
31
31
|
}
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import PropTypes from 'prop-types';
|
2
1
|
import { useSize } from 'ahooks';
|
3
2
|
import Tooltip from '@mui/material/Tooltip';
|
4
3
|
|
@@ -27,7 +26,16 @@ const UnstyledContainer = styled('span')`
|
|
27
26
|
cursor: pointer;
|
28
27
|
`;
|
29
28
|
|
30
|
-
export
|
29
|
+
export interface ClickToCopyProps extends React.HTMLAttributes<HTMLDivElement> {
|
30
|
+
content?: string;
|
31
|
+
locale?: 'en' | 'zh';
|
32
|
+
tip?: string;
|
33
|
+
tipPlacement?: string;
|
34
|
+
copiedTip?: string;
|
35
|
+
unstyled?: boolean;
|
36
|
+
}
|
37
|
+
|
38
|
+
export default function ClickToCopy(props: ClickToCopyProps) {
|
31
39
|
const newProps = mergeProps(props, ClickToCopy, ['style']);
|
32
40
|
const { children, content, tip, copiedTip, tipPlacement, locale, style, unstyled, ...rest } = newProps;
|
33
41
|
const { containerRef, copied, copy, texts } = useCopy({ content, locale });
|
@@ -38,7 +46,7 @@ export default function ClickToCopy(props) {
|
|
38
46
|
const size = useSize(document.body);
|
39
47
|
const width = size?.width || 0;
|
40
48
|
|
41
|
-
const onCopy = (e) => {
|
49
|
+
const onCopy = (e: React.MouseEvent<HTMLElement>) => {
|
42
50
|
copy(e);
|
43
51
|
|
44
52
|
if (width < 600) {
|
@@ -61,24 +69,11 @@ export default function ClickToCopy(props) {
|
|
61
69
|
return <>{contentChild}</>;
|
62
70
|
}
|
63
71
|
|
64
|
-
ClickToCopy.propTypes = {
|
65
|
-
children: PropTypes.any.isRequired,
|
66
|
-
content: PropTypes.string,
|
67
|
-
tip: PropTypes.string,
|
68
|
-
tipPlacement: PropTypes.string,
|
69
|
-
copiedTip: PropTypes.string,
|
70
|
-
locale: PropTypes.oneOf(['en', 'zh']),
|
71
|
-
style: PropTypes.object,
|
72
|
-
// 仅提供点击复制功能, 不提供样式
|
73
|
-
unstyled: PropTypes.bool,
|
74
|
-
};
|
75
|
-
|
76
72
|
ClickToCopy.defaultProps = {
|
77
73
|
content: '',
|
78
74
|
tip: '',
|
79
75
|
copiedTip: '',
|
80
76
|
tipPlacement: 'right',
|
81
|
-
locale: 'en',
|
82
|
-
style: {},
|
77
|
+
locale: 'en' as const,
|
83
78
|
unstyled: false,
|
84
79
|
};
|
@@ -1,6 +1,5 @@
|
|
1
1
|
/* eslint-disable react/no-danger */
|
2
2
|
import { useState } from 'react';
|
3
|
-
import PropTypes from 'prop-types';
|
4
3
|
import Copy from 'copy-to-clipboard';
|
5
4
|
|
6
5
|
import hljs from 'highlight.js/lib/core';
|
@@ -56,9 +55,22 @@ hljs.registerLanguage('objectivec', objectivec);
|
|
56
55
|
hljs.registerLanguage('oc', objectivec);
|
57
56
|
hljs.registerLanguage('markdown', markdown);
|
58
57
|
|
59
|
-
export
|
58
|
+
export interface CodeBlockProps extends React.HTMLAttributes<HTMLPreElement> {
|
59
|
+
code?: string;
|
60
|
+
language?: string;
|
61
|
+
children?: React.ReactNode;
|
62
|
+
dark?: boolean;
|
63
|
+
}
|
64
|
+
|
65
|
+
export default function CodeBlock({
|
66
|
+
code = '',
|
67
|
+
language = 'text',
|
68
|
+
children = null,
|
69
|
+
dark = true,
|
70
|
+
...rest
|
71
|
+
}: CodeBlockProps) {
|
60
72
|
const [copied, setCopied] = useState(false);
|
61
|
-
const source = code || children;
|
73
|
+
const source = code || (children as string);
|
62
74
|
|
63
75
|
const onCopy = () => {
|
64
76
|
if (copied) {
|
@@ -106,20 +118,6 @@ export default function CodeBlock({ code, language, children, dark, ...rest }) {
|
|
106
118
|
return originEl;
|
107
119
|
}
|
108
120
|
|
109
|
-
CodeBlock.propTypes = {
|
110
|
-
code: PropTypes.string,
|
111
|
-
language: PropTypes.string,
|
112
|
-
children: PropTypes.any,
|
113
|
-
dark: PropTypes.bool,
|
114
|
-
};
|
115
|
-
|
116
|
-
CodeBlock.defaultProps = {
|
117
|
-
code: '',
|
118
|
-
language: 'text',
|
119
|
-
children: null,
|
120
|
-
dark: true,
|
121
|
-
};
|
122
|
-
|
123
121
|
const fontFamily = 'source-code-pro, Menlo, Monaco, Consolas, Courier New, monospace !important';
|
124
122
|
const Pre = styled('pre')`
|
125
123
|
font-family: ${fontFamily};
|
@@ -1,7 +1,6 @@
|
|
1
1
|
/* eslint-disable react/no-unused-prop-types */
|
2
2
|
/* eslint-disable react/static-property-placement */
|
3
3
|
import React from 'react';
|
4
|
-
import PropTypes from 'prop-types';
|
5
4
|
import axios from 'axios';
|
6
5
|
import Typography from '@mui/material/Typography';
|
7
6
|
import CircularProgress from '@mui/material/CircularProgress';
|
@@ -11,7 +10,11 @@ import { warn as deprecatedWarn } from '../Util/deprecate';
|
|
11
10
|
import Button from '../Button';
|
12
11
|
import { styled } from '../Theme';
|
13
12
|
|
14
|
-
export function submitContactForm(
|
13
|
+
export function submitContactForm(
|
14
|
+
{ formId, portalId }: { formId: string; portalId: string },
|
15
|
+
fields: Record<string, string>,
|
16
|
+
context: Record<string, string>
|
17
|
+
) {
|
15
18
|
const url = `https://api.hsforms.com/submissions/v3/integration/submit/${portalId}/${formId}`;
|
16
19
|
return axios
|
17
20
|
.post(url, {
|
@@ -27,38 +30,45 @@ export function submitContactForm({ formId, portalId }, fields, context) {
|
|
27
30
|
.catch((res) => (res.data ? res.data.message : 'Form Submit Failed'));
|
28
31
|
}
|
29
32
|
|
30
|
-
export
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
layout: PropTypes.oneOf(['horizontal', 'vertical']),
|
40
|
-
fields: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
|
41
|
-
};
|
33
|
+
export interface ContactFormProps extends React.HTMLAttributes<HTMLFormElement> {
|
34
|
+
portalId?: string;
|
35
|
+
formId?: string;
|
36
|
+
title?: string;
|
37
|
+
button?: string;
|
38
|
+
successMessage?: string;
|
39
|
+
layout?: 'horizontal' | 'vertical';
|
40
|
+
fields?: string | string[];
|
41
|
+
}
|
42
42
|
|
43
|
+
export default class ContactForm extends React.Component<
|
44
|
+
ContactFormProps,
|
45
|
+
{
|
46
|
+
loading: boolean;
|
47
|
+
errorMessage: string;
|
48
|
+
successMessage: string;
|
49
|
+
[x: string]: string | boolean;
|
50
|
+
}
|
51
|
+
> {
|
43
52
|
static defaultProps = {
|
44
|
-
style: {},
|
45
53
|
className: '',
|
46
54
|
portalId: '4796488',
|
47
55
|
formId: '929a510f-34f4-4251-98b3-34175200aebd',
|
48
56
|
title: undefined,
|
49
57
|
button: '',
|
50
|
-
layout: 'vertical',
|
58
|
+
layout: 'vertical' as const,
|
51
59
|
successMessage: 'Form Submit Success',
|
52
60
|
fields: ['Email', 'First Name', 'Last Name'],
|
53
61
|
};
|
54
62
|
|
55
|
-
|
63
|
+
fields: string[];
|
64
|
+
|
65
|
+
constructor(props: ContactFormProps) {
|
56
66
|
super(props);
|
57
67
|
|
58
68
|
if (typeof props.fields === 'string') {
|
59
69
|
this.fields = props.fields.split(',').map((x) => x.trim());
|
60
70
|
} else {
|
61
|
-
this.fields = props.fields
|
71
|
+
this.fields = props.fields!;
|
62
72
|
}
|
63
73
|
|
64
74
|
this.state = {
|
@@ -68,6 +78,7 @@ export default class ContactForm extends React.Component {
|
|
68
78
|
};
|
69
79
|
|
70
80
|
this.fields.forEach((x) => {
|
81
|
+
// @ts-ignore
|
71
82
|
this.state[x] = '';
|
72
83
|
});
|
73
84
|
deprecatedWarn('ContactForm');
|
@@ -108,7 +119,7 @@ export default class ContactForm extends React.Component {
|
|
108
119
|
required
|
109
120
|
key={x}
|
110
121
|
type="text"
|
111
|
-
value={this.state[x]}
|
122
|
+
value={this.state[x] as string}
|
112
123
|
onChange={this.getInputHandler(x)}
|
113
124
|
className="input"
|
114
125
|
placeholder={x}
|
@@ -146,20 +157,20 @@ export default class ContactForm extends React.Component {
|
|
146
157
|
);
|
147
158
|
}
|
148
159
|
|
149
|
-
onSubmit = async (e) => {
|
160
|
+
onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
150
161
|
e.preventDefault();
|
151
162
|
this.setState({ loading: true });
|
152
163
|
|
153
164
|
try {
|
154
165
|
const message = await submitContactForm(
|
155
|
-
{ formId: this.props.formId
|
156
|
-
this.fields.reduce((obj, x) => {
|
157
|
-
obj[x] = this.state[x];
|
166
|
+
{ formId: this.props.formId!, portalId: this.props.portalId! },
|
167
|
+
this.fields.reduce<Record<string, string>>((obj, x) => {
|
168
|
+
obj[x] = this.state[x] as string;
|
158
169
|
return obj;
|
159
170
|
}, {}),
|
160
171
|
{
|
161
172
|
pageUri: window.location.href,
|
162
|
-
pageName:
|
173
|
+
pageName: document.title,
|
163
174
|
}
|
164
175
|
);
|
165
176
|
|
@@ -170,14 +181,14 @@ export default class ContactForm extends React.Component {
|
|
170
181
|
} catch (err) {
|
171
182
|
this.setState({
|
172
183
|
loading: false,
|
173
|
-
errorMessage: err ? err.message : 'Form submit failed',
|
184
|
+
errorMessage: err ? (err as Error).message : 'Form submit failed',
|
174
185
|
});
|
175
186
|
}
|
176
187
|
};
|
177
188
|
|
178
189
|
getInputHandler =
|
179
|
-
(name, state = {}) =>
|
180
|
-
(e) => {
|
190
|
+
(name: string, state = {}) =>
|
191
|
+
(e: React.ChangeEvent<HTMLInputElement>) => {
|
181
192
|
this.setState(
|
182
193
|
Object.assign(state, {
|
183
194
|
[name]: e.target.value,
|
@@ -186,10 +197,17 @@ export default class ContactForm extends React.Component {
|
|
186
197
|
};
|
187
198
|
}
|
188
199
|
|
200
|
+
interface FormProps {
|
201
|
+
layout: 'vertical' | 'horizontal';
|
202
|
+
fieldCount: number;
|
203
|
+
}
|
204
|
+
|
189
205
|
// prettier-ignore
|
190
|
-
const getInputWidth = props => (props.layout === 'vertical' ? '100%' : `${Math.max(95 / (props.fieldCount + 1), 20)}%`);
|
206
|
+
const getInputWidth = (props: FormProps) => (props.layout === 'vertical' ? '100%' : `${Math.max(95 / (props.fieldCount + 1), 20)}%`);
|
191
207
|
|
192
|
-
const Form = styled('form'
|
208
|
+
const Form = styled('form', {
|
209
|
+
shouldForwardProp: (prop) => prop !== 'layout' && prop !== 'fieldCount',
|
210
|
+
})<FormProps>`
|
193
211
|
display: flex;
|
194
212
|
flex-direction: column;
|
195
213
|
justify-content: center;
|