File size: 4,432 Bytes
9b19fd8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>
  );
}