@cnt-dev/chat-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +202 -0
- package/LICENSE +21 -0
- package/README.md +303 -0
- package/index.d.ts +23 -0
- package/package.json +41 -0
- package/resources/chatui/.library +14 -0
- package/resources/chatui/ChatBox-dbg.js +1099 -0
- package/resources/chatui/ChatBox-dbg.js.map +1 -0
- package/resources/chatui/ChatBox.d.ts +308 -0
- package/resources/chatui/ChatBox.d.ts.map +1 -0
- package/resources/chatui/ChatBox.gen.d.ts +545 -0
- package/resources/chatui/ChatBox.js +5 -0
- package/resources/chatui/ChatBox.js.map +1 -0
- package/resources/chatui/ChatBox.ts +1153 -0
- package/resources/chatui/library-dbg.js +28 -0
- package/resources/chatui/library-dbg.js.map +1 -0
- package/resources/chatui/library-preload.js +17 -0
- package/resources/chatui/library-preload.js.map +1 -0
- package/resources/chatui/library.d.ts +3 -0
- package/resources/chatui/library.d.ts.map +1 -0
- package/resources/chatui/library.js +5 -0
- package/resources/chatui/library.js.map +1 -0
- package/resources/chatui/library.ts +30 -0
- package/resources/chatui/manifest.json +52 -0
- package/resources/chatui/markdown-dbg.js +116 -0
- package/resources/chatui/markdown-dbg.js.map +1 -0
- package/resources/chatui/markdown.d.ts +21 -0
- package/resources/chatui/markdown.d.ts.map +1 -0
- package/resources/chatui/markdown.js +5 -0
- package/resources/chatui/markdown.js.map +1 -0
- package/resources/chatui/markdown.ts +140 -0
- package/resources/chatui/messagebundle.properties +20 -0
- package/resources/chatui/messagebundle_en.properties +20 -0
- package/resources/chatui/themes/base/ChatBox.less +702 -0
- package/resources/chatui/themes/base/library-RTL.css +3 -0
- package/resources/chatui/themes/base/library-parameters.json +1 -0
- package/resources/chatui/themes/base/library.css +3 -0
- package/resources/chatui/themes/base/library.source.less +4 -0
- package/resources/chatui/themes/sap_fiori_3/library-RTL.css +3 -0
- package/resources/chatui/themes/sap_fiori_3/library-parameters.json +1 -0
- package/resources/chatui/themes/sap_fiori_3/library.css +3 -0
- package/resources/chatui/themes/sap_fiori_3/library.source.less +3 -0
- package/resources/chatui/themes/sap_fiori_3_dark/library-RTL.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_dark/library-parameters.json +1 -0
- package/resources/chatui/themes/sap_fiori_3_dark/library.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_dark/library.source.less +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcb/library-RTL.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcb/library-parameters.json +1 -0
- package/resources/chatui/themes/sap_fiori_3_hcb/library.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcb/library.source.less +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcw/library-RTL.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcw/library-parameters.json +1 -0
- package/resources/chatui/themes/sap_fiori_3_hcw/library.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcw/library.source.less +3 -0
- package/ui5.yaml +15 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
declare module "chatui/ChatBox" {
|
|
2
|
+
import Event from "sap/ui/base/Event";
|
|
3
|
+
import { CSSSize } from "sap/ui/core/library";
|
|
4
|
+
import { PropertyBindingInfo } from "sap/ui/base/ManagedObject";
|
|
5
|
+
import { $ControlSettings } from "sap/ui/core/Control";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Interface defining the settings object used in constructor calls
|
|
9
|
+
*/
|
|
10
|
+
interface $ChatBoxSettings extends $ControlSettings {
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Placeholder shown in the empty input field. If empty, a
|
|
14
|
+
localised default is used.
|
|
15
|
+
*/
|
|
16
|
+
placeholder?: string | PropertyBindingInfo;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* When true, the input and buttons are disabled — typically set
|
|
20
|
+
while the assistant is producing a reply.
|
|
21
|
+
*/
|
|
22
|
+
busy?: boolean | PropertyBindingInfo | `{${string}}`;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* CSS width of the control. Defaults to <code>100%</code> so the
|
|
26
|
+
chat adapts to its parent; override for a fixed size.
|
|
27
|
+
*/
|
|
28
|
+
width?: CSSSize | PropertyBindingInfo | `{${string}}`;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* CSS height of the control. Defaults to <code>100%</code>; falls
|
|
32
|
+
back to a sensible min-height when the parent has no explicit
|
|
33
|
+
height.
|
|
34
|
+
*/
|
|
35
|
+
height?: CSSSize | PropertyBindingInfo | `{${string}}`;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* When true (default), the user can attach files via the paperclip
|
|
39
|
+
button and drag-and-drop. Uploaded <code>File</code> objects are
|
|
40
|
+
handed to the consumer via the <code>files</code> parameter of
|
|
41
|
+
the <code>send</code> event — the library never performs any
|
|
42
|
+
network transfer itself.
|
|
43
|
+
*/
|
|
44
|
+
allowAttachments?: boolean | PropertyBindingInfo | `{${string}}`;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Value passed to the underlying <code><input type="file"></code>
|
|
48
|
+
as its <code>accept</code> attribute (e.g. <code>"image/*"</code>
|
|
49
|
+
or <code>".pdf,.docx"</code>). Empty string means "any file".
|
|
50
|
+
*/
|
|
51
|
+
attachmentAccept?: string | PropertyBindingInfo;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The list of conversations shown in the sidebar. Each entry has
|
|
55
|
+
an <code>id</code>, an optional <code>title</code>, an optional
|
|
56
|
+
ordered array of <code>messages</code>, and an optional
|
|
57
|
+
<code>updatedAt</code> timestamp (number, ISO string or Date).
|
|
58
|
+
Passed in by the embedding application and never mutated by
|
|
59
|
+
the library. When set for the first time, the library
|
|
60
|
+
automatically selects and displays the first conversation. If
|
|
61
|
+
the property is empty or unset, an empty new-chat view is
|
|
62
|
+
shown.
|
|
63
|
+
*/
|
|
64
|
+
conversations?: (object | null) | PropertyBindingInfo | `{${string}}`;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* /**
|
|
68
|
+
* The id of the currently displayed conversation. Empty string
|
|
69
|
+
* means "new chat draft" — no history is shown, and the next
|
|
70
|
+
* <code>send</code> event carries an empty <code>conversationId</code>
|
|
71
|
+
* so the consumer can allocate a fresh id. When set to a value
|
|
72
|
+
* that matches an entry in
|
|
73
|
+
{@link #getConversations}
|
|
74
|
+
, that
|
|
75
|
+
* conversation's messages are loaded into the transcript.
|
|
76
|
+
*/
|
|
77
|
+
activeConversationId?: string | PropertyBindingInfo;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* /**
|
|
81
|
+
* Fired when the user submits a prompt. The embedding
|
|
82
|
+
* application should produce an assistant response and feed it
|
|
83
|
+
* back via
|
|
84
|
+
{@link #addAssistantMessage}
|
|
85
|
+
or
|
|
86
|
+
*
|
|
87
|
+
{@link #appendToLastAssistantMessage}
|
|
88
|
+
.
|
|
89
|
+
*/
|
|
90
|
+
send?: (event: ChatBox$SendEvent) => void;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Fired when the user clicks the "Neue Konversation" button.
|
|
94
|
+
The transcript view has already been cleared and
|
|
95
|
+
<code>activeConversationId</code> reset to <code>""</code> by
|
|
96
|
+
the time the event fires — listeners typically use this to
|
|
97
|
+
reset any server-side session state.
|
|
98
|
+
*/
|
|
99
|
+
newChat?: (event: ChatBox$NewChatEvent) => void;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Fired when the user picks a conversation from the sidebar.
|
|
103
|
+
The library has already switched the transcript view to that
|
|
104
|
+
conversation and updated <code>activeConversationId</code>.
|
|
105
|
+
*/
|
|
106
|
+
conversationSelect?: (event: ChatBox$ConversationSelectEvent) => void;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* /**
|
|
110
|
+
* Fired when the user clicks the × on a conversation in the
|
|
111
|
+
* sidebar. The library does not mutate the conversations
|
|
112
|
+
* property itself — the consumer is expected to drop the entry
|
|
113
|
+
* from its store and push an updated list back via
|
|
114
|
+
*
|
|
115
|
+
{@link #setConversations}
|
|
116
|
+
.
|
|
117
|
+
*/
|
|
118
|
+
conversationDelete?: (event: ChatBox$ConversationDeleteEvent) => void;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export default interface ChatBox {
|
|
122
|
+
|
|
123
|
+
// property: placeholder
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Placeholder shown in the empty input field. If empty, a
|
|
127
|
+
localised default is used.
|
|
128
|
+
*/
|
|
129
|
+
getPlaceholder(): string;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Placeholder shown in the empty input field. If empty, a
|
|
133
|
+
localised default is used.
|
|
134
|
+
*/
|
|
135
|
+
setPlaceholder(placeholder: string): this;
|
|
136
|
+
|
|
137
|
+
// property: busy
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* When true, the input and buttons are disabled — typically set
|
|
141
|
+
while the assistant is producing a reply.
|
|
142
|
+
*/
|
|
143
|
+
getBusy(): boolean;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* When true, the input and buttons are disabled — typically set
|
|
147
|
+
while the assistant is producing a reply.
|
|
148
|
+
*/
|
|
149
|
+
setBusy(busy: boolean): this;
|
|
150
|
+
|
|
151
|
+
// property: width
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* CSS width of the control. Defaults to <code>100%</code> so the
|
|
155
|
+
chat adapts to its parent; override for a fixed size.
|
|
156
|
+
*/
|
|
157
|
+
getWidth(): CSSSize;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* CSS width of the control. Defaults to <code>100%</code> so the
|
|
161
|
+
chat adapts to its parent; override for a fixed size.
|
|
162
|
+
*/
|
|
163
|
+
setWidth(width: CSSSize): this;
|
|
164
|
+
|
|
165
|
+
// property: height
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* CSS height of the control. Defaults to <code>100%</code>; falls
|
|
169
|
+
back to a sensible min-height when the parent has no explicit
|
|
170
|
+
height.
|
|
171
|
+
*/
|
|
172
|
+
getHeight(): CSSSize;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* CSS height of the control. Defaults to <code>100%</code>; falls
|
|
176
|
+
back to a sensible min-height when the parent has no explicit
|
|
177
|
+
height.
|
|
178
|
+
*/
|
|
179
|
+
setHeight(height: CSSSize): this;
|
|
180
|
+
|
|
181
|
+
// property: allowAttachments
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* When true (default), the user can attach files via the paperclip
|
|
185
|
+
button and drag-and-drop. Uploaded <code>File</code> objects are
|
|
186
|
+
handed to the consumer via the <code>files</code> parameter of
|
|
187
|
+
the <code>send</code> event — the library never performs any
|
|
188
|
+
network transfer itself.
|
|
189
|
+
*/
|
|
190
|
+
getAllowAttachments(): boolean;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* When true (default), the user can attach files via the paperclip
|
|
194
|
+
button and drag-and-drop. Uploaded <code>File</code> objects are
|
|
195
|
+
handed to the consumer via the <code>files</code> parameter of
|
|
196
|
+
the <code>send</code> event — the library never performs any
|
|
197
|
+
network transfer itself.
|
|
198
|
+
*/
|
|
199
|
+
setAllowAttachments(allowAttachments: boolean): this;
|
|
200
|
+
|
|
201
|
+
// property: attachmentAccept
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Value passed to the underlying <code><input type="file"></code>
|
|
205
|
+
as its <code>accept</code> attribute (e.g. <code>"image/*"</code>
|
|
206
|
+
or <code>".pdf,.docx"</code>). Empty string means "any file".
|
|
207
|
+
*/
|
|
208
|
+
getAttachmentAccept(): string;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Value passed to the underlying <code><input type="file"></code>
|
|
212
|
+
as its <code>accept</code> attribute (e.g. <code>"image/*"</code>
|
|
213
|
+
or <code>".pdf,.docx"</code>). Empty string means "any file".
|
|
214
|
+
*/
|
|
215
|
+
setAttachmentAccept(attachmentAccept: string): this;
|
|
216
|
+
|
|
217
|
+
// property: conversations
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* The list of conversations shown in the sidebar. Each entry has
|
|
221
|
+
an <code>id</code>, an optional <code>title</code>, an optional
|
|
222
|
+
ordered array of <code>messages</code>, and an optional
|
|
223
|
+
<code>updatedAt</code> timestamp (number, ISO string or Date).
|
|
224
|
+
Passed in by the embedding application and never mutated by
|
|
225
|
+
the library. When set for the first time, the library
|
|
226
|
+
automatically selects and displays the first conversation. If
|
|
227
|
+
the property is empty or unset, an empty new-chat view is
|
|
228
|
+
shown.
|
|
229
|
+
*/
|
|
230
|
+
getConversations(): object | null;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* The list of conversations shown in the sidebar. Each entry has
|
|
234
|
+
an <code>id</code>, an optional <code>title</code>, an optional
|
|
235
|
+
ordered array of <code>messages</code>, and an optional
|
|
236
|
+
<code>updatedAt</code> timestamp (number, ISO string or Date).
|
|
237
|
+
Passed in by the embedding application and never mutated by
|
|
238
|
+
the library. When set for the first time, the library
|
|
239
|
+
automatically selects and displays the first conversation. If
|
|
240
|
+
the property is empty or unset, an empty new-chat view is
|
|
241
|
+
shown.
|
|
242
|
+
*/
|
|
243
|
+
setConversations(conversations: object | null): this;
|
|
244
|
+
|
|
245
|
+
// property: activeConversationId
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* /**
|
|
249
|
+
* The id of the currently displayed conversation. Empty string
|
|
250
|
+
* means "new chat draft" — no history is shown, and the next
|
|
251
|
+
* <code>send</code> event carries an empty <code>conversationId</code>
|
|
252
|
+
* so the consumer can allocate a fresh id. When set to a value
|
|
253
|
+
* that matches an entry in
|
|
254
|
+
{@link #getConversations}
|
|
255
|
+
, that
|
|
256
|
+
* conversation's messages are loaded into the transcript.
|
|
257
|
+
*/
|
|
258
|
+
getActiveConversationId(): string;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* /**
|
|
262
|
+
* The id of the currently displayed conversation. Empty string
|
|
263
|
+
* means "new chat draft" — no history is shown, and the next
|
|
264
|
+
* <code>send</code> event carries an empty <code>conversationId</code>
|
|
265
|
+
* so the consumer can allocate a fresh id. When set to a value
|
|
266
|
+
* that matches an entry in
|
|
267
|
+
{@link #getConversations}
|
|
268
|
+
, that
|
|
269
|
+
* conversation's messages are loaded into the transcript.
|
|
270
|
+
*/
|
|
271
|
+
setActiveConversationId(activeConversationId: string): this;
|
|
272
|
+
|
|
273
|
+
// event: send
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* /**
|
|
277
|
+
* Fired when the user submits a prompt. The embedding
|
|
278
|
+
* application should produce an assistant response and feed it
|
|
279
|
+
* back via
|
|
280
|
+
{@link #addAssistantMessage}
|
|
281
|
+
or
|
|
282
|
+
*
|
|
283
|
+
{@link #appendToLastAssistantMessage}
|
|
284
|
+
.
|
|
285
|
+
*/
|
|
286
|
+
attachSend(fn: (event: ChatBox$SendEvent) => void, listener?: object): this;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* /**
|
|
290
|
+
* Fired when the user submits a prompt. The embedding
|
|
291
|
+
* application should produce an assistant response and feed it
|
|
292
|
+
* back via
|
|
293
|
+
{@link #addAssistantMessage}
|
|
294
|
+
or
|
|
295
|
+
*
|
|
296
|
+
{@link #appendToLastAssistantMessage}
|
|
297
|
+
.
|
|
298
|
+
*/
|
|
299
|
+
attachSend<CustomDataType extends object>(data: CustomDataType, fn: (event: ChatBox$SendEvent, data: CustomDataType) => void, listener?: object): this;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* /**
|
|
303
|
+
* Fired when the user submits a prompt. The embedding
|
|
304
|
+
* application should produce an assistant response and feed it
|
|
305
|
+
* back via
|
|
306
|
+
{@link #addAssistantMessage}
|
|
307
|
+
or
|
|
308
|
+
*
|
|
309
|
+
{@link #appendToLastAssistantMessage}
|
|
310
|
+
.
|
|
311
|
+
*/
|
|
312
|
+
detachSend(fn: (event: ChatBox$SendEvent) => void, listener?: object): this;
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* /**
|
|
316
|
+
* Fired when the user submits a prompt. The embedding
|
|
317
|
+
* application should produce an assistant response and feed it
|
|
318
|
+
* back via
|
|
319
|
+
{@link #addAssistantMessage}
|
|
320
|
+
or
|
|
321
|
+
*
|
|
322
|
+
{@link #appendToLastAssistantMessage}
|
|
323
|
+
.
|
|
324
|
+
*/
|
|
325
|
+
fireSend(parameters?: ChatBox$SendEventParameters): this;
|
|
326
|
+
|
|
327
|
+
// event: newChat
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Fired when the user clicks the "Neue Konversation" button.
|
|
331
|
+
The transcript view has already been cleared and
|
|
332
|
+
<code>activeConversationId</code> reset to <code>""</code> by
|
|
333
|
+
the time the event fires — listeners typically use this to
|
|
334
|
+
reset any server-side session state.
|
|
335
|
+
*/
|
|
336
|
+
attachNewChat(fn: (event: ChatBox$NewChatEvent) => void, listener?: object): this;
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Fired when the user clicks the "Neue Konversation" button.
|
|
340
|
+
The transcript view has already been cleared and
|
|
341
|
+
<code>activeConversationId</code> reset to <code>""</code> by
|
|
342
|
+
the time the event fires — listeners typically use this to
|
|
343
|
+
reset any server-side session state.
|
|
344
|
+
*/
|
|
345
|
+
attachNewChat<CustomDataType extends object>(data: CustomDataType, fn: (event: ChatBox$NewChatEvent, data: CustomDataType) => void, listener?: object): this;
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Fired when the user clicks the "Neue Konversation" button.
|
|
349
|
+
The transcript view has already been cleared and
|
|
350
|
+
<code>activeConversationId</code> reset to <code>""</code> by
|
|
351
|
+
the time the event fires — listeners typically use this to
|
|
352
|
+
reset any server-side session state.
|
|
353
|
+
*/
|
|
354
|
+
detachNewChat(fn: (event: ChatBox$NewChatEvent) => void, listener?: object): this;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Fired when the user clicks the "Neue Konversation" button.
|
|
358
|
+
The transcript view has already been cleared and
|
|
359
|
+
<code>activeConversationId</code> reset to <code>""</code> by
|
|
360
|
+
the time the event fires — listeners typically use this to
|
|
361
|
+
reset any server-side session state.
|
|
362
|
+
*/
|
|
363
|
+
fireNewChat(parameters?: ChatBox$NewChatEventParameters): this;
|
|
364
|
+
|
|
365
|
+
// event: conversationSelect
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Fired when the user picks a conversation from the sidebar.
|
|
369
|
+
The library has already switched the transcript view to that
|
|
370
|
+
conversation and updated <code>activeConversationId</code>.
|
|
371
|
+
*/
|
|
372
|
+
attachConversationSelect(fn: (event: ChatBox$ConversationSelectEvent) => void, listener?: object): this;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Fired when the user picks a conversation from the sidebar.
|
|
376
|
+
The library has already switched the transcript view to that
|
|
377
|
+
conversation and updated <code>activeConversationId</code>.
|
|
378
|
+
*/
|
|
379
|
+
attachConversationSelect<CustomDataType extends object>(data: CustomDataType, fn: (event: ChatBox$ConversationSelectEvent, data: CustomDataType) => void, listener?: object): this;
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Fired when the user picks a conversation from the sidebar.
|
|
383
|
+
The library has already switched the transcript view to that
|
|
384
|
+
conversation and updated <code>activeConversationId</code>.
|
|
385
|
+
*/
|
|
386
|
+
detachConversationSelect(fn: (event: ChatBox$ConversationSelectEvent) => void, listener?: object): this;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Fired when the user picks a conversation from the sidebar.
|
|
390
|
+
The library has already switched the transcript view to that
|
|
391
|
+
conversation and updated <code>activeConversationId</code>.
|
|
392
|
+
*/
|
|
393
|
+
fireConversationSelect(parameters?: ChatBox$ConversationSelectEventParameters): this;
|
|
394
|
+
|
|
395
|
+
// event: conversationDelete
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* /**
|
|
399
|
+
* Fired when the user clicks the × on a conversation in the
|
|
400
|
+
* sidebar. The library does not mutate the conversations
|
|
401
|
+
* property itself — the consumer is expected to drop the entry
|
|
402
|
+
* from its store and push an updated list back via
|
|
403
|
+
*
|
|
404
|
+
{@link #setConversations}
|
|
405
|
+
.
|
|
406
|
+
*/
|
|
407
|
+
attachConversationDelete(fn: (event: ChatBox$ConversationDeleteEvent) => void, listener?: object): this;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* /**
|
|
411
|
+
* Fired when the user clicks the × on a conversation in the
|
|
412
|
+
* sidebar. The library does not mutate the conversations
|
|
413
|
+
* property itself — the consumer is expected to drop the entry
|
|
414
|
+
* from its store and push an updated list back via
|
|
415
|
+
*
|
|
416
|
+
{@link #setConversations}
|
|
417
|
+
.
|
|
418
|
+
*/
|
|
419
|
+
attachConversationDelete<CustomDataType extends object>(data: CustomDataType, fn: (event: ChatBox$ConversationDeleteEvent, data: CustomDataType) => void, listener?: object): this;
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* /**
|
|
423
|
+
* Fired when the user clicks the × on a conversation in the
|
|
424
|
+
* sidebar. The library does not mutate the conversations
|
|
425
|
+
* property itself — the consumer is expected to drop the entry
|
|
426
|
+
* from its store and push an updated list back via
|
|
427
|
+
*
|
|
428
|
+
{@link #setConversations}
|
|
429
|
+
.
|
|
430
|
+
*/
|
|
431
|
+
detachConversationDelete(fn: (event: ChatBox$ConversationDeleteEvent) => void, listener?: object): this;
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* /**
|
|
435
|
+
* Fired when the user clicks the × on a conversation in the
|
|
436
|
+
* sidebar. The library does not mutate the conversations
|
|
437
|
+
* property itself — the consumer is expected to drop the entry
|
|
438
|
+
* from its store and push an updated list back via
|
|
439
|
+
*
|
|
440
|
+
{@link #setConversations}
|
|
441
|
+
.
|
|
442
|
+
*/
|
|
443
|
+
fireConversationDelete(parameters?: ChatBox$ConversationDeleteEventParameters): this;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Interface describing the parameters of ChatBox's 'send' event.
|
|
448
|
+
* /**
|
|
449
|
+
* Fired when the user submits a prompt. The embedding
|
|
450
|
+
* application should produce an assistant response and feed it
|
|
451
|
+
* back via
|
|
452
|
+
{@link #addAssistantMessage}
|
|
453
|
+
or
|
|
454
|
+
*
|
|
455
|
+
{@link #appendToLastAssistantMessage}
|
|
456
|
+
.
|
|
457
|
+
*/
|
|
458
|
+
export interface ChatBox$SendEventParameters {
|
|
459
|
+
message?: string;
|
|
460
|
+
files?: object | null;
|
|
461
|
+
conversationId?: string;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Interface describing the parameters of ChatBox's 'newChat' event.
|
|
466
|
+
* Fired when the user clicks the "Neue Konversation" button.
|
|
467
|
+
The transcript view has already been cleared and
|
|
468
|
+
<code>activeConversationId</code> reset to <code>""</code> by
|
|
469
|
+
the time the event fires — listeners typically use this to
|
|
470
|
+
reset any server-side session state.
|
|
471
|
+
*/
|
|
472
|
+
// eslint-disable-next-line
|
|
473
|
+
export interface ChatBox$NewChatEventParameters {
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Interface describing the parameters of ChatBox's 'conversationSelect' event.
|
|
478
|
+
* Fired when the user picks a conversation from the sidebar.
|
|
479
|
+
The library has already switched the transcript view to that
|
|
480
|
+
conversation and updated <code>activeConversationId</code>.
|
|
481
|
+
*/
|
|
482
|
+
export interface ChatBox$ConversationSelectEventParameters {
|
|
483
|
+
id?: string;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Interface describing the parameters of ChatBox's 'conversationDelete' event.
|
|
488
|
+
* /**
|
|
489
|
+
* Fired when the user clicks the × on a conversation in the
|
|
490
|
+
* sidebar. The library does not mutate the conversations
|
|
491
|
+
* property itself — the consumer is expected to drop the entry
|
|
492
|
+
* from its store and push an updated list back via
|
|
493
|
+
*
|
|
494
|
+
{@link #setConversations}
|
|
495
|
+
.
|
|
496
|
+
*/
|
|
497
|
+
export interface ChatBox$ConversationDeleteEventParameters {
|
|
498
|
+
id?: string;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Type describing the ChatBox's 'send' event.
|
|
503
|
+
* /**
|
|
504
|
+
* Fired when the user submits a prompt. The embedding
|
|
505
|
+
* application should produce an assistant response and feed it
|
|
506
|
+
* back via
|
|
507
|
+
{@link #addAssistantMessage}
|
|
508
|
+
or
|
|
509
|
+
*
|
|
510
|
+
{@link #appendToLastAssistantMessage}
|
|
511
|
+
.
|
|
512
|
+
*/
|
|
513
|
+
export type ChatBox$SendEvent = Event<ChatBox$SendEventParameters>;
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Type describing the ChatBox's 'newChat' event.
|
|
517
|
+
* Fired when the user clicks the "Neue Konversation" button.
|
|
518
|
+
The transcript view has already been cleared and
|
|
519
|
+
<code>activeConversationId</code> reset to <code>""</code> by
|
|
520
|
+
the time the event fires — listeners typically use this to
|
|
521
|
+
reset any server-side session state.
|
|
522
|
+
*/
|
|
523
|
+
export type ChatBox$NewChatEvent = Event<ChatBox$NewChatEventParameters>;
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Type describing the ChatBox's 'conversationSelect' event.
|
|
527
|
+
* Fired when the user picks a conversation from the sidebar.
|
|
528
|
+
The library has already switched the transcript view to that
|
|
529
|
+
conversation and updated <code>activeConversationId</code>.
|
|
530
|
+
*/
|
|
531
|
+
export type ChatBox$ConversationSelectEvent = Event<ChatBox$ConversationSelectEventParameters>;
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Type describing the ChatBox's 'conversationDelete' event.
|
|
535
|
+
* /**
|
|
536
|
+
* Fired when the user clicks the × on a conversation in the
|
|
537
|
+
* sidebar. The library does not mutate the conversations
|
|
538
|
+
* property itself — the consumer is expected to drop the entry
|
|
539
|
+
* from its store and push an updated list back via
|
|
540
|
+
*
|
|
541
|
+
{@link #setConversations}
|
|
542
|
+
.
|
|
543
|
+
*/
|
|
544
|
+
export type ChatBox$ConversationDeleteEvent = Event<ChatBox$ConversationDeleteEventParameters>;
|
|
545
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* ${copyright}
|
|
3
|
+
*/
|
|
4
|
+
sap.ui.define(["sap/ui/core/Control","sap/ui/core/IconPool","sap/ui/core/Lib","sap/base/i18n/Localization","./markdown"],function(t,e,n,s,i){"use strict";function a(t){return t&&t.__esModule&&typeof t.default!=="undefined"?t.default:t}const o=a(i);const c=t.extend("chatui.ChatBox",{renderer:{apiVersion:2,render(t,n){const s=e.getIconInfo("sap-icon://paper-plane");const i=e.getIconInfo("sap-icon://add");const a=e.getIconInfo("sap-icon://attachment");const o=n._i18n();const c=n.getPlaceholder()||o.getText("chatbox.placeholder")||"";const r=n.getAllowAttachments();t.openStart("div",n);t.class("cnetChatBox");t.style("width",n.getWidth());t.style("height",n.getHeight());t.openEnd();t.openStart("aside");t.class("cnetChatBox-sidebar");t.openEnd();t.openStart("div");t.class("cnetChatBox-sidebar-header");t.openEnd();t.openStart("span");t.class("cnetChatBox-sidebar-title");t.openEnd();t.text(o.getText("chatbox.conversations")??"");t.close("span");t.close("div");t.openStart("div",n.getId()+"-conversations");t.class("cnetChatBox-conversations");t.openEnd();t.close("div");t.close("aside");t.openStart("div");t.class("cnetChatBox-main");t.openEnd();t.openStart("div");t.class("cnetChatBox-header");t.openEnd();t.openStart("div",n.getId()+"-headerTitle");t.class("cnetChatBox-header-title");t.openEnd();t.close("div");t.openStart("button",n.getId()+"-newChat");t.class("cnetChatBox-newChatButton");t.attr("type","button");t.attr("title",o.getText("chatbox.newConversation")??"");t.openEnd();t.openStart("span");t.class("cnetChatBox-icon");if(i)t.style("font-family",i.fontFamily);t.openEnd();t.text(i?.content??"+");t.close("span");t.openStart("span");t.class("cnetChatBox-newChatButton-label");t.openEnd();t.text(o.getText("chatbox.newConversation")??"");t.close("span");t.close("button");t.close("div");t.openStart("div",n.getId()+"-messages");t.class("cnetChatBox-messages");t.openEnd();t.openStart("div");t.class("cnetChatBox-empty");t.openEnd();t.text(o.getText("chatbox.emptyHint")??"");t.close("div");t.close("div");t.openStart("div");t.class("cnetChatBox-inputArea");t.openEnd();t.openStart("div");t.class("cnetChatBox-composer");t.openEnd();t.openStart("div",n.getId()+"-pending");t.class("cnetChatBox-attachmentsPending");t.openEnd();t.close("div");t.openStart("textarea",n.getId()+"-input");t.class("cnetChatBox-textarea");t.attr("placeholder",c);t.attr("rows","1");if(n.getBusy())t.attr("disabled","disabled");t.openEnd();t.close("textarea");t.openStart("div");t.class("cnetChatBox-composerBar");t.openEnd();t.openStart("div");t.class("cnetChatBox-composerBar-left");t.openEnd();if(r){t.openStart("button",n.getId()+"-attach");t.class("cnetChatBox-toolButton");t.class("cnetChatBox-attach");t.attr("type","button");t.attr("title",o.getText("chatbox.attach")??"");t.attr("aria-label",o.getText("chatbox.attach")??"");t.openEnd();t.openStart("span");t.class("cnetChatBox-icon");if(a)t.style("font-family",a.fontFamily);t.openEnd();t.text(a?.content??"📎");t.close("span");t.close("button");t.voidStart("input",n.getId()+"-fileinput");t.class("cnetChatBox-fileinput");t.attr("type","file");t.attr("multiple","multiple");if(n.getAttachmentAccept())t.attr("accept",n.getAttachmentAccept());t.voidEnd()}t.close("div");t.openStart("button",n.getId()+"-send");t.class("cnetChatBox-send");t.attr("type","button");t.attr("title",o.getText("chatbox.send")??"");t.attr("aria-label",o.getText("chatbox.send")??"");t.openEnd();t.openStart("span");t.class("cnetChatBox-icon");if(s)t.style("font-family",s.fontFamily);t.openEnd();t.text(s?.content??"➤");t.close("span");t.close("button");t.close("div");t.close("div");t.close("div");t.close("div");if(r){t.openStart("div",n.getId()+"-drop");t.class("cnetChatBox-dropOverlay");t.openEnd();t.openStart("span");t.class("cnetChatBox-dropLabel");t.openEnd();t.text(o.getText("chatbox.dropHere")??"");t.close("span");t.close("div")}t.close("div")}},metadata:{library:"chatui",properties:{placeholder:{type:"string",group:"Appearance",defaultValue:""},busy:{type:"boolean",group:"Behavior",defaultValue:false},width:{type:"sap.ui.core.CSSSize",group:"Dimension",defaultValue:"100%"},height:{type:"sap.ui.core.CSSSize",group:"Dimension",defaultValue:"100%"},allowAttachments:{type:"boolean",group:"Behavior",defaultValue:true},attachmentAccept:{type:"string",group:"Behavior",defaultValue:""},conversations:{type:"object",group:"Data",defaultValue:[]},activeConversationId:{type:"string",group:"Data",defaultValue:""}},events:{send:{parameters:{message:{type:"string"},files:{type:"object"},conversationId:{type:"string"}}},newChat:{},conversationSelect:{parameters:{id:{type:"string"}}},conversationDelete:{parameters:{id:{type:"string"}}}}},constructor:function e(n,s){t.prototype.constructor.call(this,n,s);this._messages=[];this._pendingAttachments=[];this._conversations=[];this._initialised=false;this._onLocaleChange=()=>{this.invalidate()}},init:function t(){s.attachChange(this._onLocaleChange)},exit:function t(){s.detachChange(this._onLocaleChange)},onAfterRendering:function t(){const e=this._dom("input");const n=this._dom("send");const s=this._dom("newChat");e?.addEventListener("input",()=>{e.style.height="auto";e.style.height=Math.min(e.scrollHeight,160)+"px"});e?.addEventListener("keydown",t=>{if(t.key==="Enter"&&!t.shiftKey){t.preventDefault();this._submit()}});n?.addEventListener("click",()=>this._submit());s?.addEventListener("click",()=>this._startNewChat());if(this.getAllowAttachments()){this._wireAttachments()}this._renderSidebar();this._renderHeaderTitle();this._restoreMessages();this._renderPending()},addAssistantMessage:function t(e){this._messages.push({role:"assistant",content:e??""});this._appendMessageDom(this._messages.length-1);return this},appendToLastAssistantMessage:function t(e){if(!e)return this;const n=this._messages[this._messages.length-1];if(!n||n.role!=="assistant"||n.control){return this.addAssistantMessage(e)}n.content+=e;this._updateBubble(this._messages.length-1);return this},addAssistantControl:function t(e){this.addDependent(e);this._messages.push({role:"assistant",content:"",control:e});this._appendMessageDom(this._messages.length-1);return this},clear:function t(){this._messages=[];this._pendingAttachments=[];this.destroyDependents();this._restoreMessages();this._renderPending();return this},getMessages:function t(){return this._messages.slice()},setMessages:function t(e){this._messages=this._sanitiseMessages(e);this.destroyDependents();this._restoreMessages();return this},setConversations:function t(e){const n=this._sanitiseConversations(e);this._conversations=n;this.setProperty("conversations",n,true);if(!this._initialised&&n.length>0&&!this.getActiveConversationId()){const t=n[0];this.setProperty("activeConversationId",t.id,true);this._messages=this._sanitiseMessages(t.messages??[]);this.destroyDependents();this._restoreMessages();this._renderHeaderTitle()}this._initialised=true;this._renderSidebar();return this},getConversations:function t(){return this._conversations.slice()},setActiveConversationId:function t(e){const n=typeof e==="string"?e:"";if(n===this.getActiveConversationId())return this;this.setProperty("activeConversationId",n,true);const s=this._conversations??[];const i=s.find(t=>t.id===n);this._messages=i?this._sanitiseMessages(i.messages??[]):[];this._pendingAttachments=[];this.destroyDependents();this._renderSidebar();this._renderHeaderTitle();this._restoreMessages();this._renderPending();return this},_i18n:function t(){return n.getResourceBundleFor("chatui")},_dom:function t(e){return document.getElementById(this.getId()+"-"+e)},_messagesContainer:function t(){return this._dom("messages")},_sanitiseMessages:function t(e){const n=[];if(!Array.isArray(e))return n;for(const t of e){if(!t||t.role!=="user"&&t.role!=="assistant")continue;if(typeof t.content!=="string")continue;if(t.control)continue;const e={role:t.role,content:t.content};if(Array.isArray(t.files)&&t.files.length>0){e.files=t.files.slice()}n.push(e)}return n},_sanitiseConversations:function t(e){const n=[];if(!Array.isArray(e))return n;for(const t of e){if(!t||typeof t.id!=="string"||!t.id)continue;const e={id:t.id};if(typeof t.title==="string")e.title=t.title;if(Array.isArray(t.messages))e.messages=this._sanitiseMessages(t.messages);if(t.updatedAt!==undefined&&t.updatedAt!==null)e.updatedAt=t.updatedAt;n.push(e)}return n},_submit:function t(){if(this.getBusy())return;const e=this._dom("input");const n=e?.value.trim()??"";const s=this._pendingAttachments.slice();if(!n&&s.length===0)return;if(e){e.value="";e.style.height="auto"}const i={role:"user",content:n};if(s.length>0)i.files=s;this._messages.push(i);this._pendingAttachments=[];this._appendMessageDom(this._messages.length-1);this._renderPending();this.fireEvent("send",{message:n,files:s,conversationId:this.getActiveConversationId()})},_startNewChat:function t(){if(this.getBusy())return;this._messages=[];this._pendingAttachments=[];this.destroyDependents();this.setProperty("activeConversationId","",true);this._renderSidebar();this._renderHeaderTitle();this._restoreMessages();this._renderPending();this.fireEvent("newChat")},_selectConversation:function t(e){if(this.getBusy())return;if(e===this.getActiveConversationId())return;this.setActiveConversationId(e);this.fireEvent("conversationSelect",{id:e})},_requestDeleteConversation:function t(e){if(this.getBusy())return;this.fireEvent("conversationDelete",{id:e})},_buildMessageDom:function t(e){const n=this._messages[e];const s=document.createElement("div");const i=n.role==="assistant";s.className=`cnetChatBox-message cnetChatBox-message--${i?"assistant":"user"}`;const a=document.createElement("div");a.className="cnetChatBox-bubble";this._renderBubble(a,n);s.appendChild(a);if(!n.control){const t=this._buildActions(e,n);if(t)s.appendChild(t)}return s},_buildActions:function t(e,n){const s=document.createElement("div");s.className="cnetChatBox-actions";if(n.role==="assistant"){s.appendChild(this._buildCopyButton(e))}else{s.appendChild(this._buildEditButton(e))}return s},_buildIconButton:function t(n,s,i,a){const o=e.getIconInfo(n);const c=document.createElement("button");c.type="button";c.className=`cnetChatBox-action ${s}`;c.title=i;c.setAttribute("aria-label",i);const r=document.createElement("span");r.className="cnetChatBox-icon";if(o)r.style.fontFamily=o.fontFamily;r.textContent=o?.content??a;c.appendChild(r);return c},_buildCopyButton:function t(e){const n=this._i18n().getText("chatbox.copy")??"Copy";const s=this._buildIconButton("sap-icon://copy","cnetChatBox-copy",n,"⎘");s.addEventListener("click",()=>{const t=this._messages[e];if(!t||!t.content)return;void this._copyMessage(t.content,s)});return s},_buildEditButton:function t(e){const n=this._i18n().getText("chatbox.edit")??"Edit";const s=this._buildIconButton("sap-icon://edit","cnetChatBox-edit",n,"✎");s.addEventListener("click",()=>this._enterEditMode(e));return s},_copyMessage:async function t(e,n){const s=await this._writeClipboard(e);if(!s)return;const i=this._i18n();const a=n.getAttribute("aria-label")??"";const o=i.getText("chatbox.copied")??"Copied";n.classList.add("cnetChatBox-action--done");n.title=o;window.setTimeout(()=>{n.classList.remove("cnetChatBox-action--done");n.title=a},1200)},_enterEditMode:function t(e){if(this.getBusy())return;const n=this._messagesContainer()?.children[e];const s=this._messages[e];if(!n||!s||s.role!=="user")return;const i=n.querySelector(".cnetChatBox-bubble");if(!i)return;const a=n.querySelector(".cnetChatBox-actions");if(a)a.style.display="none";i.textContent="";i.classList.add("cnetChatBox-bubble--editing");if(s.files&&s.files.length>0){i.appendChild(this._buildAttachmentList(s.files,"sent"))}const o=document.createElement("textarea");o.className="cnetChatBox-editTextarea";o.value=s.content;o.rows=2;i.appendChild(o);const c=document.createElement("div");c.className="cnetChatBox-editActions";const r=this._i18n();const d=document.createElement("button");d.type="button";d.className="cnetChatBox-editCancel";d.textContent=r.getText("chatbox.cancel")??"Cancel";const l=document.createElement("button");l.type="button";l.className="cnetChatBox-editSave";l.textContent=r.getText("chatbox.save")??"Save";d.addEventListener("click",()=>this._cancelEdit(e));l.addEventListener("click",()=>this._commitEdit(e,o.value));o.addEventListener("keydown",t=>{if(t.key==="Enter"&&!t.shiftKey){t.preventDefault();this._commitEdit(e,o.value)}else if(t.key==="Escape"){t.preventDefault();this._cancelEdit(e)}});c.appendChild(d);c.appendChild(l);i.appendChild(c);o.focus();o.setSelectionRange(o.value.length,o.value.length)},_cancelEdit:function t(e){const n=this._messagesContainer()?.children[e];const s=this._messages[e];if(!n||!s)return;const i=n.querySelector(".cnetChatBox-bubble");if(!i)return;i.classList.remove("cnetChatBox-bubble--editing");this._renderBubble(i,s);const a=n.querySelector(".cnetChatBox-actions");if(a)a.style.display=""},_commitEdit:function t(e,n){if(this.getBusy())return;const s=this._messages[e];if(!s||s.role!=="user")return;const i=n.trim();const a=s.files?s.files.slice():[];const o=i===s.content;const c=!i&&a.length===0;if(o||c){this._cancelEdit(e);return}for(let t=e+1;t<this._messages.length;t++){const e=this._messages[t];if(e.control)e.control.destroy()}this._messages.length=e+1;s.content=i;this._restoreMessages();this.fireEvent("send",{message:i,files:a,conversationId:this.getActiveConversationId()})},_writeClipboard:async function t(e){try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(e);return true}}catch{}try{const t=document.createElement("textarea");t.value=e;t.setAttribute("readonly","");t.style.position="fixed";t.style.opacity="0";document.body.appendChild(t);t.select();const n=document.execCommand("copy");document.body.removeChild(t);return n}catch{return false}},_renderBubble:function t(e,n){if(n.role==="assistant"){if(n.control){e.classList.remove("cnetChatBox-bubble--pending");e.classList.add("cnetChatBox-bubble--rich");e.innerHTML="";n.control.placeAt(e);return}e.classList.remove("cnetChatBox-bubble--rich");if(!n.content){e.classList.add("cnetChatBox-bubble--pending");e.innerHTML='<span class="cnetChatBox-dots"><span></span><span></span><span></span></span>';return}e.classList.remove("cnetChatBox-bubble--pending");e.innerHTML=o(n.content);return}e.textContent="";if(n.files&&n.files.length>0){e.appendChild(this._buildAttachmentList(n.files,"sent"))}if(n.content){const t=document.createElement("div");t.className="cnetChatBox-bubble-text";t.textContent=n.content;e.appendChild(t)}},_buildAttachmentList:function t(e,n){const s=document.createElement("div");s.className=`cnetChatBox-attachments cnetChatBox-attachments--${n}`;for(let t=0;t<e.length;t++){s.appendChild(this._buildAttachmentItem(e[t],n==="pending"?t:-1))}return s},_buildAttachmentItem:function t(n,s){const i=n.type.startsWith("image/");const a=document.createElement("div");a.className=`cnetChatBox-attachment cnetChatBox-attachment--${i?"image":"file"}`;if(i){const t=document.createElement("img");t.className="cnetChatBox-attachment-thumb";t.alt=n.name;t.src=URL.createObjectURL(n);a.appendChild(t)}else{const t=e.getIconInfo("sap-icon://document");const n=document.createElement("span");n.className="cnetChatBox-icon cnetChatBox-attachment-icon";if(t)n.style.fontFamily=t.fontFamily;n.textContent=t?.content??"📄";a.appendChild(n)}const o=document.createElement("span");o.className="cnetChatBox-attachment-name";o.textContent=n.name;o.title=n.name;a.appendChild(o);if(s>=0){const t=this._i18n();const e=t.getText("chatbox.removeAttachment")??"Remove";const n=document.createElement("button");n.type="button";n.className="cnetChatBox-attachment-remove";n.title=e;n.setAttribute("aria-label",e);n.textContent="×";n.addEventListener("click",()=>this._removePending(s));a.appendChild(n)}return a},_appendMessageDom:function t(e){const n=this._messagesContainer();if(!n)return;n.querySelector(".cnetChatBox-empty")?.remove();n.appendChild(this._buildMessageDom(e));n.scrollTop=n.scrollHeight},_updateBubble:function t(e){const n=this._messagesContainer();const s=n?.children[e];const i=s?.querySelector(".cnetChatBox-bubble");if(!i||!n)return;this._renderBubble(i,this._messages[e]);const a=n.scrollHeight-n.scrollTop-n.clientHeight<80;if(a)n.scrollTop=n.scrollHeight},_restoreMessages:function t(){const e=this._messagesContainer();if(!e)return;e.innerHTML="";if(this._messages.length===0){const t=document.createElement("div");t.className="cnetChatBox-empty";t.textContent=this._i18n().getText("chatbox.emptyHint")??"";e.appendChild(t);return}for(let t=0;t<this._messages.length;t++){e.appendChild(this._buildMessageDom(t))}e.scrollTop=e.scrollHeight},_renderSidebar:function t(){const e=this._dom("conversations");if(!e)return;e.innerHTML="";if(this._conversations.length===0){const t=document.createElement("div");t.className="cnetChatBox-conversations-empty";t.textContent=this._i18n().getText("chatbox.noConversations")??"";e.appendChild(t);return}const n=this.getActiveConversationId();for(const t of this._conversations){e.appendChild(this._buildConversationItem(t,t.id===n))}},_buildConversationItem:function t(e,n){const s=this._i18n();const i=document.createElement("div");i.className="cnetChatBox-conversation"+(n?" cnetChatBox-conversation--active":"");i.setAttribute("role","button");i.tabIndex=0;const a=document.createElement("div");a.className="cnetChatBox-conversation-body";const o=document.createElement("div");o.className="cnetChatBox-conversation-title";o.textContent=this._conversationTitle(e);a.appendChild(o);const c=document.createElement("div");c.className="cnetChatBox-conversation-snippet";c.textContent=this._conversationSnippet(e);a.appendChild(c);const r=document.createElement("div");r.className="cnetChatBox-conversation-time";r.textContent=this._formatTimestamp(e.updatedAt);a.appendChild(r);i.appendChild(a);const d=s.getText("chatbox.deleteConversation")??"Delete conversation";const l=document.createElement("button");l.type="button";l.className="cnetChatBox-conversation-remove";l.title=d;l.setAttribute("aria-label",d);l.textContent="×";l.addEventListener("click",t=>{t.stopPropagation();this._requestDeleteConversation(e.id)});i.appendChild(l);i.addEventListener("click",()=>this._selectConversation(e.id));i.addEventListener("keydown",t=>{if(t.key==="Enter"||t.key===" "){t.preventDefault();this._selectConversation(e.id)}});return i},_conversationTitle:function t(e){if(e.title&&e.title.trim())return e.title.trim();const n=e.messages??[];for(const t of n){if(t.role==="user"&&t.content&&t.content.trim()){return this._truncate(t.content.trim(),40)}}return this._i18n().getText("chatbox.untitledConversation")??"Neue Konversation"},_conversationSnippet:function t(e){const n=e.messages??[];for(let t=n.length-1;t>=0;t--){const e=n[t];if(e.content&&e.content.trim()){const t=e.role==="user"?(this._i18n().getText("chatbox.youPrefix")??"Du:")+" ":"";return this._truncate(t+e.content.trim().replace(/\s+/g," "),60)}}return""},_truncate:function t(e,n){return e.length>n?e.slice(0,n-1).trimEnd()+"…":e},_formatTimestamp:function t(e){if(e===undefined||e===null)return"";const n=e instanceof Date?e:new Date(e);if(isNaN(n.getTime()))return"";const i=new Date;const a=n.toDateString()===i.toDateString();const o=new Date(i);o.setDate(i.getDate()-1);const c=n.toDateString()===o.toDateString();const r=s.getLanguage()||undefined;if(a){return n.toLocaleTimeString(r,{hour:"2-digit",minute:"2-digit"})}if(c){return this._i18n().getText("chatbox.yesterday")??"Gestern"}const d=(i.getTime()-n.getTime())/(1e3*60*60*24);if(d<7){return n.toLocaleDateString(r,{weekday:"short"})}return n.toLocaleDateString(r,{day:"2-digit",month:"2-digit",year:"2-digit"})},_renderHeaderTitle:function t(){const e=this._dom("headerTitle");if(!e)return;const n=this.getActiveConversationId();const s=n?this._conversations.find(t=>t.id===n):undefined;e.textContent=s?this._conversationTitle(s):""},_wireAttachments:function t(){const e=this._dom("attach");const n=this._dom("fileinput");const s=this.getDomRef();e?.addEventListener("click",()=>n?.click());n?.addEventListener("change",()=>{if(!n.files)return;this._addPending(Array.from(n.files));n.value=""});if(!s)return;let i=0;s.addEventListener("dragenter",t=>{if(!this._hasFiles(t))return;t.preventDefault();i++;s.classList.add("cnetChatBox--dragOver")});s.addEventListener("dragover",t=>{if(!this._hasFiles(t))return;t.preventDefault();if(t.dataTransfer)t.dataTransfer.dropEffect="copy"});s.addEventListener("dragleave",()=>{i=Math.max(0,i-1);if(i===0)s.classList.remove("cnetChatBox--dragOver")});s.addEventListener("drop",t=>{if(!this._hasFiles(t))return;t.preventDefault();i=0;s.classList.remove("cnetChatBox--dragOver");const e=t.dataTransfer?.files;if(!e||e.length===0)return;this._addPending(Array.from(e))})},_hasFiles:function t(e){const n=e.dataTransfer?.types;if(!n)return false;for(let t=0;t<n.length;t++){if(n[t]==="Files")return true}return false},_addPending:function t(e){if(this.getBusy())return;if(e.length===0)return;this._pendingAttachments=this._pendingAttachments.concat(e);this._renderPending()},_removePending:function t(e){if(e<0||e>=this._pendingAttachments.length)return;this._pendingAttachments.splice(e,1);this._renderPending()},_renderPending:function t(){const e=this._dom("pending");if(!e)return;e.innerHTML="";if(this._pendingAttachments.length===0){e.classList.remove("cnetChatBox-attachmentsPending--hasItems");return}e.classList.add("cnetChatBox-attachmentsPending--hasItems");e.appendChild(this._buildAttachmentList(this._pendingAttachments,"pending"))}});return c});
|
|
5
|
+
//# sourceMappingURL=ChatBox.js.map
|