|
import { useState } from 'react'; |
|
import type { TConversation, TMessage } from 'librechat-data-provider'; |
|
import { Clipboard, CheckMark, EditIcon, RegenerateIcon, ContinueIcon } from '~/components/svg'; |
|
import { useGenerations, useLocalize } from '~/hooks'; |
|
import { cn } from '~/utils'; |
|
|
|
type THoverButtons = { |
|
isEditing: boolean; |
|
enterEdit: (cancel?: boolean) => void; |
|
copyToClipboard: (setIsCopied: React.Dispatch<React.SetStateAction<boolean>>) => void; |
|
conversation: TConversation | null; |
|
isSubmitting: boolean; |
|
message: TMessage; |
|
regenerate: () => void; |
|
handleContinue: (e: React.MouseEvent<HTMLButtonElement>) => void; |
|
}; |
|
|
|
export default function HoverButtons({ |
|
isEditing, |
|
enterEdit, |
|
copyToClipboard, |
|
conversation, |
|
isSubmitting, |
|
message, |
|
regenerate, |
|
handleContinue, |
|
}: THoverButtons) { |
|
const localize = useLocalize(); |
|
const { endpoint } = conversation ?? {}; |
|
const [isCopied, setIsCopied] = useState(false); |
|
const { hideEditButton, regenerateEnabled, continueSupported } = useGenerations({ |
|
isEditing, |
|
isSubmitting, |
|
message, |
|
endpoint: endpoint ?? '', |
|
}); |
|
if (!conversation) { |
|
return null; |
|
} |
|
|
|
const { isCreatedByUser } = message; |
|
|
|
const onEdit = () => { |
|
if (isEditing) { |
|
return enterEdit(true); |
|
} |
|
enterEdit(); |
|
}; |
|
|
|
return ( |
|
<div className="visible mt-2 flex justify-center gap-3 self-end text-gray-400 md:gap-4 lg:absolute lg:right-0 lg:top-0 lg:mt-0 lg:translate-x-full lg:gap-1 lg:self-center lg:pl-2"> |
|
<button |
|
className={cn( |
|
'hover-button rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400 md:invisible md:group-hover:visible', |
|
isCreatedByUser ? '' : 'active', |
|
hideEditButton ? 'opacity-0' : '', |
|
isEditing ? 'active bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-200' : '', |
|
)} |
|
onClick={onEdit} |
|
type="button" |
|
title={localize('com_ui_edit')} |
|
disabled={hideEditButton} |
|
> |
|
<EditIcon /> |
|
</button> |
|
<button |
|
className={cn( |
|
'hover-button rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400 md:invisible md:group-hover:visible', |
|
isCreatedByUser ? '' : 'active', |
|
)} |
|
onClick={() => copyToClipboard(setIsCopied)} |
|
type="button" |
|
title={ |
|
isCopied ? localize('com_ui_copied_to_clipboard') : localize('com_ui_copy_to_clipboard') |
|
} |
|
> |
|
{isCopied ? <CheckMark /> : <Clipboard />} |
|
</button> |
|
{regenerateEnabled ? ( |
|
<button |
|
className="hover-button active rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400 md:invisible md:group-hover:visible" |
|
onClick={regenerate} |
|
type="button" |
|
title={localize('com_ui_regenerate')} |
|
> |
|
<RegenerateIcon className="hover:text-gray-700 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400" /> |
|
</button> |
|
) : null} |
|
{continueSupported ? ( |
|
<button |
|
className="hover-button active rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400 md:invisible md:group-hover:visible " |
|
onClick={handleContinue} |
|
type="button" |
|
title={localize('com_ui_continue')} |
|
> |
|
<ContinueIcon className="h-4 w-4 hover:text-gray-700 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400" /> |
|
</button> |
|
) : null} |
|
</div> |
|
); |
|
} |
|
|