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>
  );
}