CopyButton.tsx 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import React, { useState, useCallback } from 'react';
  2. import icons from '../icons/Icons';
  3. import CustomIconButton from '../customButton/CustomIconButton';
  4. import { useTranslation } from 'react-i18next';
  5. import type { FC } from 'react';
  6. import type { CopyButtonProps } from './Types';
  7. const CopyIcon = icons.copyExpression;
  8. const CopyButton: FC<CopyButtonProps> = props => {
  9. const { label, icon, className, value = '', ...others } = props;
  10. const { t: commonTrans } = useTranslation();
  11. const [tooltipTitle, setTooltipTitle] = useState('Copy');
  12. const unsecuredCopyToClipboard = useCallback((v: string) => {
  13. const textArea = document.createElement('textarea');
  14. textArea.style.position = 'fixed';
  15. textArea.style.opacity = '0';
  16. textArea.style.zIndex = '-1000';
  17. textArea.value = v;
  18. document.body.appendChild(textArea);
  19. textArea.focus();
  20. textArea.select();
  21. try {
  22. document.execCommand('copy');
  23. } catch (err) {
  24. console.error('Unable to copy to clipboard', err);
  25. }
  26. document.body.removeChild(textArea);
  27. }, []);
  28. const handleClick = useCallback(
  29. (event: React.MouseEvent<HTMLElement>, v: string) => {
  30. event.stopPropagation();
  31. if (typeof v === 'object') {
  32. v = JSON.stringify(v);
  33. }
  34. setTooltipTitle(commonTrans('copy.copied'));
  35. if (navigator.clipboard && navigator.clipboard.writeText) {
  36. navigator.clipboard.writeText(v);
  37. } else {
  38. unsecuredCopyToClipboard(v);
  39. }
  40. setTimeout(() => {
  41. setTooltipTitle(commonTrans('copy.copy'));
  42. }, 1000);
  43. },
  44. [commonTrans, unsecuredCopyToClipboard]
  45. );
  46. return (
  47. <CustomIconButton
  48. tooltip={tooltipTitle}
  49. aria-label={label}
  50. className={className}
  51. onClick={event => handleClick(event, value || '')}
  52. {...others}
  53. >
  54. {icon || <CopyIcon />}
  55. </CustomIconButton>
  56. );
  57. };
  58. CopyButton.displayName = 'CopyButton';
  59. export default CopyButton;