File size: 4,297 Bytes
305a42c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
136
import {
  DocumentTextIcon,
  SpeakerWaveIcon,
  XMarkIcon,
} from '@heroicons/react/24/outline';
import { MessageExtra } from '../utils/types';
import { useState } from 'react';
import { classNames } from '../utils/misc';

export default function ChatInputExtraContextItem({
  items,
  removeItem,
  clickToShow,
}: {
  items?: MessageExtra[];
  removeItem?: (index: number) => void;
  clickToShow?: boolean;
}) {
  const [show, setShow] = useState(-1);
  const showingItem = show >= 0 ? items?.[show] : undefined;

  if (!items) return null;

  return (
    <div
      className="flex flex-row gap-4 overflow-x-auto py-2 px-1 mb-1"
      role="group"
      aria-description="Selected files"
    >
      {items.map((item, i) => (
        <div
          className="indicator"
          key={i}
          onClick={() => clickToShow && setShow(i)}
          tabIndex={0}
          aria-description={
            clickToShow ? `Click to show: ${item.name}` : undefined
          }
          role={clickToShow ? 'button' : 'menuitem'}
        >
          {removeItem && (
            <div className="indicator-item indicator-top">
              <button
                aria-label="Remove file"
                className="btn btn-neutral btn-sm w-4 h-4 p-0 rounded-full"
                onClick={() => removeItem(i)}
              >
                <XMarkIcon className="h-3 w-3" />
              </button>
            </div>
          )}

          <div
            className={classNames({
              'flex flex-row rounded-md shadow-sm items-center m-0 p-0': true,
              'cursor-pointer hover:shadow-md': !!clickToShow,
            })}
          >
            {item.type === 'imageFile' ? (
              <>
                <img
                  src={item.base64Url}
                  alt={`Preview image for ${item.name}`}
                  className="w-14 h-14 object-cover rounded-md"
                />
              </>
            ) : (
              <>
                <div
                  className="w-14 h-14 flex items-center justify-center"
                  aria-description="Document icon"
                >
                  {item.type === 'audioFile' ? (
                    <SpeakerWaveIcon className="h-8 w-8 text-gray-500" />
                  ) : (
                    <DocumentTextIcon className="h-8 w-8 text-gray-500" />
                  )}
                </div>

                <div className="text-xs pr-4">
                  <b>{item.name ?? 'Extra content'}</b>
                </div>
              </>
            )}
          </div>
        </div>
      ))}

      {showingItem && (
        <dialog
          className="modal modal-open"
          aria-description={`Preview ${showingItem.name}`}
        >
          <div className="modal-box">
            <div className="flex justify-between items-center mb-4">
              <b>{showingItem.name ?? 'Extra content'}</b>
              <button
                className="btn btn-ghost btn-sm"
                aria-label="Close preview dialog"
              >
                <XMarkIcon className="h-5 w-5" onClick={() => setShow(-1)} />
              </button>
            </div>
            {showingItem.type === 'imageFile' ? (
              <img
                src={showingItem.base64Url}
                alt={`Preview image for ${showingItem.name}`}
              />
            ) : showingItem.type === 'audioFile' ? (
              <audio
                controls
                className="w-full"
                aria-description={`Audio file ${showingItem.name}`}
              >
                <source
                  src={`data:${showingItem.mimeType};base64,${showingItem.base64Data}`}
                  type={showingItem.mimeType}
                  aria-description={`Audio file ${showingItem.name}`}
                />
                Your browser does not support the audio element.
              </audio>
            ) : (
              <div className="overflow-x-auto">
                <pre className="whitespace-pre-wrap break-words text-sm">
                  {showingItem.content}
                </pre>
              </div>
            )}
          </div>
          <div className="modal-backdrop" onClick={() => setShow(-1)}></div>
        </dialog>
      )}
    </div>
  );
}