File size: 3,169 Bytes
1e11ab6 a6060b8 6041155 5bbcdcc 1e11ab6 23d7182 1e11ab6 23d7182 5bbcdcc 4b59a79 5bbcdcc a6060b8 5bbcdcc 23d7182 6041155 23d7182 6041155 23d7182 6041155 23d7182 1e11ab6 6041155 5bbcdcc 4b59a79 5bbcdcc 1e11ab6 5bbcdcc 1e11ab6 5bbcdcc 6041155 1e11ab6 5bbcdcc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
import * as Dialog from '@radix-ui/react-dialog';
import { useEffect, useRef, useState } from 'react';
import { type ChatHistoryItem } from '~/lib/persistence';
import { exportChat } from '~/utils/chatExport';
import WithTooltip from '~/components/ui/Tooltip';
interface HistoryItemProps {
item: ChatHistoryItem;
onDelete?: (event: React.UIEvent) => void;
onDuplicate?: (id: string) => void;
}
export function HistoryItem({ item, onDelete, onDuplicate }: HistoryItemProps) {
const [hovering, setHovering] = useState(false);
const hoverRef = useRef<HTMLDivElement>(null);
useEffect(() => {
let timeout: NodeJS.Timeout | undefined;
function mouseEnter() {
setHovering(true);
if (timeout) {
clearTimeout(timeout);
}
}
function mouseLeave() {
setHovering(false);
}
hoverRef.current?.addEventListener('mouseenter', mouseEnter);
hoverRef.current?.addEventListener('mouseleave', mouseLeave);
return () => {
hoverRef.current?.removeEventListener('mouseenter', mouseEnter);
hoverRef.current?.removeEventListener('mouseleave', mouseLeave);
};
}, []);
return (
<div
ref={hoverRef}
className="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"
>
<a href={`/chat/${item.urlId}`} className="flex w-full relative truncate block">
{item.description}
<div className="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-15 group-hover:from-99%">
{hovering && (
<div className="flex items-center p-1 text-bolt-elements-textSecondary">
<WithTooltip tooltip="Export chat">
<button
className="i-ph:download-simple scale-110 mr-2"
onClick={(event) => {
event.preventDefault();
exportChat(item.messages, item.description);
}}
title="Export chat"
/>
</WithTooltip>
{onDuplicate && (
<WithTooltip tooltip="Duplicate chat">
<button
className="i-ph:copy scale-110 mr-2"
onClick={() => onDuplicate?.(item.id)}
title="Duplicate chat"
/>
</WithTooltip>
)}
<Dialog.Trigger asChild>
<WithTooltip tooltip="Delete chat">
<button
className="i-ph:trash scale-110"
onClick={(event) => {
// we prevent the default so we don't trigger the anchor above
event.preventDefault();
onDelete?.(event);
}}
/>
</WithTooltip>
</Dialog.Trigger>
</div>
)}
</div>
</a>
</div>
);
}
|