@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.
Files changed (55) hide show
  1. package/AGENTS.md +202 -0
  2. package/LICENSE +21 -0
  3. package/README.md +303 -0
  4. package/index.d.ts +23 -0
  5. package/package.json +41 -0
  6. package/resources/chatui/.library +14 -0
  7. package/resources/chatui/ChatBox-dbg.js +1099 -0
  8. package/resources/chatui/ChatBox-dbg.js.map +1 -0
  9. package/resources/chatui/ChatBox.d.ts +308 -0
  10. package/resources/chatui/ChatBox.d.ts.map +1 -0
  11. package/resources/chatui/ChatBox.gen.d.ts +545 -0
  12. package/resources/chatui/ChatBox.js +5 -0
  13. package/resources/chatui/ChatBox.js.map +1 -0
  14. package/resources/chatui/ChatBox.ts +1153 -0
  15. package/resources/chatui/library-dbg.js +28 -0
  16. package/resources/chatui/library-dbg.js.map +1 -0
  17. package/resources/chatui/library-preload.js +17 -0
  18. package/resources/chatui/library-preload.js.map +1 -0
  19. package/resources/chatui/library.d.ts +3 -0
  20. package/resources/chatui/library.d.ts.map +1 -0
  21. package/resources/chatui/library.js +5 -0
  22. package/resources/chatui/library.js.map +1 -0
  23. package/resources/chatui/library.ts +30 -0
  24. package/resources/chatui/manifest.json +52 -0
  25. package/resources/chatui/markdown-dbg.js +116 -0
  26. package/resources/chatui/markdown-dbg.js.map +1 -0
  27. package/resources/chatui/markdown.d.ts +21 -0
  28. package/resources/chatui/markdown.d.ts.map +1 -0
  29. package/resources/chatui/markdown.js +5 -0
  30. package/resources/chatui/markdown.js.map +1 -0
  31. package/resources/chatui/markdown.ts +140 -0
  32. package/resources/chatui/messagebundle.properties +20 -0
  33. package/resources/chatui/messagebundle_en.properties +20 -0
  34. package/resources/chatui/themes/base/ChatBox.less +702 -0
  35. package/resources/chatui/themes/base/library-RTL.css +3 -0
  36. package/resources/chatui/themes/base/library-parameters.json +1 -0
  37. package/resources/chatui/themes/base/library.css +3 -0
  38. package/resources/chatui/themes/base/library.source.less +4 -0
  39. package/resources/chatui/themes/sap_fiori_3/library-RTL.css +3 -0
  40. package/resources/chatui/themes/sap_fiori_3/library-parameters.json +1 -0
  41. package/resources/chatui/themes/sap_fiori_3/library.css +3 -0
  42. package/resources/chatui/themes/sap_fiori_3/library.source.less +3 -0
  43. package/resources/chatui/themes/sap_fiori_3_dark/library-RTL.css +3 -0
  44. package/resources/chatui/themes/sap_fiori_3_dark/library-parameters.json +1 -0
  45. package/resources/chatui/themes/sap_fiori_3_dark/library.css +3 -0
  46. package/resources/chatui/themes/sap_fiori_3_dark/library.source.less +3 -0
  47. package/resources/chatui/themes/sap_fiori_3_hcb/library-RTL.css +3 -0
  48. package/resources/chatui/themes/sap_fiori_3_hcb/library-parameters.json +1 -0
  49. package/resources/chatui/themes/sap_fiori_3_hcb/library.css +3 -0
  50. package/resources/chatui/themes/sap_fiori_3_hcb/library.source.less +3 -0
  51. package/resources/chatui/themes/sap_fiori_3_hcw/library-RTL.css +3 -0
  52. package/resources/chatui/themes/sap_fiori_3_hcw/library-parameters.json +1 -0
  53. package/resources/chatui/themes/sap_fiori_3_hcw/library.css +3 -0
  54. package/resources/chatui/themes/sap_fiori_3_hcw/library.source.less +3 -0
  55. 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>&lt;input type="file"&gt;</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>&lt;input type="file"&gt;</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>&lt;input type="file"&gt;</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