Skip to content

Commit 20183e2

Browse files
JackWang032jialan
andauthored
feat: refactor copyIcon component (#329)
* feat: refactor copyIcon component * test: add test case for CopyButton * feat: rename CopyButton to Copy * test: fix copy test --------- Co-authored-by: jialan <[email protected]>
1 parent 1271de6 commit 20183e2

File tree

11 files changed

+171
-146
lines changed

11 files changed

+171
-146
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"@testing-library/jest-dom": "^5.16.5",
7272
"@testing-library/react": "^13.4.0",
7373
"@testing-library/react-hooks": "^8.0.1",
74+
"@testing-library/user-event": "^14.4.3",
7475
"@typed-mxgraph/typed-mxgraph": "^1.0.7",
7576
"@types/jest": "^29.2.3",
7677
"@types/lodash": "^4.14.191",
@@ -112,7 +113,8 @@
112113
"mxgraph": "^4.2.2",
113114
"rc-drawer": "~5.1.0",
114115
"rc-virtual-list": "^3.4.13",
115-
"showdown": "^1.9.0"
116+
"showdown": "^1.9.0",
117+
"use-clippy": "^1.0.9"
116118
},
117119
"config": {
118120
"commitizen": {

pnpm-lock.yaml

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/copy/__tests__/copy.test.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
import { render, fireEvent, cleanup } from '@testing-library/react';
3+
import '@testing-library/jest-dom/extend-expect';
4+
import userEvent from '@testing-library/user-event';
5+
import Copy from '..';
6+
7+
describe('test Copy', () => {
8+
const mockText = 'This is a mock text';
9+
10+
afterEach(() => {
11+
cleanup();
12+
});
13+
14+
it('should copy text to clipboard on click', () => {
15+
const user = userEvent.setup({ writeToClipboard: true });
16+
const mockCopy = jest.fn();
17+
const { container } = render(<Copy text={mockText} onCopy={(text) => mockCopy(text)} />);
18+
const button = container.querySelector('.dtc-copy');
19+
20+
expect(button).toBeInTheDocument();
21+
22+
fireEvent.click(button!);
23+
expect(mockCopy).toHaveBeenCalledWith(mockText);
24+
user.paste().then((value) => {
25+
expect(value).toEqual(mockText);
26+
});
27+
});
28+
29+
it('should render with custom button', () => {
30+
const user = userEvent.setup({ writeToClipboard: true });
31+
const { getByText } = render(
32+
<Copy text={mockText} button={<button>测试复制文本</button>} hideTooltip />
33+
);
34+
const customButton = getByText('测试复制文本');
35+
36+
expect(customButton).toBeInTheDocument();
37+
38+
fireEvent.mouseEnter(customButton);
39+
setTimeout(() => {
40+
expect(document.body.querySelector('.ant-tooltip')).not.toBeInTheDocument();
41+
}, 0);
42+
43+
fireEvent.click(customButton);
44+
user.paste().then((value) => {
45+
expect(value).toEqual(mockText);
46+
});
47+
});
48+
});
Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,14 @@
1-
---
2-
title: CopyIcon 复制文本
3-
group: 组件
4-
toc: content
5-
demo:
6-
cols: 2
7-
---
8-
9-
# CopyIcon 复制文本
10-
11-
## 何时使用
12-
13-
复制文本到粘贴版
14-
15-
## 示例
16-
17-
```jsx
18-
/**
19-
* title: "点击按钮,复制文本。"
20-
*/
211
import React from 'react';
22-
import { CopyIcon } from 'dt-react-component';
2+
import { Copy } from 'dt-react-component';
233

244
const text =
255
'基于 ant-design 的 React UI 组件库。 主要用于中,后台产品。我们的目标是满足更具体的业务场景组件。 当然,我们也有基于原生 javascript 实现的业务组件,例如ContextMenu,KeyEventListener等.';
266

277
export default () => {
288
return (
29-
<>
30-
<CopyIcon text={text} />
9+
<div>
10+
<Copy text={text} title="复制该文本" />
3111
<p>{text}</p>
32-
</>
12+
</div>
3313
);
3414
};
35-
```

src/copy/demos/custom.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react';
2+
import { Copy } from 'dt-react-component';
3+
4+
const text =
5+
'基于 ant-design 的 React UI 组件库。 主要用于中,后台产品。我们的目标是满足更具体的业务场景组件。 当然,我们也有基于原生 javascript 实现的业务组件,例如ContextMenu,KeyEventListener等.';
6+
7+
export default () => {
8+
return (
9+
<div>
10+
<Copy text={text} button={<a>复制文本</a>} hideTooltip />
11+
<p>{text}</p>
12+
</div>
13+
);
14+
};

src/copy/index.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
title: Copy 复制文本
3+
group: 组件
4+
toc: content
5+
demo:
6+
cols: 1
7+
---
8+
9+
# Copy 复制文本
10+
11+
## 何时使用
12+
13+
复制文本到粘贴版
14+
15+
## 示例
16+
17+
<code src='./demos/basic.tsx' title="点击按钮,进行复制"></code>
18+
<code src='./demos/custom.tsx' title="自定义按钮" description='通过hideTooltip属性,可以隐藏默认的提示'></code>
19+
20+
### API
21+
22+
| 参数 | 说明 | 类型 | 默认值 |
23+
| ----------- | --------------------- | ------------------------ | ----------------------------------- |
24+
| text | 需要复制的文本 | `string` | - |
25+
| title | 在 Tooltip 展示的文本 | `string` | `复制` |
26+
| hideTooltip | 是否隐藏 Tooltip | `boolean` | `false` |
27+
| button | 自定义按钮 | `React.ReactNode` | `<CopyOutlined />` |
28+
| onCopy | 复制后的回调函数 | `(text: string) => void` | `() => message.success('复制成功')` |

src/copy/index.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from 'react';
2+
import { Tooltip, message } from 'antd';
3+
import { CopyOutlined } from '@ant-design/icons';
4+
import useClippy from 'use-clippy';
5+
import classNames from 'classnames';
6+
import './style.scss';
7+
8+
export interface ICopyProps {
9+
text: string;
10+
title?: React.ReactNode;
11+
button?: React.ReactNode;
12+
hideTooltip?: boolean;
13+
style?: React.CSSProperties;
14+
className?: string;
15+
onCopy?: (text: string) => void;
16+
}
17+
18+
const Copy: React.FC<ICopyProps> = (props) => {
19+
const {
20+
button = <CopyOutlined className="dtc-copy__default-icon" />,
21+
text,
22+
title = '复制',
23+
hideTooltip,
24+
style,
25+
className,
26+
onCopy = () => message.success('复制成功'),
27+
} = props;
28+
const [_, setClipboard] = useClippy();
29+
30+
const handleCopy = () => {
31+
setClipboard(text);
32+
onCopy(text);
33+
};
34+
35+
const renderCopyButton = () => (
36+
<span
37+
className={classNames(['dtc-copy', className])}
38+
style={style}
39+
onClick={() => handleCopy()}
40+
>
41+
{button}
42+
</span>
43+
);
44+
45+
return !hideTooltip ? (
46+
<Tooltip placement="right" title={title}>
47+
{renderCopyButton()}
48+
</Tooltip>
49+
) : (
50+
renderCopyButton()
51+
);
52+
};
53+
54+
export default Copy;

src/copy/style.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.dtc-copy {
2+
display: inline-block;
3+
cursor: pointer;
4+
&__default-icon:hover {
5+
color: #58ABF9;
6+
}
7+
}

src/copyIcon/index.tsx

Lines changed: 0 additions & 115 deletions
This file was deleted.

src/copyIcon/style.scss

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)