You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.4 KiB
90 lines
2.4 KiB
import { useRef, useState, useCallback } from 'react'; |
|
|
|
import { FormattedMessage } from 'react-intl'; |
|
|
|
import classNames from 'classnames'; |
|
|
|
import ContentCopyIcon from '@/material-icons/400-24px/content_copy.svg?react'; |
|
import { Icon } from 'mastodon/components/icon'; |
|
import { useTimeout } from 'mastodon/hooks/useTimeout'; |
|
|
|
export const CopyPasteText: React.FC<{ value: string }> = ({ value }) => { |
|
const inputRef = useRef<HTMLTextAreaElement>(null); |
|
const [copied, setCopied] = useState(false); |
|
const [focused, setFocused] = useState(false); |
|
const [setAnimationTimeout] = useTimeout(); |
|
|
|
const handleInputClick = useCallback(() => { |
|
setCopied(false); |
|
|
|
if (inputRef.current) { |
|
inputRef.current.focus(); |
|
inputRef.current.select(); |
|
inputRef.current.setSelectionRange(0, value.length); |
|
} |
|
}, [setCopied, value]); |
|
|
|
const handleButtonClick = useCallback( |
|
(e: React.MouseEvent) => { |
|
e.stopPropagation(); |
|
void navigator.clipboard.writeText(value); |
|
inputRef.current?.blur(); |
|
setCopied(true); |
|
setAnimationTimeout(() => { |
|
setCopied(false); |
|
}, 700); |
|
}, |
|
[setCopied, setAnimationTimeout, value], |
|
); |
|
|
|
const handleKeyUp = useCallback( |
|
(e: React.KeyboardEvent) => { |
|
if (e.key !== ' ') return; |
|
void navigator.clipboard.writeText(value); |
|
setCopied(true); |
|
setAnimationTimeout(() => { |
|
setCopied(false); |
|
}, 700); |
|
}, |
|
[setCopied, setAnimationTimeout, value], |
|
); |
|
|
|
const handleFocus = useCallback(() => { |
|
setFocused(true); |
|
}, [setFocused]); |
|
|
|
const handleBlur = useCallback(() => { |
|
setFocused(false); |
|
}, [setFocused]); |
|
|
|
return ( |
|
<div |
|
className={classNames('copy-paste-text', { copied, focused })} |
|
tabIndex={0} |
|
role='button' |
|
onClick={handleInputClick} |
|
onKeyUp={handleKeyUp} |
|
> |
|
<textarea |
|
readOnly |
|
value={value} |
|
ref={inputRef} |
|
onClick={handleInputClick} |
|
onFocus={handleFocus} |
|
onBlur={handleBlur} |
|
/> |
|
|
|
<button className='button' onClick={handleButtonClick}> |
|
<Icon id='copy' icon={ContentCopyIcon} />{' '} |
|
{copied ? ( |
|
<FormattedMessage id='copypaste.copied' defaultMessage='Copied' /> |
|
) : ( |
|
<FormattedMessage |
|
id='copypaste.copy_to_clipboard' |
|
defaultMessage='Copy to clipboard' |
|
/> |
|
)} |
|
</button> |
|
</div> |
|
); |
|
};
|
|
|