mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-01-22 19:06:12 +00:00
135 lines
4.5 KiB
TypeScript
135 lines
4.5 KiB
TypeScript
import { useParams } from '@remix-run/react';
|
|
import { classNames } from '~/utils/classNames';
|
|
import * as Dialog from '@radix-ui/react-dialog';
|
|
import { type ChatHistoryItem } from '~/lib/persistence';
|
|
import WithTooltip from '~/components/ui/Tooltip';
|
|
import { useEditChatDescription } from '~/lib/hooks';
|
|
import { forwardRef, type ForwardedRef } from 'react';
|
|
|
|
interface HistoryItemProps {
|
|
item: ChatHistoryItem;
|
|
onDelete?: (event: React.UIEvent) => void;
|
|
onDuplicate?: (id: string) => void;
|
|
exportChat: (id?: string) => void;
|
|
}
|
|
|
|
export function HistoryItem({ item, onDelete, onDuplicate, exportChat }: HistoryItemProps) {
|
|
const { id: urlId } = useParams();
|
|
const isActiveChat = urlId === item.urlId;
|
|
|
|
const { editing, handleChange, handleBlur, handleSubmit, handleKeyDown, currentDescription, toggleEditMode } =
|
|
useEditChatDescription({
|
|
initialDescription: item.description,
|
|
customChatId: item.id,
|
|
syncWithGlobalStore: isActiveChat,
|
|
});
|
|
|
|
const renderDescriptionForm = (
|
|
<form onSubmit={handleSubmit} className="flex-1 flex items-center">
|
|
<input
|
|
type="text"
|
|
className="flex-1 bg-bolt-elements-background-depth-1 text-bolt-elements-textPrimary rounded px-2 mr-2"
|
|
autoFocus
|
|
value={currentDescription}
|
|
onChange={handleChange}
|
|
onBlur={handleBlur}
|
|
onKeyDown={handleKeyDown}
|
|
/>
|
|
<button
|
|
type="submit"
|
|
className="i-ph:check scale-110 hover:text-bolt-elements-item-contentAccent"
|
|
onMouseDown={handleSubmit}
|
|
/>
|
|
</form>
|
|
);
|
|
|
|
return (
|
|
<div
|
|
className={classNames(
|
|
'group rounded-md text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary hover:bg-bolt-elements-background-depth-3 overflow-hidden flex justify-between items-center px-2 py-1',
|
|
{ '[&&]:text-bolt-elements-textPrimary bg-bolt-elements-background-depth-3': isActiveChat },
|
|
)}
|
|
>
|
|
{editing ? (
|
|
renderDescriptionForm
|
|
) : (
|
|
<a href={`/chat/${item.urlId}`} className="flex w-full relative truncate block">
|
|
{currentDescription}
|
|
<div
|
|
className={classNames(
|
|
'absolute right-0 z-1 top-0 bottom-0 bg-gradient-to-l from-bolt-elements-background-depth-2 group-hover:from-bolt-elements-background-depth-3 box-content pl-3 to-transparent w-10 flex justify-end group-hover:w-22 group-hover:from-99%',
|
|
{ 'from-bolt-elements-background-depth-3 w-10 ': isActiveChat },
|
|
)}
|
|
>
|
|
<div className="flex items-center p-1 text-bolt-elements-textSecondary opacity-0 group-hover:opacity-100 transition-opacity">
|
|
<ChatActionButton
|
|
toolTipContent="Export chat"
|
|
icon="i-ph:download-simple"
|
|
onClick={(event) => {
|
|
event.preventDefault();
|
|
exportChat(item.id);
|
|
}}
|
|
/>
|
|
{onDuplicate && (
|
|
<ChatActionButton
|
|
toolTipContent="Duplicate chat"
|
|
icon="i-ph:copy"
|
|
onClick={() => onDuplicate?.(item.id)}
|
|
/>
|
|
)}
|
|
<ChatActionButton
|
|
toolTipContent="Rename chat"
|
|
icon="i-ph:pencil-fill"
|
|
onClick={(event) => {
|
|
event.preventDefault();
|
|
toggleEditMode();
|
|
}}
|
|
/>
|
|
<Dialog.Trigger asChild>
|
|
<ChatActionButton
|
|
toolTipContent="Delete chat"
|
|
icon="i-ph:trash"
|
|
className="[&&]:hover:text-bolt-elements-button-danger-text"
|
|
onClick={(event) => {
|
|
event.preventDefault();
|
|
onDelete?.(event);
|
|
}}
|
|
/>
|
|
</Dialog.Trigger>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const ChatActionButton = forwardRef(
|
|
(
|
|
{
|
|
toolTipContent,
|
|
icon,
|
|
className,
|
|
onClick,
|
|
}: {
|
|
toolTipContent: string;
|
|
icon: string;
|
|
className?: string;
|
|
onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
|
btnTitle?: string;
|
|
},
|
|
ref: ForwardedRef<HTMLButtonElement>,
|
|
) => {
|
|
return (
|
|
<WithTooltip tooltip={toolTipContent}>
|
|
<button
|
|
ref={ref}
|
|
type="button"
|
|
className={`scale-110 mr-2 hover:text-bolt-elements-item-contentAccent ${icon} ${className ? className : ''}`}
|
|
onClick={onClick}
|
|
/>
|
|
</WithTooltip>
|
|
);
|
|
},
|
|
);
|