@arcblock/ux 2.10.65 → 2.10.66

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. package/lib/ActionButton/index.d.ts +1 -1
  2. package/lib/Alert/index.d.ts +1 -1
  3. package/lib/AnimationWaiter/index.d.ts +27 -15
  4. package/lib/AnimationWaiter/index.js +15 -14
  5. package/lib/Async/index.d.ts +50 -17
  6. package/lib/Badge/index.d.ts +1 -1
  7. package/lib/Badge/index.js +7 -1
  8. package/lib/BlockletContext/index.d.ts +12 -28
  9. package/lib/BlockletContext/index.js +3 -21
  10. package/lib/Button/wrap.d.ts +5 -3
  11. package/lib/Button/wrap.js +2 -1
  12. package/lib/ButtonGroup/index.d.ts +12 -2
  13. package/lib/ButtonGroup/index.js +13 -3
  14. package/lib/CardSelector/index.d.ts +11 -33
  15. package/lib/CardSelector/index.js +16 -32
  16. package/lib/Center/index.d.ts +6 -21
  17. package/lib/Center/index.js +2 -17
  18. package/lib/ClickToCopy/copy-button.d.ts +9 -26
  19. package/lib/ClickToCopy/copy-button.js +5 -17
  20. package/lib/ClickToCopy/hook.d.ts +11 -5
  21. package/lib/ClickToCopy/hook.js +3 -3
  22. package/lib/ClickToCopy/index.d.ts +18 -29
  23. package/lib/ClickToCopy/index.js +0 -13
  24. package/lib/CodeBlock/LightBox.d.ts +1 -1
  25. package/lib/CodeBlock/index.d.ts +7 -26
  26. package/lib/CodeBlock/index.js +4 -17
  27. package/lib/Colors/index.d.ts +2 -2
  28. package/lib/Colors/themes/default.d.ts +54 -61
  29. package/lib/Colors/themes/temp.d.ts +35 -35
  30. package/lib/ContactForm/index.d.ts +26 -30
  31. package/lib/ContactForm/index.js +7 -17
  32. package/lib/Dialog/confirm.d.ts +3 -3
  33. package/lib/Dialog/confirm.js +2 -2
  34. package/lib/Earth/index.d.ts +10 -1
  35. package/lib/Header/auto-hidden.d.ts +6 -11
  36. package/lib/Header/auto-hidden.js +0 -5
  37. package/lib/Header/header.d.ts +20 -51
  38. package/lib/Header/header.js +10 -42
  39. package/lib/Header/index.d.ts +2 -2
  40. package/lib/Header/responsive-header.d.ts +10 -22
  41. package/lib/Header/responsive-header.js +1 -13
  42. package/lib/Icon/image.d.ts +8 -36
  43. package/lib/Icon/image.js +6 -24
  44. package/lib/Icon/index.d.ts +9 -1
  45. package/lib/Icon/index.js +6 -25
  46. package/lib/NavMenu/index.d.ts +1 -1
  47. package/lib/NavMenu/nav-menu.d.ts +37 -51
  48. package/lib/NavMenu/nav-menu.js +47 -102
  49. package/lib/NavMenu/style.d.ts +8 -2
  50. package/lib/NavMenu/style.js +3 -1
  51. package/lib/PageScroller/index.d.ts +13 -1
  52. package/lib/Passport/passport.js +1 -1
  53. package/lib/PricingTable/index.d.ts +3 -1
  54. package/lib/RelativeTime/index.d.ts +1 -1
  55. package/lib/Screenshot/BaseScreenshot/index.js +1 -1
  56. package/lib/SplitButton/index.d.ts +0 -19
  57. package/lib/SplitButton/index.js +7 -27
  58. package/lib/TextCollapse/index.d.ts +10 -1
  59. package/lib/Theme/index.d.ts +5 -13
  60. package/lib/Theme/index.js +4 -11
  61. package/lib/Theme/theme-provider.d.ts +16 -18
  62. package/lib/Theme/theme.d.ts +37 -11
  63. package/lib/Theme/theme.js +13 -22
  64. package/lib/Util/constant.d.ts +31 -31
  65. package/lib/Util/deprecate.d.ts +7 -5
  66. package/lib/Util/federated.d.ts +21 -21
  67. package/lib/Util/federated.js +1 -1
  68. package/lib/Util/index.d.ts +59 -60
  69. package/lib/Util/index.js +16 -43
  70. package/lib/Util/passport.d.ts +6 -6
  71. package/lib/Util/wallet.d.ts +15 -3
  72. package/lib/WebWalletSWKeeper/index.js +1 -1
  73. package/lib/global.d.ts +13 -0
  74. package/lib/index.d.ts +4 -2
  75. package/lib/index.js +2 -2
  76. package/lib/type.d.ts +31 -1
  77. package/package.json +5 -5
  78. package/src/AnimationWaiter/index.jsx +15 -14
  79. package/src/Async/{index.jsx → index.tsx} +13 -4
  80. package/src/Badge/index.jsx +8 -1
  81. package/src/BlockletContext/{index.jsx → index.tsx} +17 -22
  82. package/src/Button/wrap.jsx +2 -1
  83. package/src/ButtonGroup/index.js +13 -3
  84. package/src/CardSelector/{index.jsx → index.tsx} +32 -33
  85. package/src/Center/index.tsx +33 -0
  86. package/src/ClickToCopy/{copy-button.jsx → copy-button.tsx} +15 -16
  87. package/src/ClickToCopy/{hook.js → hook.ts} +5 -5
  88. package/src/ClickToCopy/{index.jsx → index.tsx} +12 -17
  89. package/src/CodeBlock/{index.jsx → index.tsx} +15 -17
  90. package/src/ContactForm/{index.jsx → index.tsx} +47 -29
  91. package/src/Dialog/confirm.jsx +2 -2
  92. package/src/Header/{auto-hidden.jsx → auto-hidden.tsx} +6 -7
  93. package/src/Header/{header.jsx → header.tsx} +32 -46
  94. package/src/Header/{responsive-header.jsx → responsive-header.tsx} +9 -15
  95. package/src/Icon/{image.jsx → image.tsx} +19 -22
  96. package/src/Icon/{index.jsx → index.tsx} +22 -24
  97. package/src/NavMenu/{nav-menu.jsx → nav-menu.tsx} +161 -144
  98. package/src/NavMenu/{style.js → style.ts} +9 -1
  99. package/src/Passport/passport.jsx +1 -1
  100. package/src/Screenshot/BaseScreenshot/index.jsx +1 -1
  101. package/src/SplitButton/index.tsx +10 -23
  102. package/src/Theme/{index.js → index.ts} +6 -12
  103. package/src/Theme/{theme-provider.jsx → theme-provider.tsx} +10 -2
  104. package/src/Theme/{theme.js → theme.ts} +54 -23
  105. package/src/Util/{deprecate.jsx → deprecate.tsx} +8 -4
  106. package/src/Util/{federated.js → federated.ts} +3 -3
  107. package/src/Util/{index.js → index.ts} +85 -59
  108. package/src/Util/{passport.js → passport.ts} +2 -2
  109. package/src/Util/{wallet.js → wallet.ts} +1 -1
  110. package/src/WebWalletSWKeeper/index.jsx +1 -1
  111. package/src/global.d.ts +13 -0
  112. package/src/{index.js → index.ts} +2 -2
  113. package/src/type.d.ts +31 -1
  114. package/src/Center/index.jsx +0 -41
  115. /package/src/CodeBlock/{LightBox.jsx → LightBox.tsx} +0 -0
  116. /package/src/Colors/{index.js → index.ts} +0 -0
  117. /package/src/Colors/themes/{default.js → default.ts} +0 -0
  118. /package/src/Colors/themes/{temp.js → temp.ts} +0 -0
  119. /package/src/Header/{index.js → index.ts} +0 -0
  120. /package/src/NavMenu/{index.js → index.ts} +0 -0
  121. /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 {Object} animationData lottie json 动画数据
13
- * @param {Number} size 动画的尺寸,单位px
14
- * @param {String|Array} message 动画下方的文字;数组情况下会在一定时间切换文案
15
- * @param {Number} messageDuration 动画下方的文字为数组时,每个文案的持续时间;默认5000ms
16
- * @param {Number} messageLoop 动画下方的文字为数组时,文案是否循环播放
17
- * @param {Array} tips 底部的提示元素
18
- * @param {Number} tipsDuration 底部提示的切换时间,单位毫秒,默认3000ms
19
- * @param {Number} speed 动画默认的播放速度
20
- * @param {Number} maybeDuration 整个动画大概的持续时间,单位毫秒,用于计算增量下的动画速度,默认两分钟(120000ms)
21
- * @param {Number} increaseSpeed maybeDuration 时间下增加的速度,默认为0(不增加速度)
22
- * @returns element
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.any,
172
+ animationData: PropTypes.oneOfType([PropTypes.object, PropTypes.oneOf([null])]),
172
173
  size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
173
- message: PropTypes.any,
174
+ message: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.node)]),
174
175
  messageDuration: PropTypes.number,
175
176
  messageLoop: PropTypes.bool,
176
- tips: PropTypes.array,
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(importComponent, key = 'default', showProgress = true) {
6
- class AsyncComponent extends React.Component {
7
- constructor(props) {
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 = {
@@ -74,7 +74,14 @@ Badge.defaultProps = {
74
74
  };
75
75
 
76
76
  export default withDeprecated(
77
- forwardRef((props, ref) => <Badge {...props} forwardedRef={ref} />),
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
- * @param {object} props
12
- * @param {string} props.baseUrl baseUrl 为 blocklet origin + blocklet prefix
13
- * @param {any} props.children
14
- * @returns
15
- */
16
- function BlockletProvider({ children, baseUrl, loading }) {
17
- const [blockletData, setBlockletData] = useState(null);
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 };
@@ -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
- * } & Omit<MuiButtonProps, 'color'>} ButtonProps
28
+ * }} CustomButtonProps
29
+ * @typedef { CustomButtonProps & Omit<MuiButtonProps, 'color'> } ButtonProps
29
30
  */
30
31
 
31
32
  /**
@@ -1,6 +1,16 @@
1
1
  import ButtonGroup from '@mui/material/ButtonGroup';
2
2
  import wrap from '../Button/wrap';
3
3
 
4
- // deprecated, ux ButtonGroup 组件废弃, 建议直接使用 @mui/material/ButtonGroup
5
- // (该定制组件原本目的是调整 ButtonGroup 的圆角, 但最新设计规范已经不再使用较大的圆角, 改为使用 mui button 默认的圆角)
6
- export default wrap(ButtonGroup);
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 default function CardSelector({ list, width, height, cardSpace, onSelect, defaultIndex }) {
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
- const outerWidth = outterCon.current.clientWidth;
34
+ if (outterCon.current) {
35
+ // 外部容器大小
36
+ const outerWidth = outterCon.current.clientWidth;
20
37
 
21
- setTranslateX(i * (width + cardSpace) - (outerWidth - width) / 2 + cardSpace * 0.5);
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
- const func = (e) => e.preventDefault();
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
- <Contianer ref={outterCon} onTouchStart={touchstart} onTouchEnd={touchend}>
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
- </Contianer>
99
+ </Container>
83
100
  );
84
101
  }
85
102
 
86
- const Contianer = styled.div`
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
- import PropTypes from 'prop-types';
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 default function CopyButton({ content, locale, render, showTooltip, ...rest }) {
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.textContent);
23
+ Copy(content || (containerRef.current?.textContent ?? ''));
24
24
  setCopied(true);
25
25
  };
26
26
 
27
27
  useEffect(() => {
28
- let timer = null;
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 default function ClickToCopy(props) {
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 default function CodeBlock({ code, language, children, dark, ...rest }) {
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({ formId, portalId }, fields, context) {
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 default class ContactForm extends React.Component {
31
- static propTypes = {
32
- style: PropTypes.object,
33
- className: PropTypes.string,
34
- portalId: PropTypes.string,
35
- formId: PropTypes.string,
36
- title: PropTypes.string,
37
- button: PropTypes.string,
38
- successMessage: PropTypes.string,
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
- constructor(props) {
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, portalId: this.props.portalId },
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: window.location.title,
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;