File size: 4,768 Bytes
baa4c21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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>
    );
  },
);