mirror of
https://github.com/lux-tel/websites.git
synced 2026-10-30 20:31:36 +00:00
80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
'use client';
|
|
|
|
import { type ButtonHTMLAttributes, forwardRef, useState } from 'react';
|
|
import { BaseDataTestId, TestingProps } from '../data-test-ids';
|
|
import { ClipboardIcon } from '../icons/ClipboardIcon';
|
|
import { toast } from '../lib/toast';
|
|
import { cn } from '../lib/utils';
|
|
import { Button } from './ui/button';
|
|
import { CheckIcon } from 'lucide-react';
|
|
import { Spinner } from '../icons/Spinner';
|
|
|
|
export interface CopyToClipboardButtonProps
|
|
extends ButtonHTMLAttributes<HTMLButtonElement>,
|
|
TestingProps<BaseDataTestId.Button> {
|
|
textToCopy: string;
|
|
copyToClipboardToastMessage?: string;
|
|
onCopyComplete?: () => void;
|
|
}
|
|
|
|
/**
|
|
* Copies the specified text to the clipboard and displays a success toast message.
|
|
*
|
|
* @param textToCopy The text to be copied to the clipboard.
|
|
* @param copyToClipboardToastMessage The message to be displayed in the success toast.
|
|
*/
|
|
async function copyToClipboard(
|
|
textToCopy: string,
|
|
copyToClipboardToastMessage?: string,
|
|
onCopyComplete?: () => void
|
|
) {
|
|
await navigator.clipboard.writeText(textToCopy);
|
|
if (copyToClipboardToastMessage) {
|
|
toast.success(copyToClipboardToastMessage);
|
|
}
|
|
if (onCopyComplete) {
|
|
onCopyComplete();
|
|
}
|
|
}
|
|
|
|
const CopyToClipboardButton = forwardRef<HTMLButtonElement, CopyToClipboardButtonProps>(
|
|
({ textToCopy, copyToClipboardToastMessage, onCopyComplete, className, ...props }, ref) => {
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [isCopied, setIsCopied] = useState(false);
|
|
|
|
const handleClick = async () => {
|
|
if (isLoading || isCopied) return;
|
|
setIsLoading(true);
|
|
await copyToClipboard(textToCopy, copyToClipboardToastMessage, onCopyComplete);
|
|
setIsCopied(true);
|
|
setIsLoading(false);
|
|
setTimeout(() => {
|
|
setIsCopied(false);
|
|
}, 2000);
|
|
};
|
|
|
|
return (
|
|
<Button
|
|
onClick={handleClick}
|
|
variant="ghost"
|
|
rounded={'md'}
|
|
className={cn('select-all p-0', className)}
|
|
ref={ref}
|
|
{...props}
|
|
data-testid={props['data-testid']}
|
|
>
|
|
{isLoading ? (
|
|
<Spinner className="h-5 w-5" />
|
|
) : isCopied ? (
|
|
<CheckIcon className="stroke-session-green h-5 w-5" />
|
|
) : (
|
|
<ClipboardIcon className="h-5 w-5 stroke-current" />
|
|
)}
|
|
</Button>
|
|
);
|
|
}
|
|
);
|
|
CopyToClipboardButton.displayName = 'CopyToClipboardButton';
|
|
|
|
export { CopyToClipboardButton };
|