@webority/chat-react 0.37.0 → 0.38.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 (2) hide show
  1. package/dist/chat-react.js +1 -876
  2. package/package.json +9 -11
@@ -1,876 +1 @@
1
- import { ChatApiError as e, DEFAULT_CHAT_LABELS as t, createChatClient as n, createSseParser as r, linkRoute as i, mergeLabels as a, parseBlocks as o, parseInline as s } from "@webority/ui-elements/chat-core";
2
- import { AppActionIcon as c, AppAlert as l, AppButton as u, AppCard as d, AppConfirmDialog as f, AppDataTable as p, AppEmptyState as m, AppIcon as h, AppLink as g, AppSidebarMenu as _, AppSkeleton as v, AppSpinner as y, AppTextarea as b, useFloatingStack as x } from "@webority/ui-react";
3
- import { Fragment as S, useCallback as C, useEffect as w, useId as T, useRef as E, useState as D } from "react";
4
- import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
5
- import { createPortal as j } from "react-dom";
6
- //#region src/components/ActionCard.jsx
7
- function M(e, t) {
8
- return e.kind === "Reply" ? t.actionReply(e.ticketNumber) : e.kind === "Reopen" ? t.actionReopen(e.ticketNumber) : t.actionRaiseTicket;
9
- }
10
- function N(e, t, n) {
11
- return e === "Reply" ? n.actionDoneReply(t) : e === "Reopen" ? n.actionDoneReopen(t) : n.actionDoneRaiseTicket(t);
12
- }
13
- function P({ action: e, confirmAction: t, onViewTicket: n, labels: r }) {
14
- let i = a(r), [o, s] = D("ready"), [c, f] = D(null), [p, m] = D("");
15
- if (o === "dismissed") return /* @__PURE__ */ k("p", {
16
- className: "wui-text-sm text-body-secondary mb-0",
17
- children: i.actionDismissed
18
- });
19
- if (o === "done") return /* @__PURE__ */ k(l, {
20
- variant: "success",
21
- role: "status",
22
- size: "sm",
23
- action: n ? /* @__PURE__ */ k(u, {
24
- size: "sm",
25
- variant: "ghost",
26
- onClick: () => n(c),
27
- children: i.viewTicket
28
- }) : void 0,
29
- children: N(e.kind, c.number, i)
30
- });
31
- async function h() {
32
- s("sending"), m("");
33
- try {
34
- f(await t(e.token)), s("done");
35
- } catch (e) {
36
- m(e?.message || i.actionFailed), s("ready");
37
- }
38
- }
39
- let g = o === "sending", _ = new Date(e.expiresDateTimeUtc).getTime() <= Date.now(), v = e.kind === "RaiseTicket" ? [e.category, e.subject].filter(Boolean).join(" · ") : "";
40
- return /* @__PURE__ */ k(d, {
41
- padding: "sm",
42
- className: "border",
43
- title: M(e, i),
44
- subtitle: v || void 0,
45
- children: /* @__PURE__ */ A("div", {
46
- className: "d-flex flex-column gap-2",
47
- children: [e.kind !== "Reopen" && e.body && /* @__PURE__ */ k("p", {
48
- className: "wui-text-sm mb-0",
49
- style: {
50
- whiteSpace: "pre-wrap",
51
- overflowWrap: "anywhere"
52
- },
53
- children: e.body
54
- }), _ ? /* @__PURE__ */ k("p", {
55
- className: "wui-text-sm text-body-secondary mb-0",
56
- children: i.actionExpired
57
- }) : /* @__PURE__ */ A(O, { children: [
58
- /* @__PURE__ */ k("p", {
59
- className: "wui-text-xs text-body-secondary mb-0",
60
- children: i.actionNote
61
- }),
62
- p && /* @__PURE__ */ k(l, {
63
- size: "sm",
64
- variant: "danger",
65
- children: p
66
- }),
67
- /* @__PURE__ */ A("div", {
68
- className: "d-flex flex-wrap gap-2",
69
- children: [/* @__PURE__ */ k(u, {
70
- size: "sm",
71
- loading: g,
72
- onClick: h,
73
- children: i.actionConfirm
74
- }), /* @__PURE__ */ k(u, {
75
- size: "sm",
76
- variant: "secondary",
77
- disabled: g,
78
- onClick: () => s("dismissed"),
79
- children: i.actionDismiss
80
- })]
81
- })
82
- ] })]
83
- })
84
- });
85
- }
86
- //#endregion
87
- //#region src/components/ChatComposer.jsx
88
- function F({ onSubmit: e, busy: t = !1, disabled: n = !1, maxLength: r = 4e3, inputRef: i, labels: o }) {
89
- let s = a(o), c = T(), [l, d] = D(""), f = t || n || !l.trim();
90
- function p() {
91
- f || (e(l.trim()), d(""));
92
- }
93
- return /* @__PURE__ */ A("form", {
94
- className: "d-flex align-items-end gap-2",
95
- "aria-label": s.composer,
96
- onSubmit: (e) => {
97
- e.preventDefault(), p();
98
- },
99
- children: [
100
- /* @__PURE__ */ k(b, {
101
- id: `${c}-message`,
102
- "aria-label": s.composer,
103
- "aria-describedby": `${c}-hint`,
104
- placeholder: s.placeholder,
105
- rows: 1,
106
- autoGrow: !0,
107
- maxLength: r,
108
- value: l,
109
- disabled: n,
110
- ref: i,
111
- fieldClassName: "flex-grow-1 mb-0",
112
- onChange: (e) => d(e.target.value),
113
- onKeyDown: (e) => {
114
- e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing && (e.preventDefault(), p());
115
- }
116
- }),
117
- /* @__PURE__ */ k("span", {
118
- id: `${c}-hint`,
119
- className: "visually-hidden",
120
- children: s.composerHint
121
- }),
122
- /* @__PURE__ */ k(u, {
123
- type: "submit",
124
- leftIcon: "send",
125
- disabled: f,
126
- children: /* @__PURE__ */ k("span", {
127
- className: "visually-hidden",
128
- children: s.send
129
- })
130
- })
131
- ]
132
- });
133
- }
134
- //#endregion
135
- //#region src/lib/format.js
136
- var I = new Intl.DateTimeFormat("en-IN", {
137
- day: "2-digit",
138
- month: "numeric",
139
- year: "numeric",
140
- hour: "numeric",
141
- minute: "2-digit",
142
- hour12: !0,
143
- timeZoneName: "short"
144
- }), L = [
145
- "Jan",
146
- "Feb",
147
- "Mar",
148
- "Apr",
149
- "May",
150
- "Jun",
151
- "Jul",
152
- "Aug",
153
- "Sep",
154
- "Oct",
155
- "Nov",
156
- "Dec"
157
- ];
158
- function R(e) {
159
- if (!e) return "-";
160
- let t = new Date(e);
161
- if (Number.isNaN(t.getTime())) return "-";
162
- let n = Object.fromEntries(I.formatToParts(t).map((e) => [e.type, e.value]));
163
- return `${n.day} ${L[Number(n.month) - 1]} ${n.year}, ${n.hour}:${n.minute} ${n.dayPeriod.toLowerCase()} ${n.timeZoneName}`;
164
- }
165
- //#endregion
166
- //#region src/components/ChatConversationList.jsx
167
- function z({ client: e, onOpen: t, onDeleted: n, pageSize: r = 20, labels: i }) {
168
- let o = a(i), [s, p] = D([]), [h, g] = D(!0), [_, y] = D(""), [b, x] = D(!1), [S, T] = D(0), [E, O] = D(null), [j, M] = D(!1), [N, P] = D(""), F = C(async (t) => {
169
- g(!0), y("");
170
- try {
171
- let n = await e.listConversations({
172
- skip: t,
173
- take: r
174
- });
175
- p((e) => t === 0 ? n : [...e, ...n]), x(n.length === r);
176
- } catch (e) {
177
- y(e?.message || o.loadFailed);
178
- } finally {
179
- g(!1);
180
- }
181
- }, [
182
- e,
183
- r,
184
- o.loadFailed
185
- ]);
186
- w(() => {
187
- F(0);
188
- }, [F, S]);
189
- async function I() {
190
- M(!0), P("");
191
- try {
192
- await e.deleteConversation(E.publicId), p((e) => e.filter((e) => e.publicId !== E.publicId)), n?.(E.publicId), O(null);
193
- } catch (e) {
194
- P(e?.message || o.deleteFailed);
195
- } finally {
196
- M(!1);
197
- }
198
- }
199
- return !h && !_ && s.length === 0 ? /* @__PURE__ */ k(m, {
200
- icon: "chat",
201
- size: "sm",
202
- title: o.conversationsEmptyTitle,
203
- text: o.conversationsEmptyText
204
- }) : /* @__PURE__ */ A("div", {
205
- className: "d-flex flex-column gap-3",
206
- children: [
207
- _ && /* @__PURE__ */ k(l, {
208
- variant: "danger",
209
- action: /* @__PURE__ */ k(u, {
210
- size: "sm",
211
- variant: "secondary",
212
- onClick: () => T((e) => e + 1),
213
- children: o.retry
214
- }),
215
- children: _
216
- }),
217
- s.length > 0 && /* @__PURE__ */ k("ul", {
218
- className: "list-unstyled d-flex flex-column gap-2 mb-0",
219
- "aria-label": o.conversations,
220
- children: s.map((e) => /* @__PURE__ */ k("li", { children: /* @__PURE__ */ A(d, {
221
- padding: "sm",
222
- className: "border",
223
- bodyClassName: "d-flex align-items-center gap-2",
224
- children: [/* @__PURE__ */ k(u, {
225
- variant: "ghost",
226
- className: "flex-grow-1 text-start",
227
- style: { minWidth: 0 },
228
- onClick: () => t(e),
229
- children: /* @__PURE__ */ A("span", {
230
- className: "d-flex flex-column",
231
- style: { minWidth: 0 },
232
- children: [/* @__PURE__ */ k("span", {
233
- className: "text-truncate fw-semibold",
234
- children: e.title || o.untitled
235
- }), /* @__PURE__ */ k("time", {
236
- dateTime: e.lastMessageDateTimeUtc,
237
- className: "wui-text-xs text-body-secondary",
238
- children: R(e.lastMessageDateTimeUtc)
239
- })]
240
- })
241
- }), /* @__PURE__ */ k(c, {
242
- icon: "trash-2",
243
- danger: !0,
244
- label: o.deleteConversation,
245
- onClick: () => {
246
- P(""), O(e);
247
- }
248
- })]
249
- }) }, e.publicId))
250
- }),
251
- h && /* @__PURE__ */ A("div", {
252
- className: "d-flex flex-column gap-2",
253
- "aria-hidden": "true",
254
- children: [
255
- /* @__PURE__ */ k(v, { height: 44 }),
256
- /* @__PURE__ */ k(v, { height: 44 }),
257
- /* @__PURE__ */ k(v, { height: 44 })
258
- ]
259
- }),
260
- !h && b && /* @__PURE__ */ k(u, {
261
- variant: "secondary",
262
- className: "align-self-center",
263
- onClick: () => F(s.length),
264
- children: o.loadMore
265
- }),
266
- /* @__PURE__ */ k(f, {
267
- open: E !== null,
268
- title: o.deleteConfirmTitle,
269
- message: N ? /* @__PURE__ */ k(l, {
270
- variant: "danger",
271
- children: N
272
- }) : o.deleteConfirmMessage,
273
- confirmLabel: o.deleteConfirm,
274
- cancelLabel: o.cancel,
275
- danger: !0,
276
- loading: j,
277
- onConfirm: I,
278
- onClose: () => {
279
- j || O(null);
280
- }
281
- })
282
- ]
283
- });
284
- }
285
- //#endregion
286
- //#region src/components/ChatLauncher.jsx
287
- var B = {
288
- zIndex: "var(--wui-z-fixed)",
289
- bottom: 0
290
- }, V = {
291
- end: { insetInlineEnd: 0 },
292
- start: { insetInlineStart: 0 }
293
- };
294
- function H({ onClick: e, open: t = !1, position: n = "end", icon: r = "sparkles", compact: i = !1, className: o, style: s, labels: c }) {
295
- let l = a(c);
296
- return i ? /* @__PURE__ */ k(U, {
297
- onClick: e,
298
- open: t,
299
- position: n,
300
- icon: r,
301
- className: o,
302
- style: s,
303
- label: l.launcher
304
- }) : /* @__PURE__ */ k("span", {
305
- "data-support-capture": "exclude",
306
- className: ["position-fixed m-3", o].filter(Boolean).join(" "),
307
- style: {
308
- ...B,
309
- ...V[n],
310
- ...s
311
- },
312
- children: /* @__PURE__ */ k(u, {
313
- leftIcon: r,
314
- className: "rounded-pill",
315
- onClick: e,
316
- "aria-haspopup": "dialog",
317
- "aria-expanded": t,
318
- children: l.launcher
319
- })
320
- });
321
- }
322
- function U({ onClick: e, open: t, position: n, icon: r, className: i, style: a, label: o }) {
323
- let s = x(n);
324
- return s ? j(/* @__PURE__ */ k("span", {
325
- className: ["wui-floating-stack-item wui-floating-stack-item--primary", i].filter(Boolean).join(" "),
326
- style: a,
327
- children: /* @__PURE__ */ k(u, {
328
- className: "wui-floating-btn",
329
- onClick: e,
330
- "aria-label": o,
331
- "aria-haspopup": "dialog",
332
- "aria-expanded": t,
333
- tooltip: o,
334
- tooltipPlacement: n === "start" ? "end" : "start",
335
- children: /* @__PURE__ */ k(h, {
336
- name: r,
337
- size: 24
338
- })
339
- })
340
- }), s) : null;
341
- }
342
- //#endregion
343
- //#region src/markdown.jsx
344
- function W({ tokens: e, resolveLink: t, linkComponent: n }) {
345
- return e.map((e) => {
346
- switch (e.type) {
347
- case "code": return /* @__PURE__ */ k("code", { children: e.text }, e.key);
348
- case "strong": return /* @__PURE__ */ k("strong", { children: /* @__PURE__ */ k(W, {
349
- tokens: e.children,
350
- resolveLink: t,
351
- linkComponent: n
352
- }) }, e.key);
353
- case "em": return /* @__PURE__ */ k("em", { children: /* @__PURE__ */ k(W, {
354
- tokens: e.children,
355
- resolveLink: t,
356
- linkComponent: n
357
- }) }, e.key);
358
- case "link": {
359
- let r = /* @__PURE__ */ k(W, {
360
- tokens: e.children,
361
- resolveLink: t,
362
- linkComponent: n
363
- }), a = i(e.href, t);
364
- return a ? /* @__PURE__ */ k(g, {
365
- href: a,
366
- linkComponent: n,
367
- animation: "static",
368
- children: r
369
- }, e.key) : /* @__PURE__ */ k("span", { children: r }, e.key);
370
- }
371
- default: return /* @__PURE__ */ k(S, { children: e.text }, e.key);
372
- }
373
- });
374
- }
375
- function G({ text: e, resolveLink: t, linkComponent: n }) {
376
- return /* @__PURE__ */ k(W, {
377
- tokens: s(e),
378
- resolveLink: t,
379
- linkComponent: n
380
- });
381
- }
382
- function K({ block: e, resolveLink: t, linkComponent: n }) {
383
- let r = (e) => /* @__PURE__ */ k(G, {
384
- text: e,
385
- resolveLink: t,
386
- linkComponent: n
387
- });
388
- switch (e.type) {
389
- case "heading": return /* @__PURE__ */ k("p", {
390
- className: "fw-semibold mb-2",
391
- children: r(e.text)
392
- });
393
- case "rule": return /* @__PURE__ */ k("hr", { className: "my-2" });
394
- case "code": return /* @__PURE__ */ k("pre", {
395
- className: "wui-text-sm mb-2",
396
- children: /* @__PURE__ */ k("code", { children: e.text })
397
- });
398
- case "list": {
399
- let t = e.items.map((e, t) => /* @__PURE__ */ k("li", { children: r(e) }, t));
400
- return e.ordered ? /* @__PURE__ */ k("ol", {
401
- className: "mb-2 ps-4",
402
- start: e.start === 1 ? void 0 : e.start,
403
- children: t
404
- }) : /* @__PURE__ */ k("ul", {
405
- className: "mb-2 ps-4",
406
- children: t
407
- });
408
- }
409
- case "table": return /* @__PURE__ */ k(p, {
410
- columns: e.header.map((e, t) => ({
411
- key: `c${t}`,
412
- label: r(e),
413
- render: (e) => r(e.cells[t] ?? "")
414
- })),
415
- rows: e.rows.map((e, t) => ({
416
- id: t,
417
- cells: e
418
- })),
419
- density: "compact",
420
- empty: null,
421
- wrapperClassName: "mb-2"
422
- });
423
- default: return /* @__PURE__ */ k("p", {
424
- className: "mb-2",
425
- children: e.lines.map((e, t) => /* @__PURE__ */ A("span", { children: [t > 0 && /* @__PURE__ */ k("br", {}), r(e)] }, t))
426
- });
427
- }
428
- }
429
- function q({ text: e, resolveLink: t, linkComponent: n, className: r }) {
430
- let i = o(e);
431
- return /* @__PURE__ */ k("div", {
432
- className: ["wui-text-sm text-break", r].filter(Boolean).join(" "),
433
- children: i.map((e) => /* @__PURE__ */ k(K, {
434
- block: e,
435
- resolveLink: t,
436
- linkComponent: n
437
- }, e.key))
438
- });
439
- }
440
- //#endregion
441
- //#region src/components/ReplyRating.jsx
442
- function J({ rating: e = null, onRate: t, noteMaxLength: n = 1e3, labels: r }) {
443
- let i = a(r), o = T(), [s, c] = D(!1), [d, f] = D(!1), [p, m] = D(""), [h, g] = D(""), [_, v] = D(!1);
444
- async function y(e, n) {
445
- c(!0), g("");
446
- try {
447
- await t(e, n), f(e === "Down" && n === void 0), v(e === "Up" || n !== void 0), n !== void 0 && m("");
448
- } catch {
449
- g(i.ratingFailed);
450
- } finally {
451
- c(!1);
452
- }
453
- }
454
- return /* @__PURE__ */ A("div", {
455
- className: "d-flex flex-column gap-2",
456
- children: [
457
- /* @__PURE__ */ A("div", {
458
- className: "d-flex flex-wrap align-items-center gap-1",
459
- children: [
460
- /* @__PURE__ */ k(u, {
461
- size: "sm",
462
- variant: e === "Up" ? "subtle" : "ghost",
463
- leftIcon: "check",
464
- "aria-pressed": e === "Up",
465
- disabled: s,
466
- onClick: () => y("Up"),
467
- children: i.rateUp
468
- }),
469
- /* @__PURE__ */ k(u, {
470
- size: "sm",
471
- variant: e === "Down" ? "subtle" : "ghost",
472
- leftIcon: "x",
473
- "aria-pressed": e === "Down",
474
- disabled: s,
475
- onClick: () => y("Down"),
476
- children: i.rateDown
477
- }),
478
- _ && !d && /* @__PURE__ */ k("span", {
479
- className: "wui-text-xs text-body-secondary",
480
- role: "status",
481
- children: i.rated
482
- })
483
- ]
484
- }),
485
- h && /* @__PURE__ */ k(l, {
486
- size: "sm",
487
- variant: "danger",
488
- children: h
489
- }),
490
- d && /* @__PURE__ */ A("form", {
491
- className: "d-flex flex-column gap-2",
492
- onSubmit: (e) => {
493
- e.preventDefault(), y("Down", p);
494
- },
495
- children: [/* @__PURE__ */ k(b, {
496
- id: `${o}-note`,
497
- label: i.ratingNote,
498
- hint: i.ratingNoteHint,
499
- rows: 2,
500
- maxLength: n,
501
- value: p,
502
- onChange: (e) => m(e.target.value)
503
- }), /* @__PURE__ */ A("div", {
504
- className: "d-flex gap-2",
505
- children: [/* @__PURE__ */ k(u, {
506
- type: "submit",
507
- size: "sm",
508
- loading: s,
509
- children: i.ratingNoteSend
510
- }), /* @__PURE__ */ k(u, {
511
- size: "sm",
512
- variant: "secondary",
513
- disabled: s,
514
- onClick: () => {
515
- f(!1), v(!0);
516
- },
517
- children: i.ratingNoteSkip
518
- })]
519
- })]
520
- })
521
- ]
522
- });
523
- }
524
- //#endregion
525
- //#region src/components/ChatMessage.jsx
526
- var Y = {
527
- maxWidth: "85%",
528
- whiteSpace: "pre-wrap",
529
- overflowWrap: "anywhere"
530
- };
531
- function X({ turn: e, onRate: t, resolveLink: n, linkComponent: r, confirmAction: i, onViewTicket: o, renderReply: s, labels: c }) {
532
- let u = a(c), f = e.streaming && !e.answer;
533
- return /* @__PURE__ */ A("li", {
534
- className: "d-flex flex-column gap-2",
535
- children: [e.question && /* @__PURE__ */ A("div", {
536
- className: "align-self-end",
537
- style: Y,
538
- children: [/* @__PURE__ */ A("span", {
539
- className: "visually-hidden",
540
- children: [u.you, ": "]
541
- }), /* @__PURE__ */ k(d, {
542
- padding: "sm",
543
- variant: "muted",
544
- className: "wui-text-sm",
545
- children: e.question
546
- })]
547
- }), /* @__PURE__ */ A("div", {
548
- className: "d-flex flex-column gap-2",
549
- style: { minWidth: 0 },
550
- children: [
551
- /* @__PURE__ */ A("span", {
552
- className: "visually-hidden",
553
- children: [u.assistant, ": "]
554
- }),
555
- /* @__PURE__ */ k("div", {
556
- "aria-live": "polite",
557
- "aria-busy": e.streaming,
558
- children: f ? /* @__PURE__ */ A("span", {
559
- className: "d-inline-flex align-items-center gap-2 wui-text-sm text-body-secondary",
560
- children: [/* @__PURE__ */ k(y, {
561
- size: "sm",
562
- label: u.thinking
563
- }), /* @__PURE__ */ k("span", {
564
- "aria-hidden": "true",
565
- children: u.thinking
566
- })]
567
- }) : e.answer && (s ? s(e, { streaming: !!e.streaming }) : /* @__PURE__ */ k(q, {
568
- text: e.answer,
569
- resolveLink: n,
570
- linkComponent: r
571
- }))
572
- }),
573
- e.error && /* @__PURE__ */ k(l, {
574
- size: "sm",
575
- variant: "danger",
576
- children: e.error.message
577
- }),
578
- i && !e.streaming && e.actions.map((e) => /* @__PURE__ */ k(P, {
579
- action: e,
580
- confirmAction: i,
581
- onViewTicket: o,
582
- labels: c
583
- }, e.token)),
584
- t && e.messageId && !e.streaming && /* @__PURE__ */ k(J, {
585
- rating: e.rating,
586
- onRate: (n, r) => t(e.id, n, r),
587
- labels: c
588
- })
589
- ]
590
- })]
591
- });
592
- }
593
- //#endregion
594
- //#region src/components/ChatThread.jsx
595
- function Z({ turns: e, empty: t, onRate: n, resolveLink: r, linkComponent: i, confirmAction: o, onViewTicket: s, renderReply: c, labels: l }) {
596
- let u = a(l), d = E(null), f = e[e.length - 1];
597
- return w(() => {
598
- d.current?.scrollIntoView({ block: "end" });
599
- }, [
600
- e.length,
601
- f?.answer,
602
- f?.error,
603
- f?.actions
604
- ]), e.length === 0 ? t ?? /* @__PURE__ */ k(m, {
605
- icon: "sparkles",
606
- size: "sm",
607
- title: u.emptyTitle,
608
- text: u.emptyText
609
- }) : /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k("ol", {
610
- className: "list-unstyled d-flex flex-column gap-3 mb-0",
611
- "aria-label": u.thread,
612
- children: e.map((e) => /* @__PURE__ */ k(X, {
613
- turn: e,
614
- onRate: n,
615
- resolveLink: r,
616
- linkComponent: i,
617
- confirmAction: o,
618
- onViewTicket: s,
619
- renderReply: c,
620
- labels: l
621
- }, e.id))
622
- }), /* @__PURE__ */ k("div", { ref: d })] });
623
- }
624
- //#endregion
625
- //#region src/components/ChatPanel.jsx
626
- function Q({ chat: e, open: t, onClose: n, title: r, titleIcon: i = "sparkles", headerActions: o, empty: s, disclaimer: u, maxLength: d = 4e3, allowanceThreshold: f = 10, width: p = "440px", resolveLink: m, linkComponent: g, confirmAction: v, onViewTicket: b, rating: x = !0, renderReply: S, labels: C }) {
627
- let T = a(C), D = E(null), { refreshAllowance: O } = e;
628
- w(() => {
629
- t && O().catch(() => {});
630
- }, [t, O]);
631
- let j = e.messagesLeftToday, M = r ?? T.panelTitle;
632
- return /* @__PURE__ */ k(_, {
633
- show: t,
634
- onHide: n,
635
- side: "right",
636
- width: p,
637
- header: /* @__PURE__ */ A("div", {
638
- className: "drawer-header",
639
- children: [/* @__PURE__ */ A("div", {
640
- className: "drawer-title",
641
- children: [i && /* @__PURE__ */ k("span", {
642
- className: "drawer-title-ic",
643
- children: /* @__PURE__ */ k(h, {
644
- name: i,
645
- size: 18
646
- })
647
- }), M]
648
- }), /* @__PURE__ */ A("div", {
649
- className: "d-flex align-items-center gap-1",
650
- children: [
651
- o,
652
- /* @__PURE__ */ k(c, {
653
- icon: "plus",
654
- label: T.newChat,
655
- onClick: e.newConversation,
656
- disabled: e.turns.length === 0 && !e.loading
657
- }),
658
- /* @__PURE__ */ k(c, {
659
- icon: "x",
660
- label: T.close,
661
- onClick: n
662
- })
663
- ]
664
- })]
665
- }),
666
- footer: /* @__PURE__ */ A("div", {
667
- className: "d-flex flex-column gap-2",
668
- children: [
669
- j !== null && j <= f && /* @__PURE__ */ k("p", {
670
- className: "wui-text-xs text-body-secondary mb-0",
671
- role: "status",
672
- children: T.allowance(j)
673
- }),
674
- /* @__PURE__ */ k(F, {
675
- onSubmit: e.submit,
676
- busy: e.streaming || e.loading,
677
- disabled: j === 0,
678
- maxLength: d,
679
- inputRef: D,
680
- labels: C
681
- }),
682
- /* @__PURE__ */ k("p", {
683
- className: "wui-text-xs text-body-secondary mb-0",
684
- children: u ?? T.disclaimer
685
- })
686
- ]
687
- }),
688
- ariaLabel: typeof M == "string" ? M : T.panelTitle,
689
- onEntered: () => D.current?.focus(),
690
- children: e.loading ? /* @__PURE__ */ k("div", {
691
- className: "d-flex justify-content-center py-4",
692
- children: /* @__PURE__ */ k(y, { label: T.loadingConversation })
693
- }) : e.loadError ? /* @__PURE__ */ k(l, {
694
- variant: "danger",
695
- children: e.loadError.message
696
- }) : /* @__PURE__ */ k(Z, {
697
- turns: e.turns,
698
- empty: s,
699
- onRate: x ? e.rate : void 0,
700
- resolveLink: m,
701
- linkComponent: g,
702
- confirmAction: v,
703
- onViewTicket: b,
704
- renderReply: S,
705
- labels: C
706
- })
707
- });
708
- }
709
- //#endregion
710
- //#region src/useChat.js
711
- function $(e) {
712
- return {
713
- code: e?.code || "unknown",
714
- message: e?.message || "Something went wrong. Please try again.",
715
- resetsAtUtc: e?.resetsAtUtc ?? null
716
- };
717
- }
718
- function ee(e) {
719
- if (!e) return [];
720
- let t = JSON.parse(e);
721
- return Array.isArray(t) ? t : [];
722
- }
723
- function te(e) {
724
- let t = [];
725
- for (let n of e ?? []) {
726
- if (n.role === "User") {
727
- t.push({
728
- id: n.publicId,
729
- question: n.content,
730
- answer: "",
731
- streaming: !1,
732
- error: null,
733
- actions: [],
734
- messageId: null,
735
- rating: null,
736
- ratingNote: null
737
- });
738
- continue;
739
- }
740
- let e = t[t.length - 1], r = {
741
- answer: n.content,
742
- actions: ee(n.actionsJson),
743
- messageId: n.publicId,
744
- rating: n.rating ?? null,
745
- ratingNote: n.ratingNote ?? null
746
- };
747
- e && e.messageId === null && e.answer === "" ? Object.assign(e, r) : t.push({
748
- id: n.publicId,
749
- question: "",
750
- streaming: !1,
751
- error: null,
752
- ...r
753
- });
754
- }
755
- return t;
756
- }
757
- function ne({ client: e, pageContext: t }) {
758
- let [n, r] = D([]), [i, a] = D(null), [o, s] = D(null), [c, l] = D(!1), [u, d] = D(null), f = E(null), p = E(0), m = E(0), h = E(t);
759
- h.current = t;
760
- let g = E(null);
761
- g.current = i;
762
- let _ = E(n);
763
- _.current = n;
764
- let v = C(() => {
765
- p.current += 1, f.current?.abort(), f.current = null;
766
- }, []);
767
- w(() => v, [v]);
768
- let y = C((e, t) => {
769
- r((n) => n.map((n) => n.id === e ? {
770
- ...n,
771
- ...typeof t == "function" ? t(n) : t
772
- } : n));
773
- }, []), b = C(async (t) => {
774
- let n = typeof t == "string" ? t.trim() : "";
775
- if (!n || f.current) return;
776
- let i = p.current, o = new AbortController();
777
- f.current = o, m.current += 1;
778
- let c = `turn-${m.current}`;
779
- r((e) => [...e, {
780
- id: c,
781
- question: n,
782
- answer: "",
783
- streaming: !0,
784
- error: null,
785
- actions: [],
786
- messageId: null,
787
- rating: null,
788
- ratingNote: null
789
- }]);
790
- let l = () => i === p.current && !o.signal.aborted;
791
- try {
792
- let t = await e.sendMessage({
793
- message: n,
794
- conversationId: g.current,
795
- pageContext: h.current
796
- }, {
797
- signal: o.signal,
798
- onEvent: (e, t) => {
799
- l() && (e === "delta" ? y(c, (e) => ({ answer: e.answer + (t?.text ?? "") })) : e === "reset" ? y(c, { answer: "" }) : e === "actions" && y(c, { actions: Array.isArray(t?.actions) ? t.actions : [] }));
800
- }
801
- });
802
- if (!l()) return;
803
- y(c, {
804
- answer: t.reply,
805
- messageId: t.messageId ?? null,
806
- streaming: !1
807
- }), g.current = t.conversationId, a(t.conversationId), s(t.messagesLeftToday ?? null);
808
- } catch (e) {
809
- if (!l()) return;
810
- y(c, {
811
- answer: "",
812
- actions: [],
813
- streaming: !1,
814
- error: $(e)
815
- }), e?.code === "daily-limit" && s(0), e?.code === "conversation-not-found" && (g.current = null, a(null));
816
- } finally {
817
- f.current === o && (f.current = null);
818
- }
819
- }, [e, y]), x = C(async (t) => {
820
- v();
821
- let n = p.current;
822
- r([]), a(null), d(null), l(!0);
823
- try {
824
- let i = await e.getConversation(t);
825
- if (n !== p.current) return;
826
- r(te(i.messages)), a(i.publicId);
827
- } catch (e) {
828
- if (n !== p.current) return;
829
- d($(e));
830
- } finally {
831
- n === p.current && l(!1);
832
- }
833
- }, [v, e]), S = C(() => {
834
- v(), r([]), a(null), d(null), l(!1);
835
- }, [v]), T = C(() => {
836
- v(), r([]), a(null), s(null), d(null), l(!1);
837
- }, [v]), O = C(async () => {
838
- let t = p.current, n = await e.getAllowance();
839
- t === p.current && s(n?.messagesLeftToday ?? null);
840
- }, [e]), k = C(async (t, n, r) => {
841
- let i = _.current.find((e) => e.id === t), a = g.current;
842
- if (!i?.messageId || !a) throw Error("Only a stored reply can be rated.");
843
- let o = {
844
- rating: i.rating,
845
- ratingNote: i.ratingNote
846
- }, s = typeof r == "string" && r.trim() ? r.trim() : null;
847
- y(t, {
848
- rating: n,
849
- ratingNote: s
850
- });
851
- try {
852
- await e.rateMessage(a, i.messageId, {
853
- rating: n,
854
- note: s
855
- });
856
- } catch (e) {
857
- throw y(t, o), e;
858
- }
859
- }, [e, y]);
860
- return {
861
- turns: n,
862
- conversationId: i,
863
- messagesLeftToday: o,
864
- streaming: n.some((e) => e.streaming),
865
- loading: c,
866
- loadError: u,
867
- submit: b,
868
- openConversation: x,
869
- newConversation: S,
870
- rate: k,
871
- refreshAllowance: O,
872
- reset: T
873
- };
874
- }
875
- //#endregion
876
- export { P as ActionCard, e as ChatApiError, F as ChatComposer, z as ChatConversationList, H as ChatLauncher, q as ChatMarkdown, X as ChatMessage, Q as ChatPanel, Z as ChatThread, t as DEFAULT_CHAT_LABELS, J as ReplyRating, n as createChatClient, r as createSseParser, ne as useChat };
1
+ import{ChatApiError as e,DEFAULT_CHAT_LABELS as t,createChatClient as n,createSseParser as r,linkRoute as i,mergeLabels as a,parseBlocks as o,parseInline as s}from"@webority/ui-elements/chat-core";import{AppActionIcon as c,AppAlert as l,AppButton as u,AppCard as d,AppConfirmDialog as f,AppDataTable as p,AppEmptyState as m,AppIcon as h,AppLink as g,AppSidebarMenu as _,AppSkeleton as v,AppSpinner as y,AppTextarea as b,useFloatingStack as x}from"@webority/ui-react";import{Fragment as S,useCallback as C,useEffect as w,useId as T,useRef as E,useState as D}from"react";import{Fragment as O,jsx as k,jsxs as A}from"react/jsx-runtime";import{createPortal as j}from"react-dom";function M(e,t){return e.kind===`Reply`?t.actionReply(e.ticketNumber):e.kind===`Reopen`?t.actionReopen(e.ticketNumber):t.actionRaiseTicket}function N(e,t,n){return e===`Reply`?n.actionDoneReply(t):e===`Reopen`?n.actionDoneReopen(t):n.actionDoneRaiseTicket(t)}function P({action:e,confirmAction:t,onViewTicket:n,labels:r}){let i=a(r),[o,s]=D(`ready`),[c,f]=D(null),[p,m]=D(``);if(o===`dismissed`)return k(`p`,{className:`wui-text-sm text-body-secondary mb-0`,children:i.actionDismissed});if(o===`done`)return k(l,{variant:`success`,role:`status`,size:`sm`,action:n?k(u,{size:`sm`,variant:`ghost`,onClick:()=>n(c),children:i.viewTicket}):void 0,children:N(e.kind,c.number,i)});async function h(){s(`sending`),m(``);try{f(await t(e.token)),s(`done`)}catch(e){m(e?.message||i.actionFailed),s(`ready`)}}let g=o===`sending`,_=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),v=e.kind===`RaiseTicket`?[e.category,e.subject].filter(Boolean).join(` · `):``;return k(d,{padding:`sm`,className:`border`,title:M(e,i),subtitle:v||void 0,children:A(`div`,{className:`d-flex flex-column gap-2`,children:[e.kind!==`Reopen`&&e.body&&k(`p`,{className:`wui-text-sm mb-0`,style:{whiteSpace:`pre-wrap`,overflowWrap:`anywhere`},children:e.body}),_?k(`p`,{className:`wui-text-sm text-body-secondary mb-0`,children:i.actionExpired}):A(O,{children:[k(`p`,{className:`wui-text-xs text-body-secondary mb-0`,children:i.actionNote}),p&&k(l,{size:`sm`,variant:`danger`,children:p}),A(`div`,{className:`d-flex flex-wrap gap-2`,children:[k(u,{size:`sm`,loading:g,onClick:h,children:i.actionConfirm}),k(u,{size:`sm`,variant:`secondary`,disabled:g,onClick:()=>s(`dismissed`),children:i.actionDismiss})]})]})]})})}function F({onSubmit:e,busy:t=!1,disabled:n=!1,maxLength:r=4e3,inputRef:i,labels:o}){let s=a(o),c=T(),[l,d]=D(``),f=t||n||!l.trim();function p(){f||(e(l.trim()),d(``))}return A(`form`,{className:`d-flex align-items-end gap-2`,"aria-label":s.composer,onSubmit:e=>{e.preventDefault(),p()},children:[k(b,{id:`${c}-message`,"aria-label":s.composer,"aria-describedby":`${c}-hint`,placeholder:s.placeholder,rows:1,autoGrow:!0,maxLength:r,value:l,disabled:n,ref:i,fieldClassName:`flex-grow-1 mb-0`,onChange:e=>d(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),p())}}),k(`span`,{id:`${c}-hint`,className:`visually-hidden`,children:s.composerHint}),k(u,{type:`submit`,leftIcon:`send`,disabled:f,children:k(`span`,{className:`visually-hidden`,children:s.send})})]})}var I=new Intl.DateTimeFormat(`en-IN`,{day:`2-digit`,month:`numeric`,year:`numeric`,hour:`numeric`,minute:`2-digit`,hour12:!0,timeZoneName:`short`}),L=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`];function R(e){if(!e)return`-`;let t=new Date(e);if(Number.isNaN(t.getTime()))return`-`;let n=Object.fromEntries(I.formatToParts(t).map(e=>[e.type,e.value]));return`${n.day} ${L[Number(n.month)-1]} ${n.year}, ${n.hour}:${n.minute} ${n.dayPeriod.toLowerCase()} ${n.timeZoneName}`}function z({client:e,onOpen:t,onDeleted:n,pageSize:r=20,labels:i}){let o=a(i),[s,p]=D([]),[h,g]=D(!0),[_,y]=D(``),[b,x]=D(!1),[S,T]=D(0),[E,O]=D(null),[j,M]=D(!1),[N,P]=D(``),F=C(async t=>{g(!0),y(``);try{let n=await e.listConversations({skip:t,take:r});p(e=>t===0?n:[...e,...n]),x(n.length===r)}catch(e){y(e?.message||o.loadFailed)}finally{g(!1)}},[e,r,o.loadFailed]);w(()=>{F(0)},[F,S]);async function I(){M(!0),P(``);try{await e.deleteConversation(E.publicId),p(e=>e.filter(e=>e.publicId!==E.publicId)),n?.(E.publicId),O(null)}catch(e){P(e?.message||o.deleteFailed)}finally{M(!1)}}return!h&&!_&&s.length===0?k(m,{icon:`chat`,size:`sm`,title:o.conversationsEmptyTitle,text:o.conversationsEmptyText}):A(`div`,{className:`d-flex flex-column gap-3`,children:[_&&k(l,{variant:`danger`,action:k(u,{size:`sm`,variant:`secondary`,onClick:()=>T(e=>e+1),children:o.retry}),children:_}),s.length>0&&k(`ul`,{className:`list-unstyled d-flex flex-column gap-2 mb-0`,"aria-label":o.conversations,children:s.map(e=>k(`li`,{children:A(d,{padding:`sm`,className:`border`,bodyClassName:`d-flex align-items-center gap-2`,children:[k(u,{variant:`ghost`,className:`flex-grow-1 text-start`,style:{minWidth:0},onClick:()=>t(e),children:A(`span`,{className:`d-flex flex-column`,style:{minWidth:0},children:[k(`span`,{className:`text-truncate fw-semibold`,children:e.title||o.untitled}),k(`time`,{dateTime:e.lastMessageDateTimeUtc,className:`wui-text-xs text-body-secondary`,children:R(e.lastMessageDateTimeUtc)})]})}),k(c,{icon:`trash-2`,danger:!0,label:o.deleteConversation,onClick:()=>{P(``),O(e)}})]})},e.publicId))}),h&&A(`div`,{className:`d-flex flex-column gap-2`,"aria-hidden":`true`,children:[k(v,{height:44}),k(v,{height:44}),k(v,{height:44})]}),!h&&b&&k(u,{variant:`secondary`,className:`align-self-center`,onClick:()=>F(s.length),children:o.loadMore}),k(f,{open:E!==null,title:o.deleteConfirmTitle,message:N?k(l,{variant:`danger`,children:N}):o.deleteConfirmMessage,confirmLabel:o.deleteConfirm,cancelLabel:o.cancel,danger:!0,loading:j,onConfirm:I,onClose:()=>{j||O(null)}})]})}var B={zIndex:`var(--wui-z-fixed)`,bottom:0},V={end:{insetInlineEnd:0},start:{insetInlineStart:0}};function H({onClick:e,open:t=!1,position:n=`end`,icon:r=`sparkles`,compact:i=!1,className:o,style:s,labels:c}){let l=a(c);return i?k(U,{onClick:e,open:t,position:n,icon:r,className:o,style:s,label:l.launcher}):k(`span`,{"data-support-capture":`exclude`,className:[`position-fixed m-3`,o].filter(Boolean).join(` `),style:{...B,...V[n],...s},children:k(u,{leftIcon:r,className:`rounded-pill`,onClick:e,"aria-haspopup":`dialog`,"aria-expanded":t,children:l.launcher})})}function U({onClick:e,open:t,position:n,icon:r,className:i,style:a,label:o}){let s=x(n);return s?j(k(`span`,{className:[`wui-floating-stack-item wui-floating-stack-item--primary`,i].filter(Boolean).join(` `),style:a,children:k(u,{className:`wui-floating-btn`,onClick:e,"aria-label":o,"aria-haspopup":`dialog`,"aria-expanded":t,tooltip:o,tooltipPlacement:n===`start`?`end`:`start`,children:k(h,{name:r,size:24})})}),s):null}function W({tokens:e,resolveLink:t,linkComponent:n}){return e.map(e=>{switch(e.type){case`code`:return k(`code`,{children:e.text},e.key);case`strong`:return k(`strong`,{children:k(W,{tokens:e.children,resolveLink:t,linkComponent:n})},e.key);case`em`:return k(`em`,{children:k(W,{tokens:e.children,resolveLink:t,linkComponent:n})},e.key);case`link`:{let r=k(W,{tokens:e.children,resolveLink:t,linkComponent:n}),a=i(e.href,t);return a?k(g,{href:a,linkComponent:n,animation:`static`,children:r},e.key):k(`span`,{children:r},e.key)}default:return k(S,{children:e.text},e.key)}})}function G({text:e,resolveLink:t,linkComponent:n}){return k(W,{tokens:s(e),resolveLink:t,linkComponent:n})}function K({block:e,resolveLink:t,linkComponent:n}){let r=e=>k(G,{text:e,resolveLink:t,linkComponent:n});switch(e.type){case`heading`:return k(`p`,{className:`fw-semibold mb-2`,children:r(e.text)});case`rule`:return k(`hr`,{className:`my-2`});case`code`:return k(`pre`,{className:`wui-text-sm mb-2`,children:k(`code`,{children:e.text})});case`list`:{let t=e.items.map((e,t)=>k(`li`,{children:r(e)},t));return e.ordered?k(`ol`,{className:`mb-2 ps-4`,start:e.start===1?void 0:e.start,children:t}):k(`ul`,{className:`mb-2 ps-4`,children:t})}case`table`:return k(p,{columns:e.header.map((e,t)=>({key:`c${t}`,label:r(e),render:e=>r(e.cells[t]??``)})),rows:e.rows.map((e,t)=>({id:t,cells:e})),density:`compact`,empty:null,wrapperClassName:`mb-2`});default:return k(`p`,{className:`mb-2`,children:e.lines.map((e,t)=>A(`span`,{children:[t>0&&k(`br`,{}),r(e)]},t))})}}function q({text:e,resolveLink:t,linkComponent:n,className:r}){let i=o(e);return k(`div`,{className:[`wui-text-sm text-break`,r].filter(Boolean).join(` `),children:i.map(e=>k(K,{block:e,resolveLink:t,linkComponent:n},e.key))})}function J({rating:e=null,onRate:t,noteMaxLength:n=1e3,labels:r}){let i=a(r),o=T(),[s,c]=D(!1),[d,f]=D(!1),[p,m]=D(``),[h,g]=D(``),[_,v]=D(!1);async function y(e,n){c(!0),g(``);try{await t(e,n),f(e===`Down`&&n===void 0),v(e===`Up`||n!==void 0),n!==void 0&&m(``)}catch{g(i.ratingFailed)}finally{c(!1)}}return A(`div`,{className:`d-flex flex-column gap-2`,children:[A(`div`,{className:`d-flex flex-wrap align-items-center gap-1`,children:[k(u,{size:`sm`,variant:e===`Up`?`subtle`:`ghost`,leftIcon:`check`,"aria-pressed":e===`Up`,disabled:s,onClick:()=>y(`Up`),children:i.rateUp}),k(u,{size:`sm`,variant:e===`Down`?`subtle`:`ghost`,leftIcon:`x`,"aria-pressed":e===`Down`,disabled:s,onClick:()=>y(`Down`),children:i.rateDown}),_&&!d&&k(`span`,{className:`wui-text-xs text-body-secondary`,role:`status`,children:i.rated})]}),h&&k(l,{size:`sm`,variant:`danger`,children:h}),d&&A(`form`,{className:`d-flex flex-column gap-2`,onSubmit:e=>{e.preventDefault(),y(`Down`,p)},children:[k(b,{id:`${o}-note`,label:i.ratingNote,hint:i.ratingNoteHint,rows:2,maxLength:n,value:p,onChange:e=>m(e.target.value)}),A(`div`,{className:`d-flex gap-2`,children:[k(u,{type:`submit`,size:`sm`,loading:s,children:i.ratingNoteSend}),k(u,{size:`sm`,variant:`secondary`,disabled:s,onClick:()=>{f(!1),v(!0)},children:i.ratingNoteSkip})]})]})]})}var Y={maxWidth:`85%`,whiteSpace:`pre-wrap`,overflowWrap:`anywhere`};function X({turn:e,onRate:t,resolveLink:n,linkComponent:r,confirmAction:i,onViewTicket:o,renderReply:s,labels:c}){let u=a(c),f=e.streaming&&!e.answer;return A(`li`,{className:`d-flex flex-column gap-2`,children:[e.question&&A(`div`,{className:`align-self-end`,style:Y,children:[A(`span`,{className:`visually-hidden`,children:[u.you,`: `]}),k(d,{padding:`sm`,variant:`muted`,className:`wui-text-sm`,children:e.question})]}),A(`div`,{className:`d-flex flex-column gap-2`,style:{minWidth:0},children:[A(`span`,{className:`visually-hidden`,children:[u.assistant,`: `]}),k(`div`,{"aria-live":`polite`,"aria-busy":e.streaming,children:f?A(`span`,{className:`d-inline-flex align-items-center gap-2 wui-text-sm text-body-secondary`,children:[k(y,{size:`sm`,label:u.thinking}),k(`span`,{"aria-hidden":`true`,children:u.thinking})]}):e.answer&&(s?s(e,{streaming:!!e.streaming}):k(q,{text:e.answer,resolveLink:n,linkComponent:r}))}),e.error&&k(l,{size:`sm`,variant:`danger`,children:e.error.message}),i&&!e.streaming&&e.actions.map(e=>k(P,{action:e,confirmAction:i,onViewTicket:o,labels:c},e.token)),t&&e.messageId&&!e.streaming&&k(J,{rating:e.rating,onRate:(n,r)=>t(e.id,n,r),labels:c})]})]})}function Z({turns:e,empty:t,onRate:n,resolveLink:r,linkComponent:i,confirmAction:o,onViewTicket:s,renderReply:c,labels:l}){let u=a(l),d=E(null),f=e[e.length-1];return w(()=>{d.current?.scrollIntoView({block:`end`})},[e.length,f?.answer,f?.error,f?.actions]),e.length===0?t??k(m,{icon:`sparkles`,size:`sm`,title:u.emptyTitle,text:u.emptyText}):A(O,{children:[k(`ol`,{className:`list-unstyled d-flex flex-column gap-3 mb-0`,"aria-label":u.thread,children:e.map(e=>k(X,{turn:e,onRate:n,resolveLink:r,linkComponent:i,confirmAction:o,onViewTicket:s,renderReply:c,labels:l},e.id))}),k(`div`,{ref:d})]})}function Q({chat:e,open:t,onClose:n,title:r,titleIcon:i=`sparkles`,headerActions:o,empty:s,disclaimer:u,maxLength:d=4e3,allowanceThreshold:f=10,width:p=`440px`,resolveLink:m,linkComponent:g,confirmAction:v,onViewTicket:b,rating:x=!0,renderReply:S,labels:C}){let T=a(C),D=E(null),{refreshAllowance:O}=e;w(()=>{t&&O().catch(()=>{})},[t,O]);let j=e.messagesLeftToday,M=r??T.panelTitle;return k(_,{show:t,onHide:n,side:`right`,width:p,header:A(`div`,{className:`drawer-header`,children:[A(`div`,{className:`drawer-title`,children:[i&&k(`span`,{className:`drawer-title-ic`,children:k(h,{name:i,size:18})}),M]}),A(`div`,{className:`d-flex align-items-center gap-1`,children:[o,k(c,{icon:`plus`,label:T.newChat,onClick:e.newConversation,disabled:e.turns.length===0&&!e.loading}),k(c,{icon:`x`,label:T.close,onClick:n})]})]}),footer:A(`div`,{className:`d-flex flex-column gap-2`,children:[j!==null&&j<=f&&k(`p`,{className:`wui-text-xs text-body-secondary mb-0`,role:`status`,children:T.allowance(j)}),k(F,{onSubmit:e.submit,busy:e.streaming||e.loading,disabled:j===0,maxLength:d,inputRef:D,labels:C}),k(`p`,{className:`wui-text-xs text-body-secondary mb-0`,children:u??T.disclaimer})]}),ariaLabel:typeof M==`string`?M:T.panelTitle,onEntered:()=>D.current?.focus(),children:e.loading?k(`div`,{className:`d-flex justify-content-center py-4`,children:k(y,{label:T.loadingConversation})}):e.loadError?k(l,{variant:`danger`,children:e.loadError.message}):k(Z,{turns:e.turns,empty:s,onRate:x?e.rate:void 0,resolveLink:m,linkComponent:g,confirmAction:v,onViewTicket:b,renderReply:S,labels:C})})}function $(e){return{code:e?.code||`unknown`,message:e?.message||`Something went wrong. Please try again.`,resetsAtUtc:e?.resetsAtUtc??null}}function ee(e){if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t:[]}function te(e){let t=[];for(let n of e??[]){if(n.role===`User`){t.push({id:n.publicId,question:n.content,answer:``,streaming:!1,error:null,actions:[],messageId:null,rating:null,ratingNote:null});continue}let e=t[t.length-1],r={answer:n.content,actions:ee(n.actionsJson),messageId:n.publicId,rating:n.rating??null,ratingNote:n.ratingNote??null};e&&e.messageId===null&&e.answer===``?Object.assign(e,r):t.push({id:n.publicId,question:``,streaming:!1,error:null,...r})}return t}function ne({client:e,pageContext:t}){let[n,r]=D([]),[i,a]=D(null),[o,s]=D(null),[c,l]=D(!1),[u,d]=D(null),f=E(null),p=E(0),m=E(0),h=E(t);h.current=t;let g=E(null);g.current=i;let _=E(n);_.current=n;let v=C(()=>{p.current+=1,f.current?.abort(),f.current=null},[]);w(()=>v,[v]);let y=C((e,t)=>{r(n=>n.map(n=>n.id===e?{...n,...typeof t==`function`?t(n):t}:n))},[]),b=C(async t=>{let n=typeof t==`string`?t.trim():``;if(!n||f.current)return;let i=p.current,o=new AbortController;f.current=o,m.current+=1;let c=`turn-${m.current}`;r(e=>[...e,{id:c,question:n,answer:``,streaming:!0,error:null,actions:[],messageId:null,rating:null,ratingNote:null}]);let l=()=>i===p.current&&!o.signal.aborted;try{let t=await e.sendMessage({message:n,conversationId:g.current,pageContext:h.current},{signal:o.signal,onEvent:(e,t)=>{l()&&(e===`delta`?y(c,e=>({answer:e.answer+(t?.text??``)})):e===`reset`?y(c,{answer:``}):e===`actions`&&y(c,{actions:Array.isArray(t?.actions)?t.actions:[]}))}});if(!l())return;y(c,{answer:t.reply,messageId:t.messageId??null,streaming:!1}),g.current=t.conversationId,a(t.conversationId),s(t.messagesLeftToday??null)}catch(e){if(!l())return;y(c,{answer:``,actions:[],streaming:!1,error:$(e)}),e?.code===`daily-limit`&&s(0),e?.code===`conversation-not-found`&&(g.current=null,a(null))}finally{f.current===o&&(f.current=null)}},[e,y]),x=C(async t=>{v();let n=p.current;r([]),a(null),d(null),l(!0);try{let i=await e.getConversation(t);if(n!==p.current)return;r(te(i.messages)),a(i.publicId)}catch(e){if(n!==p.current)return;d($(e))}finally{n===p.current&&l(!1)}},[v,e]),S=C(()=>{v(),r([]),a(null),d(null),l(!1)},[v]),T=C(()=>{v(),r([]),a(null),s(null),d(null),l(!1)},[v]),O=C(async()=>{let t=p.current,n=await e.getAllowance();t===p.current&&s(n?.messagesLeftToday??null)},[e]),k=C(async(t,n,r)=>{let i=_.current.find(e=>e.id===t),a=g.current;if(!i?.messageId||!a)throw Error(`Only a stored reply can be rated.`);let o={rating:i.rating,ratingNote:i.ratingNote},s=typeof r==`string`&&r.trim()?r.trim():null;y(t,{rating:n,ratingNote:s});try{await e.rateMessage(a,i.messageId,{rating:n,note:s})}catch(e){throw y(t,o),e}},[e,y]);return{turns:n,conversationId:i,messagesLeftToday:o,streaming:n.some(e=>e.streaming),loading:c,loadError:u,submit:b,openConversation:x,newConversation:S,rate:k,refreshAllowance:O,reset:T}}export{P as ActionCard,e as ChatApiError,F as ChatComposer,z as ChatConversationList,H as ChatLauncher,q as ChatMarkdown,X as ChatMessage,Q as ChatPanel,Z as ChatThread,t as DEFAULT_CHAT_LABELS,J as ReplyRating,n as createChatClient,r as createSseParser,ne as useChat};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/chat-react",
3
- "version": "0.37.0",
3
+ "version": "0.38.0",
4
4
  "description": "Webority AI assistant for React portals: a streaming chat client, a store-agnostic chat hook, and the launcher, panel, thread, rating and support action card, built on @webority/ui-react.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -8,13 +8,11 @@
8
8
  "access": "public",
9
9
  "registry": "https://registry.npmjs.org/"
10
10
  },
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/Webority/webority-ui.git",
14
- "directory": "packages/chat-react"
15
- },
16
11
  "files": [
17
- "dist"
12
+ "dist",
13
+ "!dist/**/__tests__",
14
+ "!dist/**/*.test.*",
15
+ "!dist/**/*.map"
18
16
  ],
19
17
  "main": "./dist/chat-react.js",
20
18
  "module": "./dist/chat-react.js",
@@ -32,8 +30,8 @@
32
30
  "react": "^19.0.0",
33
31
  "react-bootstrap": "^2.10.0",
34
32
  "react-dom": "^19.0.0",
35
- "@webority/ui-elements": "0.37.0",
36
- "@webority/ui-react": "0.37.0"
33
+ "@webority/ui-elements": "0.38.0",
34
+ "@webority/ui-react": "0.38.0"
37
35
  },
38
36
  "devDependencies": {
39
37
  "@testing-library/dom": "10.4.2",
@@ -51,8 +49,8 @@
51
49
  "typescript": "^7.0.2",
52
50
  "vite": "^8.0.12",
53
51
  "vitest": "5.0.1",
54
- "@webority/ui-elements": "0.37.0",
55
- "@webority/ui-react": "0.37.0"
52
+ "@webority/ui-elements": "0.38.0",
53
+ "@webority/ui-react": "0.38.0"
56
54
  },
57
55
  "scripts": {
58
56
  "build": "vite build && tsc -p tsconfig.json",