{
static defaultProps = {
buttonDefaultText: defaultCopyText,
buttonProps: {},
buttonSuccessText: defaultCopiedText,
className: '',
hideOptionalLabel: true,
readOnly: true,
successStateDuration: DEFAULT_SUCCESS_STATE_DURATION,
type: 'text',
};
constructor(props: Props) {
super(props);
// $FlowFixMe https://github.com/facebook/flow/issues/4335
this.isCopyCommandSupported = document.queryCommandSupported('copy');
this.state = {
copySuccess: false,
buttonText: props.buttonDefaultText,
hasFocused: false,
};
}
componentDidMount() {
const { autofocus, value } = this.props;
if (autofocus && value) {
this.performAutofocus();
}
}
componentDidUpdate() {
const { autofocus, value, triggerCopyOnLoad } = this.props;
const { copySuccess, hasFocused } = this.state;
// if we've set focus before, and should auto focus on update, make sure to
// focus after component update
if (autofocus && value) {
this.performAutofocus();
}
if (triggerCopyOnLoad && !copySuccess && !hasFocused) {
this.animateCopyButton();
}
}
componentWillUnmount() {
this.clearCopySuccessTimeout();
}
copyInputRef: ?HTMLInputElement;
copySuccessTimeout: ?TimeoutID;
isCopyCommandSupported: boolean;
animateCopyButton() {
const { successStateDuration, buttonSuccessText } = this.props;
this.clearCopySuccessTimeout();
this.setState(
{
copySuccess: true,
buttonText: buttonSuccessText,
hasFocused: true,
},
() => {
this.copySuccessTimeout = setTimeout(() => {
this.restoreCopyButton();
}, successStateDuration);
},
);
}
clearCopySuccessTimeout() {
if (!this.copySuccessTimeout) {
return;
}
clearTimeout(this.copySuccessTimeout);
this.copySuccessTimeout = null;
}
copySelectedText = () => document.execCommand('copy');
restoreCopyButton = () => {
this.setState({
copySuccess: false,
buttonText: this.props.buttonDefaultText,
});
};
handleCopyButtonClick = () => {
this.performAutofocus();
this.copySelectedText();
this.animateCopyButton();
};
handleFocus = (event: SyntheticEvent<>) => {
if (this.copyInputRef) {
this.performAutofocus();
}
if (this.props.onFocus) {
this.props.onFocus(event);
}
};
handleCopyEvent = (event: SyntheticEvent<>) => {
this.animateCopyButton();
const { onCopySuccess } = this.props;
if (onCopySuccess) {
onCopySuccess(event);
}
};
performAutofocus = () => {
const { copyInputRef } = this;
if (copyInputRef) {
copyInputRef.select();
copyInputRef.scrollLeft = 0;
}
};
renderCopyButton = () =>
this.isCopyCommandSupported ? (
) : null;
render() {
const { className, ...rest } = this.props;
const { copySuccess } = this.state;
const { isCopyCommandSupported } = this;
const inputProps = omit(rest, [
'autofocus',
'buttonDefaultText',
'buttonSuccessText',
'buttonProps',
'onCopySuccess',
'successStateDuration',
'triggerCopyOnLoad',
]);
if (isCopyCommandSupported) {
inputProps.inputRef = ref => {
this.copyInputRef = ref;
};
}
const wrapperClasses = classNames(className, {
'copy-success': copySuccess,
'text-input-with-copy-button-container': isCopyCommandSupported,
});
const copyEvent = isCopyCommandSupported ? { onCopy: this.handleCopyEvent } : {};
return (
{this.renderCopyButton()}
);
}
}
export default TextInputWithCopyButton;