@arcblock/ux 2.10.65 → 2.10.67
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.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;
|