@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.
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;