@douyinfe/semi-ui
Version:
A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.
137 lines • 3.94 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import Tooltip from '../tooltip/index';
import { cssClasses } from '@douyinfe/semi-foundation/lib/es/typography/constants';
import copy from 'copy-text-to-clipboard';
import cls from 'classnames';
import { noop } from '@douyinfe/semi-foundation/lib/es/utils/function';
import LocaleConsumer from '../locale/localeConsumer';
import { IconCopy, IconTick } from '@douyinfe/semi-icons';
import isEnterPress from '@douyinfe/semi-foundation/lib/es/utils/isEnterPress';
const prefixCls = cssClasses.PREFIX;
export class Copyable extends React.PureComponent {
constructor(props) {
super(props);
this.copy = e => {
const {
content,
duration,
onCopy
} = this.props;
const res = copy(content);
onCopy && onCopy(e, content, res);
this.setCopied(content, duration);
};
this.setCopied = (item, timer) => {
this.setState({
copied: true,
item
});
this._timeId = setTimeout(() => {
this.resetCopied();
}, timer * 1000);
};
this.resetCopied = () => {
if (this._timeId) {
clearTimeout(this._timeId);
this._timeId = null;
this.setState({
copied: false,
item: ''
});
}
};
this.renderSuccessTip = () => {
const {
successTip
} = this.props;
if (typeof successTip !== 'undefined') {
return successTip;
}
return /*#__PURE__*/React.createElement(LocaleConsumer, {
componentName: "Typography"
}, locale => (/*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(IconTick, null), locale.copied)));
};
this.renderCopyIcon = () => {
const {
icon
} = this.props;
const copyProps = {
role: "button",
tabIndex: 0,
onClick: this.copy,
onKeyPress: e => isEnterPress(e) && this.copy(e)
};
{/* TODO: replace `a` tag with `span` in next major version
NOTE: may have effect on style */
}
const defaultIcon =
/*#__PURE__*/
// eslint-disable-next-line jsx-a11y/anchor-is-valid
React.createElement("a", {
className: `${prefixCls}-action-copy-icon`
}, /*#__PURE__*/React.createElement(IconCopy, Object.assign({
onClick: this.copy
}, copyProps)));
return /*#__PURE__*/React.isValidElement(icon) ? /*#__PURE__*/React.cloneElement(icon, copyProps) : defaultIcon;
};
this.state = {
copied: false,
item: ''
};
}
componentWillUnmount() {
if (this._timeId) {
clearTimeout(this._timeId);
this._timeId = null;
}
}
render() {
const {
style,
className,
forwardRef,
copyTip,
render
} = this.props;
const {
copied
} = this.state;
const finalCls = cls(className, {
[`${prefixCls}-action-copy`]: !copied,
[`${prefixCls}-action-copied`]: copied
});
if (render) {
return render(copied, this.copy, this.props);
}
return /*#__PURE__*/React.createElement(LocaleConsumer, {
componentName: "Typography"
}, locale => (/*#__PURE__*/React.createElement("span", {
style: Object.assign({
marginLeft: '4px'
}, style),
className: finalCls,
ref: forwardRef
}, copied ? this.renderSuccessTip() : (/*#__PURE__*/React.createElement(Tooltip, {
content: typeof copyTip !== 'undefined' ? copyTip : locale.copy
}, this.renderCopyIcon())))));
}
}
Copyable.propTypes = {
content: PropTypes.string,
onCopy: PropTypes.func,
successTip: PropTypes.node,
copyTip: PropTypes.node,
duration: PropTypes.number,
style: PropTypes.object,
className: PropTypes.string,
icon: PropTypes.node
};
Copyable.defaultProps = {
content: '',
onCopy: noop,
duration: 3,
style: {},
className: ''
};
export default Copyable;