UI/ClipboardButton: Remove ClipboardJS in favor of native Clipboard API (#42996)

* UI/ClipboardButton: Remove ClipboardJS in favor of native Clipboard API
Closes #42365

* Add backwards compatibility
This commit is contained in:
kay delaney
2022-01-07 13:41:09 +00:00
committed by GitHub
parent 4eacdf5f9e
commit 36e4a871f2
10 changed files with 55 additions and 224 deletions

View File

@@ -48,7 +48,6 @@
"ansicolor": "1.1.95",
"calculate-size": "1.1.1",
"classnames": "2.3.1",
"clipboard": "2.0.4",
"core-js": "3.20.0",
"d3": "5.15.0",
"date-fns": "2.28.0",
@@ -119,7 +118,6 @@
"@testing-library/react-hooks": "7.0.2",
"@testing-library/user-event": "13.5.0",
"@types/classnames": "2.3.0",
"@types/clipboard": "2.0.1",
"@types/common-tags": "^1.8.0",
"@types/d3": "7.1.0",
"@types/enzyme": "3.10.5",

View File

@@ -1,51 +1,44 @@
import React, { PureComponent } from 'react';
import Clipboard from 'clipboard';
import React, { useCallback, useRef } from 'react';
import { Button, ButtonProps } from '../Button';
/** @deprecated Will be removed in next major release */
interface ClipboardEvent {
action: string;
text: string;
trigger: Element;
clearSelection(): void;
}
export interface Props extends ButtonProps {
/** A function that returns text to be copied */
getText(): string;
/** Callback when the text has been successfully copied */
onClipboardCopy?(e: Clipboard.Event): void;
onClipboardCopy?(e: ClipboardEvent): void;
/** Callback when there was an error copying the text */
onClipboardError?(e: Clipboard.Event): void;
onClipboardError?(e: ClipboardEvent): void;
}
export class ClipboardButton extends PureComponent<Props> {
private clipboard!: Clipboard;
private elem!: HTMLButtonElement;
const dummyClearFunc = () => {};
setRef = (elem: HTMLButtonElement) => {
this.elem = elem;
};
export function ClipboardButton({ onClipboardCopy, onClipboardError, children, getText, ...buttonProps }: Props) {
// Can be removed in 9.x
const buttonRef = useRef<null | HTMLButtonElement>(null);
const copyText = useCallback(() => {
const copiedText = getText();
const dummyEvent: ClipboardEvent = {
action: 'copy',
clearSelection: dummyClearFunc,
text: copiedText,
trigger: buttonRef.current!,
};
navigator.clipboard
.writeText(copiedText)
.then(() => (onClipboardCopy?.(dummyEvent), () => onClipboardError?.(dummyEvent)));
}, [getText, onClipboardCopy, onClipboardError]);
componentDidMount() {
const { getText, onClipboardCopy, onClipboardError } = this.props;
this.clipboard = new Clipboard(this.elem, {
text: () => getText(),
});
this.clipboard.on('success', (e: Clipboard.Event) => {
onClipboardCopy && onClipboardCopy(e);
});
this.clipboard.on('error', (e: Clipboard.Event) => {
onClipboardError && onClipboardError(e);
});
}
componentWillUnmount() {
this.clipboard.destroy();
}
render() {
const { getText, onClipboardCopy, onClipboardError, children, ...buttonProps } = this.props;
return (
<Button {...buttonProps} ref={this.setRef}>
{children}
</Button>
);
}
return (
<Button onClick={copyText} {...buttonProps} ref={buttonRef}>
{children}
</Button>
);
}