@cossistant/react 0.0.30 → 0.0.31
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/README.md +3 -1
- package/hooks/private/use-grouped-messages.d.ts.map +1 -1
- package/hooks/private/use-grouped-messages.js +34 -10
- package/hooks/private/use-grouped-messages.js.map +1 -1
- package/hooks/use-conversation-page.js +4 -2
- package/hooks/use-conversation-page.js.map +1 -1
- package/hooks/use-conversation-preview.d.ts.map +1 -1
- package/hooks/use-conversation-preview.js +2 -1
- package/hooks/use-conversation-preview.js.map +1 -1
- package/package.json +5 -4
- package/packages/types/src/api/conversation.d.ts +21 -15
- package/packages/types/src/api/conversation.d.ts.map +1 -1
- package/packages/types/src/api/timeline-item.d.ts +9 -9
- package/packages/types/src/realtime-events.d.ts +19 -15
- package/packages/types/src/realtime-events.d.ts.map +1 -1
- package/packages/types/src/schemas.d.ts +6 -4
- package/packages/types/src/schemas.d.ts.map +1 -1
- package/primitives/multimodal-input.d.ts +2 -2
- package/primitives/multimodal-input.d.ts.map +1 -1
- package/primitives/timeline-item.d.ts.map +1 -1
- package/primitives/timeline-item.js +22 -7
- package/primitives/timeline-item.js.map +1 -1
- package/support/components/button.d.ts +1 -1
- package/support/components/conversation-resolved-feedback.d.ts +21 -0
- package/support/components/conversation-resolved-feedback.d.ts.map +1 -0
- package/support/components/conversation-resolved-feedback.js +59 -0
- package/support/components/conversation-resolved-feedback.js.map +1 -0
- package/support/components/conversation-timeline-utils.d.ts +5 -0
- package/support/components/conversation-timeline-utils.d.ts.map +1 -0
- package/support/components/conversation-timeline-utils.js +10 -0
- package/support/components/conversation-timeline-utils.js.map +1 -0
- package/support/components/conversation-timeline.d.ts.map +1 -1
- package/support/components/conversation-timeline.js +2 -1
- package/support/components/conversation-timeline.js.map +1 -1
- package/support/components/icons.d.ts +1 -1
- package/support/components/icons.d.ts.map +1 -1
- package/support/components/icons.js +6 -2
- package/support/components/icons.js.map +1 -1
- package/support/components/index.d.ts +2 -1
- package/support/components/index.js +2 -1
- package/support/pages/conversation.d.ts.map +1 -1
- package/support/pages/conversation.js +33 -7
- package/support/pages/conversation.js.map +1 -1
- package/support/text/locales/en.js +9 -0
- package/support/text/locales/en.js.map +1 -1
- package/support/text/locales/es.js +9 -0
- package/support/text/locales/es.js.map +1 -1
- package/support/text/locales/fr.js +9 -0
- package/support/text/locales/fr.js.map +1 -1
- package/support/text/locales/keys.d.ts +11 -0
- package/support/text/locales/keys.d.ts.map +1 -1
- package/support/text/locales/keys.js +3 -0
- package/support/text/locales/keys.js.map +1 -1
|
@@ -58,8 +58,8 @@ declare const realtimeSchema: {
|
|
|
58
58
|
aiAgentId: ZodNullable<ZodString>;
|
|
59
59
|
lastSeenAt: ZodString;
|
|
60
60
|
actorType: ZodEnum<{
|
|
61
|
-
user: "user";
|
|
62
61
|
visitor: "visitor";
|
|
62
|
+
user: "user";
|
|
63
63
|
ai_agent: "ai_agent";
|
|
64
64
|
}>;
|
|
65
65
|
actorId: ZodString;
|
|
@@ -117,10 +117,12 @@ declare const realtimeSchema: {
|
|
|
117
117
|
visitorId: ZodString;
|
|
118
118
|
websiteId: ZodString;
|
|
119
119
|
status: ZodDefault<ZodEnum<{
|
|
120
|
-
open: "open";
|
|
121
120
|
resolved: "resolved";
|
|
121
|
+
open: "open";
|
|
122
122
|
spam: "spam";
|
|
123
123
|
}>>;
|
|
124
|
+
visitorRating: ZodOptional<ZodNullable<ZodNumber>>;
|
|
125
|
+
visitorRatingAt: ZodOptional<ZodNullable<ZodString>>;
|
|
124
126
|
deletedAt: ZodDefault<ZodNullable<ZodString>>;
|
|
125
127
|
visitorLastSeenAt: ZodOptional<ZodNullable<ZodString>>;
|
|
126
128
|
lastTimelineItem: ZodOptional<ZodObject<{
|
|
@@ -142,15 +144,15 @@ declare const realtimeSchema: {
|
|
|
142
144
|
type: ZodLiteral<"text">;
|
|
143
145
|
text: ZodString;
|
|
144
146
|
state: ZodOptional<ZodEnum<{
|
|
145
|
-
done: "done";
|
|
146
147
|
streaming: "streaming";
|
|
148
|
+
done: "done";
|
|
147
149
|
}>>;
|
|
148
150
|
}, $strip>, ZodObject<{
|
|
149
151
|
type: ZodLiteral<"reasoning">;
|
|
150
152
|
text: ZodString;
|
|
151
153
|
state: ZodOptional<ZodEnum<{
|
|
152
|
-
done: "done";
|
|
153
154
|
streaming: "streaming";
|
|
155
|
+
done: "done";
|
|
154
156
|
}>>;
|
|
155
157
|
providerMetadata: ZodOptional<ZodObject<{
|
|
156
158
|
cossistant: ZodOptional<ZodObject<{
|
|
@@ -170,8 +172,8 @@ declare const realtimeSchema: {
|
|
|
170
172
|
output: ZodOptional<ZodUnknown>;
|
|
171
173
|
state: ZodEnum<{
|
|
172
174
|
error: "error";
|
|
173
|
-
result: "result";
|
|
174
175
|
partial: "partial";
|
|
176
|
+
result: "result";
|
|
175
177
|
}>;
|
|
176
178
|
errorText: ZodOptional<ZodString>;
|
|
177
179
|
providerMetadata: ZodOptional<ZodObject<{
|
|
@@ -272,8 +274,8 @@ declare const realtimeSchema: {
|
|
|
272
274
|
header: ZodObject<{
|
|
273
275
|
id: ZodString;
|
|
274
276
|
status: ZodEnum<{
|
|
275
|
-
open: "open";
|
|
276
277
|
resolved: "resolved";
|
|
278
|
+
open: "open";
|
|
277
279
|
spam: "spam";
|
|
278
280
|
}>;
|
|
279
281
|
priority: ZodEnum<{
|
|
@@ -302,6 +304,8 @@ declare const realtimeSchema: {
|
|
|
302
304
|
channel: ZodString;
|
|
303
305
|
title: ZodNullable<ZodString>;
|
|
304
306
|
resolutionTime: ZodNullable<ZodNumber>;
|
|
307
|
+
visitorRating: ZodNullable<ZodNumber>;
|
|
308
|
+
visitorRatingAt: ZodNullable<ZodString>;
|
|
305
309
|
startedAt: ZodNullable<ZodString>;
|
|
306
310
|
firstResponseAt: ZodNullable<ZodString>;
|
|
307
311
|
resolvedAt: ZodNullable<ZodString>;
|
|
@@ -337,15 +341,15 @@ declare const realtimeSchema: {
|
|
|
337
341
|
type: ZodLiteral<"text">;
|
|
338
342
|
text: ZodString;
|
|
339
343
|
state: ZodOptional<ZodEnum<{
|
|
340
|
-
done: "done";
|
|
341
344
|
streaming: "streaming";
|
|
345
|
+
done: "done";
|
|
342
346
|
}>>;
|
|
343
347
|
}, $strip>, ZodObject<{
|
|
344
348
|
type: ZodLiteral<"reasoning">;
|
|
345
349
|
text: ZodString;
|
|
346
350
|
state: ZodOptional<ZodEnum<{
|
|
347
|
-
done: "done";
|
|
348
351
|
streaming: "streaming";
|
|
352
|
+
done: "done";
|
|
349
353
|
}>>;
|
|
350
354
|
providerMetadata: ZodOptional<ZodObject<{
|
|
351
355
|
cossistant: ZodOptional<ZodObject<{
|
|
@@ -365,8 +369,8 @@ declare const realtimeSchema: {
|
|
|
365
369
|
output: ZodOptional<ZodUnknown>;
|
|
366
370
|
state: ZodEnum<{
|
|
367
371
|
error: "error";
|
|
368
|
-
result: "result";
|
|
369
372
|
partial: "partial";
|
|
373
|
+
result: "result";
|
|
370
374
|
}>;
|
|
371
375
|
errorText: ZodOptional<ZodString>;
|
|
372
376
|
providerMetadata: ZodOptional<ZodObject<{
|
|
@@ -482,15 +486,15 @@ declare const realtimeSchema: {
|
|
|
482
486
|
type: ZodLiteral<"text">;
|
|
483
487
|
text: ZodString;
|
|
484
488
|
state: ZodOptional<ZodEnum<{
|
|
485
|
-
done: "done";
|
|
486
489
|
streaming: "streaming";
|
|
490
|
+
done: "done";
|
|
487
491
|
}>>;
|
|
488
492
|
}, $strip>, ZodObject<{
|
|
489
493
|
type: ZodLiteral<"reasoning">;
|
|
490
494
|
text: ZodString;
|
|
491
495
|
state: ZodOptional<ZodEnum<{
|
|
492
|
-
done: "done";
|
|
493
496
|
streaming: "streaming";
|
|
497
|
+
done: "done";
|
|
494
498
|
}>>;
|
|
495
499
|
providerMetadata: ZodOptional<ZodObject<{
|
|
496
500
|
cossistant: ZodOptional<ZodObject<{
|
|
@@ -510,8 +514,8 @@ declare const realtimeSchema: {
|
|
|
510
514
|
output: ZodOptional<ZodUnknown>;
|
|
511
515
|
state: ZodEnum<{
|
|
512
516
|
error: "error";
|
|
513
|
-
result: "result";
|
|
514
517
|
partial: "partial";
|
|
518
|
+
result: "result";
|
|
515
519
|
}>;
|
|
516
520
|
errorText: ZodOptional<ZodString>;
|
|
517
521
|
providerMetadata: ZodOptional<ZodObject<{
|
|
@@ -777,8 +781,8 @@ declare const realtimeSchema: {
|
|
|
777
781
|
toolName: ZodString;
|
|
778
782
|
state: ZodEnum<{
|
|
779
783
|
error: "error";
|
|
780
|
-
result: "result";
|
|
781
784
|
partial: "partial";
|
|
785
|
+
result: "result";
|
|
782
786
|
}>;
|
|
783
787
|
}, $strip>>;
|
|
784
788
|
audience: ZodDefault<ZodEnum<{
|
|
@@ -795,8 +799,8 @@ declare const realtimeSchema: {
|
|
|
795
799
|
aiAgentId: ZodString;
|
|
796
800
|
workflowRunId: ZodString;
|
|
797
801
|
status: ZodEnum<{
|
|
798
|
-
error: "error";
|
|
799
802
|
success: "success";
|
|
803
|
+
error: "error";
|
|
800
804
|
skipped: "skipped";
|
|
801
805
|
cancelled: "cancelled";
|
|
802
806
|
}>;
|
|
@@ -965,8 +969,8 @@ declare const realtimeSchema: {
|
|
|
965
969
|
id: ZodString;
|
|
966
970
|
title: ZodNullable<ZodString>;
|
|
967
971
|
type: ZodEnum<{
|
|
968
|
-
article: "article";
|
|
969
972
|
url: "url";
|
|
973
|
+
article: "article";
|
|
970
974
|
faq: "faq";
|
|
971
975
|
}>;
|
|
972
976
|
}, $strip>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-events.d.ts","names":[],"sources":["../../../../../types/src/realtime-events.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAqBa
|
|
1
|
+
{"version":3,"file":"realtime-events.d.ts","names":[],"sources":["../../../../../types/src/realtime-events.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAqBa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8VD,iBAAA,gBAAiC;KAEjC,+BAA+B,qBAAqB,eACvD,gBAAgB;KAGb,wBAAwB;QAC7B;WACG,qBAAqB;;KAGnB,gBAAA,WACL,oBAAoB,cAAc,KACvC;KAEU,4BAA4B,qBACvC,qBAAqB"}
|
|
@@ -12,10 +12,12 @@ declare const conversationSchema: ZodObject<{
|
|
|
12
12
|
visitorId: ZodString;
|
|
13
13
|
websiteId: ZodString;
|
|
14
14
|
status: ZodDefault<ZodEnum<{
|
|
15
|
-
open: "open";
|
|
16
15
|
resolved: "resolved";
|
|
16
|
+
open: "open";
|
|
17
17
|
spam: "spam";
|
|
18
18
|
}>>;
|
|
19
|
+
visitorRating: ZodOptional<ZodNullable<ZodNumber>>;
|
|
20
|
+
visitorRatingAt: ZodOptional<ZodNullable<ZodString>>;
|
|
19
21
|
deletedAt: ZodDefault<ZodNullable<ZodString>>;
|
|
20
22
|
visitorLastSeenAt: ZodOptional<ZodNullable<ZodString>>;
|
|
21
23
|
lastTimelineItem: ZodOptional<ZodObject<{
|
|
@@ -37,15 +39,15 @@ declare const conversationSchema: ZodObject<{
|
|
|
37
39
|
type: ZodLiteral<"text">;
|
|
38
40
|
text: ZodString;
|
|
39
41
|
state: ZodOptional<ZodEnum<{
|
|
40
|
-
done: "done";
|
|
41
42
|
streaming: "streaming";
|
|
43
|
+
done: "done";
|
|
42
44
|
}>>;
|
|
43
45
|
}, $strip>, ZodObject<{
|
|
44
46
|
type: ZodLiteral<"reasoning">;
|
|
45
47
|
text: ZodString;
|
|
46
48
|
state: ZodOptional<ZodEnum<{
|
|
47
|
-
done: "done";
|
|
48
49
|
streaming: "streaming";
|
|
50
|
+
done: "done";
|
|
49
51
|
}>>;
|
|
50
52
|
providerMetadata: ZodOptional<ZodObject<{
|
|
51
53
|
cossistant: ZodOptional<ZodObject<{
|
|
@@ -65,8 +67,8 @@ declare const conversationSchema: ZodObject<{
|
|
|
65
67
|
output: ZodOptional<ZodUnknown>;
|
|
66
68
|
state: ZodEnum<{
|
|
67
69
|
error: "error";
|
|
68
|
-
result: "result";
|
|
69
70
|
partial: "partial";
|
|
71
|
+
result: "result";
|
|
70
72
|
}>;
|
|
71
73
|
errorText: ZodOptional<ZodString>;
|
|
72
74
|
providerMetadata: ZodOptional<ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","names":[],"sources":["../../../../../types/src/schemas.ts"],"sourcesContent":[],"mappings":";;;;;;cAkBa,oBAAkB
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","names":[],"sources":["../../../../../types/src/schemas.ts"],"sourcesContent":[],"mappings":";;;;;;cAkBa,oBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqBnB,YAAA,GAAe,cAAe;cAE7B,wBAAsB;;;;;;;;;;CAvBJ,QAAA,CAAA;AAAA,KAmCnB,gBAAA,GAAmB,MAnCA,CAAA,OAmCe,sBAnCf,CAAA"}
|
|
@@ -16,7 +16,7 @@ type MultimodalInputProps = Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElem
|
|
|
16
16
|
* clipboard uploads and auto-resizing while remaining composable via
|
|
17
17
|
* `asChild`.
|
|
18
18
|
*/
|
|
19
|
-
declare const MultimodalInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "
|
|
19
|
+
declare const MultimodalInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange" | "value"> & {
|
|
20
20
|
value: string;
|
|
21
21
|
onChange: (value: string) => void;
|
|
22
22
|
onSubmit?: () => void;
|
|
@@ -38,7 +38,7 @@ declare const FileInput: React$1.ForwardRefExoticComponent<React$1.InputHTMLAttr
|
|
|
38
38
|
onFileSelect?: (files: File[]) => void;
|
|
39
39
|
asChild?: boolean;
|
|
40
40
|
} & React$1.RefAttributes<HTMLInputElement>>;
|
|
41
|
-
declare const SupportInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "
|
|
41
|
+
declare const SupportInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange" | "value"> & {
|
|
42
42
|
value: string;
|
|
43
43
|
onChange: (value: string) => void;
|
|
44
44
|
onSubmit?: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../src/primitives/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAGY,oBAAA,GAAuB,KAClC,OAAA,CAAM,uBAAuB;;EADlB,QAAA,EAAA,CAAA,KAAA,EAAA,MAAoB,EAAA,GAAA,IAAA;EACF,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAA7B,YAAM,CAAA,EAAA,CAAA,KAAA,EAMiB,IANjB,EAAA,EAAA,GAAA,IAAA;EAD4B,OAAA,CAAA,EAAA,OAAA;EAOX,SAAA,CAAA,EAAA,MAAA;EAGf,KAAA,CAAA,EAAA,KAAA,GAAA,IAAA;EAAK,QAAA,CAAA,EAAA,OAAA;AASd,CAAA;;;;;;cAAa,iBAAe,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,uBAAA;;EAAA,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EA4GhB,YAAA,CAAA,EAAA,CAAA,KAAc,EAxHF,IAwHE,EAAA,EAAA,GAAA,IAAA;EAA6B,OAAA,CAAA,EAAA,OAAA;EAA1B,SAAM,CAAA,EAAA,MAAA;EACX,KAAA,CAAA,EAtHf,KAsHe,GAAA,IAAA;EAAI,QAAA,CAAA,EAAA,OAAA;AAQ5B,CAAA,wBAkCI,oBAAA,CAAA,CAAA;AAlCkB,KATV,cAAA,GAAiB,OAAA,CAAM,mBASb,CATiC,gBASjC,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EARE,IAQF,EAAA,EAAA,GAAA,IAAA;EARE,OAAA,CAAA,EAAA,OAAA;;;;;AA6CxB;AAAyB,cArCZ,SAqCY,EArCH,OAAA,CAAA,yBAqCG,CArCH,OAAA,CAAA,mBAqCG,CArCH,gBAqCG,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EA7CD,IA6CC,EAAA,EAAA,GAAA,IAAA;EAAA,OAAA,CAAA,EAAA,OAAA;CAtKD,wBAAA,iBAAA,CAAA,CAAA;AAGf,cAmKI,YAnKJ,EAmKgB,OAAA,CAAA,yBAnKhB,CAmKgB,IAnKhB,CAmKgB,OAAA,CAAA,sBAnKhB,CAmKgB,mBAnKhB,CAAA,EAAA,
|
|
1
|
+
{"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../src/primitives/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAGY,oBAAA,GAAuB,KAClC,OAAA,CAAM,uBAAuB;;EADlB,QAAA,EAAA,CAAA,KAAA,EAAA,MAAoB,EAAA,GAAA,IAAA;EACF,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAA7B,YAAM,CAAA,EAAA,CAAA,KAAA,EAMiB,IANjB,EAAA,EAAA,GAAA,IAAA;EAD4B,OAAA,CAAA,EAAA,OAAA;EAOX,SAAA,CAAA,EAAA,MAAA;EAGf,KAAA,CAAA,EAAA,KAAA,GAAA,IAAA;EAAK,QAAA,CAAA,EAAA,OAAA;AASd,CAAA;;;;;;cAAa,iBAAe,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,uBAAA;;EAAA,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EA4GhB,YAAA,CAAA,EAAA,CAAA,KAAc,EAxHF,IAwHE,EAAA,EAAA,GAAA,IAAA;EAA6B,OAAA,CAAA,EAAA,OAAA;EAA1B,SAAM,CAAA,EAAA,MAAA;EACX,KAAA,CAAA,EAtHf,KAsHe,GAAA,IAAA;EAAI,QAAA,CAAA,EAAA,OAAA;AAQ5B,CAAA,wBAkCI,oBAAA,CAAA,CAAA;AAlCkB,KATV,cAAA,GAAiB,OAAA,CAAM,mBASb,CATiC,gBASjC,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EARE,IAQF,EAAA,EAAA,GAAA,IAAA;EARE,OAAA,CAAA,EAAA,OAAA;;;;;AA6CxB;AAAyB,cArCZ,SAqCY,EArCH,OAAA,CAAA,yBAqCG,CArCH,OAAA,CAAA,mBAqCG,CArCH,gBAqCG,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EA7CD,IA6CC,EAAA,EAAA,GAAA,IAAA;EAAA,OAAA,CAAA,EAAA,OAAA;CAtKD,wBAAA,iBAAA,CAAA,CAAA;AAGf,cAmKI,YAnKJ,EAmKgB,OAAA,CAAA,yBAnKhB,CAmKgB,IAnKhB,CAmKgB,OAAA,CAAA,sBAnKhB,CAmKgB,mBAnKhB,CAAA,EAAA,UAAA,GAAA,OAAA,CAAA,GAAA;;;EAmKgB,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EAtKD,IAsKC,EAAA,EAAA,GAAA,IAAA;;;UAnKhB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-item.d.ts","names":[],"sources":["../../src/primitives/timeline-item.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAUA;AAUA;AACsB,KAXV,uBAAA,GAWU;EAArB,SAAM,EAAA,OAAA;EADyB,IAAA,EAAA,OAAA;EAK5B,OAAM,EAAA,OAAA;EACG,SAAA,EAZD,IAYC;EAA4B,IAAA,EAAM,MAAA,GAAA,IAAA;EAGxC,UAAA,EAAA,SAAA,GAAA,IAAA,GAAA,OAAA;EAAgB,QAAA,EAAA,SAAA,GAAA,OAAA,GAAA,gBAAA;AAQvB,CAAA;AAAyB,KAjBb,iBAAA,GAAoB,IAiBP,CAhBxB,OAAA,CAAM,cAgBkB,CAhBH,cAgBG,CAAA,EAAA,UAAA,CAAA,GAAA;EAAA,QAAA,CAAA,EAZrB,OAAA,CAAM,SAYe,GAAA,CAAA,CAAA,KAAA,EAXZ,uBAWY,EAAA,GAXgB,OAAA,CAAM,SAWtB,CAAA;EAAA,OAAA,CAAA,EAAA,OAAA;EAZrB,SAAM,CAAA,EAAA,MAAA;EACG,IAAA,EAGN,cAHM;CAA4B;;;;;;
|
|
1
|
+
{"version":3,"file":"timeline-item.d.ts","names":[],"sources":["../../src/primitives/timeline-item.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAUA;AAUA;AACsB,KAXV,uBAAA,GAWU;EAArB,SAAM,EAAA,OAAA;EADyB,IAAA,EAAA,OAAA;EAK5B,OAAM,EAAA,OAAA;EACG,SAAA,EAZD,IAYC;EAA4B,IAAA,EAAM,MAAA,GAAA,IAAA;EAGxC,UAAA,EAAA,SAAA,GAAA,IAAA,GAAA,OAAA;EAAgB,QAAA,EAAA,SAAA,GAAA,OAAA,GAAA,gBAAA;AAQvB,CAAA;AAAyB,KAjBb,iBAAA,GAAoB,IAiBP,CAhBxB,OAAA,CAAM,cAgBkB,CAhBH,cAgBG,CAAA,EAAA,UAAA,CAAA,GAAA;EAAA,QAAA,CAAA,EAZrB,OAAA,CAAM,SAYe,GAAA,CAAA,CAAA,KAAA,EAXZ,uBAWY,EAAA,GAXgB,OAAA,CAAM,SAWtB,CAAA;EAAA,OAAA,CAAA,EAAA,OAAA;EAZrB,SAAM,CAAA,EAAA,MAAA;EACG,IAAA,EAGN,cAHM;CAA4B;;;;;;AAoM7B,cAzLC,YAyLuB,EAzLX,OAAA,CAAA,yBAyLW,CAzLX,IAyLW,CAzLX,OAAA,CAAA,cAyLW,CAzLX,cAyLW,CAAA,EAAA,UAAA,CAAA,GAAA;EACd,QAAA,CAAA,EAtMlB,OAAA,CAAM,SAsMY,GAAA,CAAA,CAAA,KAAA,EArMT,uBAqMS,EAAA,GArMmB,OAAA,CAAM,SAqMzB,CAAA;EAArB,OAAM,CAAA,EAAA,OAAA;EADgC,SAAA,CAAA,EAAA,MAAA;EAI3B,IAAA,EArML,cAqMW;CAAkC,wBAAM,eAAA,CAAA,CAAA;AAAS,KAJvD,wBAAA,GAA2B,IAI4B,CAHlE,OAAA,CAAM,cAG4D,CAH7C,cAG6C,CAAA,EAAA,UAAA,CAAA,GAAA;EAYtD,QAAA,CAAA,EAZD,OAAA,CAAM,SA6Dd,GAAA,CAAA,CAAA,OAAA,EAAA,MAAA,EAAA,GA7DgD,OAAA,CAAM,SA6DtD,CAAA;EAjD4B,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA;EAAA,IAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAZpB,cAAM,CAAA,EAAA,OAAA;CAAkC;;;;;AA+DpD;AACsB,cApDT,mBAoDS,EApDU,OAAA,CAAA,yBAoDV,CApDU,IAoDV,CApDU,OAAA,CAAA,cAoDV,CApDU,cAoDV,CAAA,EAAA,UAAA,CAAA,GAAA;EAArB,QAAM,CAAA,EAhEK,OAAA,CAAM,SAgEX,GAAA,CAAA,CAAA,OAAA,EAAA,MAAA,EAAA,GAhE6C,OAAA,CAAM,SAgEnD,CAAA;EADkC,OAAA,CAAA,EAAA,OAAA;EAI7B,SAAM,CAAA,EAAA,MAAA;EAAyB,IAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAAS,cAAM,CAAA,EAAA,OAAA;CAG9C,wBAAA,eAAA,CAAA,CAAA;AACK,KARL,0BAAA,GAA6B,IAQxB,CAPhB,OAAA,CAAM,cAOU,CAPK,eAOL,CAAA,EAAA,UAAA,CAAA,GAAA;EAAI,QAAA,CAAA,EAJT,OAAA,CAAM,SAIG,GAAA,CAAA,CAAA,SAAA,EAJsB,IAItB,EAAA,GAJ+B,OAAA,CAAM,SAIrC,CAAA;EAOR,OAAA,CAAA,EAAA,OAAA;EAAqB,SAAA,CAAA,EAAA,MAAA;EAAA,SAAA,EARtB,IAQsB;EAAA,MAAA,CAAA,EAAA,CAAA,IAAA,EAPjB,IAOiB,EAAA,GAAA,MAAA;CAXtB;;;;;cAWC,uBAAqB,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,eAAA;aAXtB,OAAA,CAAM,yBAAyB,SAAS,OAAA,CAAM;EAWxB,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA;aARtB;kBACK"}
|
|
@@ -97,15 +97,30 @@ const MemoizedMarkdownBlock = React$1.memo(({ content }) => {
|
|
|
97
97
|
className: "italic",
|
|
98
98
|
children
|
|
99
99
|
}),
|
|
100
|
-
a: ({ href, children }) =>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
a: ({ href, children, node }) => {
|
|
101
|
+
const rawHref = href || node?.properties?.href || "";
|
|
102
|
+
if (rawHref.startsWith("mention:")) {
|
|
103
|
+
const parts = rawHref.split(":");
|
|
104
|
+
const mentionType = parts[1];
|
|
105
|
+
const mentionId = parts.slice(2).join(":");
|
|
106
|
+
return /* @__PURE__ */ jsx("span", {
|
|
107
|
+
className: "rounded bg-co-orange/15 font-medium text-co-orange",
|
|
108
|
+
"data-mention-id": mentionId,
|
|
109
|
+
"data-mention-type": mentionType,
|
|
110
|
+
children
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return /* @__PURE__ */ jsx("a", {
|
|
114
|
+
className: "underline hover:opacity-80",
|
|
115
|
+
href,
|
|
116
|
+
rel: "noopener noreferrer",
|
|
117
|
+
target: "_blank",
|
|
118
|
+
children
|
|
119
|
+
});
|
|
120
|
+
}
|
|
107
121
|
},
|
|
108
122
|
remarkPlugins: [remarkBreaks],
|
|
123
|
+
urlTransform: (url) => url,
|
|
109
124
|
children: content
|
|
110
125
|
});
|
|
111
126
|
}, (prevProps, nextProps) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-item.js","names":["React","renderProps: TimelineItemRenderProps"],"sources":["../../src/primitives/timeline-item.tsx"],"sourcesContent":["import type { TimelineItem as TimelineItemType } from \"@cossistant/types/api/timeline-item\";\nimport * as React from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkBreaks from \"remark-breaks\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\n/**\n * Metadata describing the origin of a timeline item and pre-parsed content that can\n * be consumed by render-prop children.\n */\nexport type TimelineItemRenderProps = {\n\tisVisitor: boolean;\n\tisAI: boolean;\n\tisHuman: boolean;\n\ttimestamp: Date;\n\ttext: string | null;\n\tsenderType: \"visitor\" | \"ai\" | \"human\";\n\titemType: \"message\" | \"event\" | \"identification\";\n};\n\nexport type TimelineItemProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: TimelineItemRenderProps) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\titem: TimelineItemType;\n};\n\n/**\n * Generic timeline item wrapper that adds accessibility attributes and resolves the\n * sender type into convenient render props for custom layouts. Works with\n * both MESSAGE and EVENT timeline item types.\n */\nexport const TimelineItem = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, TimelineItemProps>(\n\t\t({ children, className, asChild = false, item, ...props }, ref) => {\n\t\t\t// Determine sender type from timeline item properties\n\t\t\tconst isVisitor = item.visitorId !== null;\n\t\t\tconst isAI = item.aiAgentId !== null;\n\t\t\tconst isHuman = item.userId !== null && !isVisitor;\n\n\t\t\tconst senderType = isVisitor ? \"visitor\" : isAI ? \"ai\" : \"human\";\n\n\t\t\tconst renderProps: TimelineItemRenderProps = {\n\t\t\t\tisVisitor,\n\t\t\t\tisAI,\n\t\t\t\tisHuman,\n\t\t\t\ttimestamp: new Date(item.createdAt),\n\t\t\t\ttext: item.text,\n\t\t\t\tsenderType,\n\t\t\t\titemType: item.type,\n\t\t\t};\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\n\n\t\t\tconst itemTypeLabel = (() => {\n\t\t\t\tif (item.type === \"event\") {\n\t\t\t\t\treturn \"Event\";\n\t\t\t\t}\n\t\t\t\tif (item.type === \"identification\") {\n\t\t\t\t\treturn \"Identification\";\n\t\t\t\t}\n\t\t\t\tif (isVisitor) {\n\t\t\t\t\treturn \"visitor\";\n\t\t\t\t}\n\t\t\t\tif (isAI) {\n\t\t\t\t\treturn \"AI assistant\";\n\t\t\t\t}\n\t\t\t\treturn \"human agent\";\n\t\t\t})();\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\trole: \"article\",\n\t\t\t\t\t\t\"aria-label\": `${item.type === \"message\" ? \"Message\" : \"Event\"} from ${itemTypeLabel}`,\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItem\";\n\treturn Component;\n})();\n\nconst MemoizedMarkdownBlock = React.memo(\n\t({ content }: { content: string }) => {\n\t\treturn (\n\t\t\t<ReactMarkdown\n\t\t\t\tcomponents={{\n\t\t\t\t\t// Render paragraphs as block elements to preserve multiline spacing\n\t\t\t\t\tp: ({ children }) => {\n\t\t\t\t\t\t// Skip empty paragraphs (caused by consecutive blank lines in markdown)\n\t\t\t\t\t\tconst isEmpty =\n\t\t\t\t\t\t\tchildren === undefined ||\n\t\t\t\t\t\t\tchildren === null ||\n\t\t\t\t\t\t\tchildren === \"\" ||\n\t\t\t\t\t\t\t(Array.isArray(children) &&\n\t\t\t\t\t\t\t\tchildren.every((c) => c === \"\\n\" || c === \"\" || c == null));\n\t\t\t\t\t\tif (isEmpty) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn <span className=\"mt-1 block first:mt-0\">{children}</span>;\n\t\t\t\t\t},\n\t\t\t\t\t// Ensure proper line break handling\n\t\t\t\t\tbr: () => <br />,\n\t\t\t\t\t// Handle code blocks properly\n\t\t\t\t\tcode: ({ children, ...props }) => {\n\t\t\t\t\t\t// Check if it's inline code by looking at the parent element\n\t\t\t\t\t\tconst isInline = !(\n\t\t\t\t\t\t\t\"className\" in props &&\n\t\t\t\t\t\t\ttypeof props.className === \"string\" &&\n\t\t\t\t\t\t\tprops.className.includes(\"language-\")\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn isInline ? (\n\t\t\t\t\t\t\t<code className=\"rounded bg-co-background-300 px-1 py-0.5 text-xs\">\n\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<pre className=\"overflow-x-auto rounded bg-co-background-300 p-2\">\n\t\t\t\t\t\t\t\t<code className=\"text-xs\">{children}</code>\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\t// Handle strong/bold text\n\t\t\t\t\tstrong: ({ children }) => (\n\t\t\t\t\t\t<strong className=\"font-semibold\">{children}</strong>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle ordered lists\n\t\t\t\t\tol: ({ children }) => (\n\t\t\t\t\t\t<ol className=\"my-0 list-decimal pl-6\">{children}</ol>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle unordered lists\n\t\t\t\t\tul: ({ children }) => (\n\t\t\t\t\t\t<ul className=\"my-0 list-disc pl-6\">{children}</ul>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle list items\n\t\t\t\t\tli: ({ children }) => (\n\t\t\t\t\t\t<li className=\"[&>span.block]:mt-0 [&>span.block]:inline\">\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle blockquotes\n\t\t\t\t\tblockquote: ({ children }) => (\n\t\t\t\t\t\t<blockquote className=\"my-1 border-co-border border-l-2 pl-3 italic opacity-80\">\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</blockquote>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle emphasis\n\t\t\t\t\tem: ({ children }) => <em className=\"italic\">{children}</em>,\n\t\t\t\t\t// Handle links\n\t\t\t\t\ta: ({ href, children }) => (\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclassName=\"underline hover:opacity-80\"\n\t\t\t\t\t\t\thref={href}\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t),\n\t\t\t\t}}\n\t\t\t\tremarkPlugins={[remarkBreaks]}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t</ReactMarkdown>\n\t\t);\n\t},\n\t(prevProps, nextProps) => {\n\t\tif (prevProps.content !== nextProps.content) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n);\n\nMemoizedMarkdownBlock.displayName = \"MemoizedMarkdownBlock\";\n\nexport type TimelineItemContentProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode | ((content: string) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\ttext?: string | null;\n\trenderMarkdown?: boolean;\n};\n\n/**\n * Renders the content of a timeline item, optionally piping Markdown content through a\n * memoised renderer or handing the raw text to a render prop for custom\n * formatting.\n */\nexport const TimelineItemContent = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, TimelineItemContentProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\ttext = \"\",\n\t\t\t\trenderMarkdown = true,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst content = React.useMemo(() => {\n\t\t\t\tconst textContent = text ?? \"\";\n\t\t\t\tif (typeof children === \"function\") {\n\t\t\t\t\treturn children(textContent);\n\t\t\t\t}\n\t\t\t\tif (children) {\n\t\t\t\t\treturn children;\n\t\t\t\t}\n\t\t\t\tif (renderMarkdown && textContent) {\n\t\t\t\t\treturn <MemoizedMarkdownBlock content={textContent} />;\n\t\t\t\t}\n\t\t\t\treturn textContent;\n\t\t\t}, [children, text, renderMarkdown]);\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t...props.style,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItemContent\";\n\treturn Component;\n})();\n\nexport type TimelineItemTimestampProps = Omit<\n\tReact.HTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode | ((timestamp: Date) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\ttimestamp: Date;\n\tformat?: (date: Date) => string;\n};\n\n/**\n * Timestamp helper that renders a formatted date or allows callers to supply a\n * render prop for custom time displays while preserving semantic markup.\n */\nexport const TimelineItemTimestamp = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLSpanElement,\n\t\tTimelineItemTimestampProps\n\t>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\ttimestamp,\n\t\t\t\tformat = (date) =>\n\t\t\t\t\tdate.toLocaleTimeString([], {\n\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t}),\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\"\n\t\t\t\t\t? children(timestamp)\n\t\t\t\t\t: children || format(timestamp);\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"span\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItemTimestamp\";\n\treturn Component;\n})();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"timeline-item.js","names":["React","renderProps: TimelineItemRenderProps"],"sources":["../../src/primitives/timeline-item.tsx"],"sourcesContent":["import type { TimelineItem as TimelineItemType } from \"@cossistant/types/api/timeline-item\";\nimport * as React from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkBreaks from \"remark-breaks\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\n/**\n * Metadata describing the origin of a timeline item and pre-parsed content that can\n * be consumed by render-prop children.\n */\nexport type TimelineItemRenderProps = {\n\tisVisitor: boolean;\n\tisAI: boolean;\n\tisHuman: boolean;\n\ttimestamp: Date;\n\ttext: string | null;\n\tsenderType: \"visitor\" | \"ai\" | \"human\";\n\titemType: \"message\" | \"event\" | \"identification\";\n};\n\nexport type TimelineItemProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: TimelineItemRenderProps) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\titem: TimelineItemType;\n};\n\n/**\n * Generic timeline item wrapper that adds accessibility attributes and resolves the\n * sender type into convenient render props for custom layouts. Works with\n * both MESSAGE and EVENT timeline item types.\n */\nexport const TimelineItem = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, TimelineItemProps>(\n\t\t({ children, className, asChild = false, item, ...props }, ref) => {\n\t\t\t// Determine sender type from timeline item properties\n\t\t\tconst isVisitor = item.visitorId !== null;\n\t\t\tconst isAI = item.aiAgentId !== null;\n\t\t\tconst isHuman = item.userId !== null && !isVisitor;\n\n\t\t\tconst senderType = isVisitor ? \"visitor\" : isAI ? \"ai\" : \"human\";\n\n\t\t\tconst renderProps: TimelineItemRenderProps = {\n\t\t\t\tisVisitor,\n\t\t\t\tisAI,\n\t\t\t\tisHuman,\n\t\t\t\ttimestamp: new Date(item.createdAt),\n\t\t\t\ttext: item.text,\n\t\t\t\tsenderType,\n\t\t\t\titemType: item.type,\n\t\t\t};\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\n\n\t\t\tconst itemTypeLabel = (() => {\n\t\t\t\tif (item.type === \"event\") {\n\t\t\t\t\treturn \"Event\";\n\t\t\t\t}\n\t\t\t\tif (item.type === \"identification\") {\n\t\t\t\t\treturn \"Identification\";\n\t\t\t\t}\n\t\t\t\tif (isVisitor) {\n\t\t\t\t\treturn \"visitor\";\n\t\t\t\t}\n\t\t\t\tif (isAI) {\n\t\t\t\t\treturn \"AI assistant\";\n\t\t\t\t}\n\t\t\t\treturn \"human agent\";\n\t\t\t})();\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\trole: \"article\",\n\t\t\t\t\t\t\"aria-label\": `${item.type === \"message\" ? \"Message\" : \"Event\"} from ${itemTypeLabel}`,\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItem\";\n\treturn Component;\n})();\n\nconst MemoizedMarkdownBlock = React.memo(\n\t({ content }: { content: string }) => {\n\t\treturn (\n\t\t\t<ReactMarkdown\n\t\t\t\t// Allow mention: protocol URLs (not sanitized by default)\n\t\t\t\tcomponents={{\n\t\t\t\t\t// Render paragraphs as block elements to preserve multiline spacing\n\t\t\t\t\tp: ({ children }) => {\n\t\t\t\t\t\t// Skip empty paragraphs (caused by consecutive blank lines in markdown)\n\t\t\t\t\t\tconst isEmpty =\n\t\t\t\t\t\t\tchildren === undefined ||\n\t\t\t\t\t\t\tchildren === null ||\n\t\t\t\t\t\t\tchildren === \"\" ||\n\t\t\t\t\t\t\t(Array.isArray(children) &&\n\t\t\t\t\t\t\t\tchildren.every((c) => c === \"\\n\" || c === \"\" || c == null));\n\t\t\t\t\t\tif (isEmpty) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn <span className=\"mt-1 block first:mt-0\">{children}</span>;\n\t\t\t\t\t},\n\t\t\t\t\t// Ensure proper line break handling\n\t\t\t\t\tbr: () => <br />,\n\t\t\t\t\t// Handle code blocks properly\n\t\t\t\t\tcode: ({ children, ...props }) => {\n\t\t\t\t\t\t// Check if it's inline code by looking at the parent element\n\t\t\t\t\t\tconst isInline = !(\n\t\t\t\t\t\t\t\"className\" in props &&\n\t\t\t\t\t\t\ttypeof props.className === \"string\" &&\n\t\t\t\t\t\t\tprops.className.includes(\"language-\")\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn isInline ? (\n\t\t\t\t\t\t\t<code className=\"rounded bg-co-background-300 px-1 py-0.5 text-xs\">\n\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<pre className=\"overflow-x-auto rounded bg-co-background-300 p-2\">\n\t\t\t\t\t\t\t\t<code className=\"text-xs\">{children}</code>\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\t// Handle strong/bold text\n\t\t\t\t\tstrong: ({ children }) => (\n\t\t\t\t\t\t<strong className=\"font-semibold\">{children}</strong>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle ordered lists\n\t\t\t\t\tol: ({ children }) => (\n\t\t\t\t\t\t<ol className=\"my-0 list-decimal pl-6\">{children}</ol>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle unordered lists\n\t\t\t\t\tul: ({ children }) => (\n\t\t\t\t\t\t<ul className=\"my-0 list-disc pl-6\">{children}</ul>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle list items\n\t\t\t\t\tli: ({ children }) => (\n\t\t\t\t\t\t<li className=\"[&>span.block]:mt-0 [&>span.block]:inline\">\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle blockquotes\n\t\t\t\t\tblockquote: ({ children }) => (\n\t\t\t\t\t\t<blockquote className=\"my-1 border-co-border border-l-2 pl-3 italic opacity-80\">\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</blockquote>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle emphasis\n\t\t\t\t\tem: ({ children }) => <em className=\"italic\">{children}</em>,\n\t\t\t\t\t// Handle links - with special handling for mentions\n\t\t\t\t\t// Mention format: [@Name](mention:type:id) - the @ is inside the link\n\t\t\t\t\ta: ({ href, children, node }) => {\n\t\t\t\t\t\t// Get the raw href from the AST node if available (react-markdown may sanitize href)\n\t\t\t\t\t\tconst rawHref =\n\t\t\t\t\t\t\thref || (node?.properties?.href as string | undefined) || \"\";\n\n\t\t\t\t\t\t// Check if this is a mention link: mention:type:id\n\t\t\t\t\t\tif (rawHref.startsWith(\"mention:\")) {\n\t\t\t\t\t\t\t// Parse mention:type:id format\n\t\t\t\t\t\t\tconst parts = rawHref.split(\":\");\n\t\t\t\t\t\t\tconst mentionType = parts[1]; // visitor, ai-agent, human-agent\n\t\t\t\t\t\t\tconst mentionId = parts.slice(2).join(\":\"); // id (may contain colons)\n\n\t\t\t\t\t\t\t// Render as styled orange pill (same design as input)\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclassName=\"rounded bg-co-orange/15 font-medium text-co-orange\"\n\t\t\t\t\t\t\t\t\tdata-mention-id={mentionId}\n\t\t\t\t\t\t\t\t\tdata-mention-type={mentionType}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Regular link\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\tclassName=\"underline hover:opacity-80\"\n\t\t\t\t\t\t\t\thref={href}\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t}}\n\t\t\t\tremarkPlugins={[remarkBreaks]}\n\t\t\t\turlTransform={(url) => url}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t</ReactMarkdown>\n\t\t);\n\t},\n\t(prevProps, nextProps) => {\n\t\tif (prevProps.content !== nextProps.content) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n);\n\nMemoizedMarkdownBlock.displayName = \"MemoizedMarkdownBlock\";\n\nexport type TimelineItemContentProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode | ((content: string) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\ttext?: string | null;\n\trenderMarkdown?: boolean;\n};\n\n/**\n * Renders the content of a timeline item, optionally piping Markdown content through a\n * memoised renderer or handing the raw text to a render prop for custom\n * formatting.\n */\nexport const TimelineItemContent = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, TimelineItemContentProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\ttext = \"\",\n\t\t\t\trenderMarkdown = true,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst content = React.useMemo(() => {\n\t\t\t\tconst textContent = text ?? \"\";\n\t\t\t\tif (typeof children === \"function\") {\n\t\t\t\t\treturn children(textContent);\n\t\t\t\t}\n\t\t\t\tif (children) {\n\t\t\t\t\treturn children;\n\t\t\t\t}\n\t\t\t\tif (renderMarkdown && textContent) {\n\t\t\t\t\treturn <MemoizedMarkdownBlock content={textContent} />;\n\t\t\t\t}\n\t\t\t\treturn textContent;\n\t\t\t}, [children, text, renderMarkdown]);\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t...props.style,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItemContent\";\n\treturn Component;\n})();\n\nexport type TimelineItemTimestampProps = Omit<\n\tReact.HTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode | ((timestamp: Date) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\ttimestamp: Date;\n\tformat?: (date: Date) => string;\n};\n\n/**\n * Timestamp helper that renders a formatted date or allows callers to supply a\n * render prop for custom time displays while preserving semantic markup.\n */\nexport const TimelineItemTimestamp = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLSpanElement,\n\t\tTimelineItemTimestampProps\n\t>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\ttimestamp,\n\t\t\t\tformat = (date) =>\n\t\t\t\t\tdate.toLocaleTimeString([], {\n\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t}),\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\"\n\t\t\t\t\t? children(timestamp)\n\t\t\t\t\t: children || format(timestamp);\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"span\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItemTimestamp\";\n\treturn Component;\n})();\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import * as class_variance_authority_dist_types0 from "class-variance-authority/
|
|
|
4
4
|
|
|
5
5
|
//#region src/support/components/button.d.ts
|
|
6
6
|
declare const coButtonVariants: (props?: ({
|
|
7
|
-
variant?: "
|
|
7
|
+
variant?: "default" | "tab" | "secondary" | "ghost" | "outline" | "tab-selected" | null | undefined;
|
|
8
8
|
size?: "default" | "large" | "icon" | null | undefined;
|
|
9
9
|
} & class_variance_authority_dist_types0.ClassProp) | undefined) => string;
|
|
10
10
|
type CossistantButtonProps = React$1.ComponentProps<"button"> & {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConversationStatus } from "@cossistant/types";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/support/components/conversation-resolved-feedback.d.ts
|
|
5
|
+
type ConversationResolvedFeedbackProps = {
|
|
6
|
+
status: ConversationStatus | null;
|
|
7
|
+
rating: number | null;
|
|
8
|
+
onRate?: (rating: number) => void;
|
|
9
|
+
isSubmitting?: boolean;
|
|
10
|
+
className?: string;
|
|
11
|
+
};
|
|
12
|
+
declare function ConversationResolvedFeedback({
|
|
13
|
+
status,
|
|
14
|
+
rating,
|
|
15
|
+
onRate,
|
|
16
|
+
isSubmitting,
|
|
17
|
+
className
|
|
18
|
+
}: ConversationResolvedFeedbackProps): react_jsx_runtime0.JSX.Element;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { ConversationResolvedFeedback };
|
|
21
|
+
//# sourceMappingURL=conversation-resolved-feedback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-resolved-feedback.d.ts","names":[],"sources":["../../../src/support/components/conversation-resolved-feedback.tsx"],"sourcesContent":[],"mappings":";;;;KAKK,iCAAA;UACI;;EADJ,MAAA,CAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAUW,YAAA,CAAA,EAAA,OAAA;EACf,SAAA,CAAA,EAAA,MAAA;CACA;AACA,iBAHe,4BAAA,CAGf;EAAA,MAAA;EAAA,MAAA;EAAA,MAAA;EAAA,YAAA;EAAA;AAAA,CAAA,EAGE,iCAHF,CAAA,EAGmC,kBAAA,CAAA,GAAA,CAAA,OAHnC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { cn } from "../utils/index.js";
|
|
2
|
+
import icons_default from "./icons.js";
|
|
3
|
+
import { Text, useSupportText } from "../text/index.js";
|
|
4
|
+
import { ConversationStatus } from "@cossistant/types";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
|
|
7
|
+
//#region src/support/components/conversation-resolved-feedback.tsx
|
|
8
|
+
const STAR_COUNT = 5;
|
|
9
|
+
function ConversationResolvedFeedback({ status, rating, onRate, isSubmitting = false, className }) {
|
|
10
|
+
const text = useSupportText();
|
|
11
|
+
const isResolved = status === ConversationStatus.RESOLVED;
|
|
12
|
+
const isRated = rating != null;
|
|
13
|
+
const isInteractive = Boolean(onRate) && !isSubmitting && !isRated;
|
|
14
|
+
if (!isResolved) return /* @__PURE__ */ jsx("div", {
|
|
15
|
+
className: cn("m-4 flex items-center justify-center text-balance px-4 pb-6 text-center font-medium text-co-muted-foreground text-sm", className),
|
|
16
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
17
|
+
as: "p",
|
|
18
|
+
textKey: "component.conversationPage.closedMessage"
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
22
|
+
className: cn("m-4 rounded-md border border-co-border/60 bg-co-background-100 px-4 py-3 text-center text-sm shadow-sm", className),
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsx(Text, {
|
|
25
|
+
as: "p",
|
|
26
|
+
className: "font-medium text-co-foreground",
|
|
27
|
+
textKey: isRated ? "component.conversationPage.ratingThanks" : "component.conversationPage.ratingPrompt"
|
|
28
|
+
}),
|
|
29
|
+
/* @__PURE__ */ jsx("div", {
|
|
30
|
+
className: "mt-2 flex items-center justify-center gap-1",
|
|
31
|
+
children: Array.from({ length: STAR_COUNT }).map((_, index) => {
|
|
32
|
+
const value = index + 1;
|
|
33
|
+
const isFilled = rating ? value <= rating : false;
|
|
34
|
+
return /* @__PURE__ */ jsx("button", {
|
|
35
|
+
"aria-label": text("component.conversationPage.ratingLabel", { rating: value }),
|
|
36
|
+
className: cn("group inline-flex h-8 w-8 items-center justify-center rounded-md transition-colors", isInteractive ? "hover:bg-co-muted" : "cursor-default opacity-70"),
|
|
37
|
+
disabled: !isInteractive,
|
|
38
|
+
onClick: () => onRate?.(value),
|
|
39
|
+
type: "button",
|
|
40
|
+
children: /* @__PURE__ */ jsx(icons_default, {
|
|
41
|
+
className: "h-4 w-4 text-co-primary",
|
|
42
|
+
name: "star",
|
|
43
|
+
variant: isFilled ? "filled" : "default"
|
|
44
|
+
})
|
|
45
|
+
}, value);
|
|
46
|
+
})
|
|
47
|
+
}),
|
|
48
|
+
/* @__PURE__ */ jsx(Text, {
|
|
49
|
+
as: "p",
|
|
50
|
+
className: "mt-2 text-co-muted-foreground text-xs",
|
|
51
|
+
textKey: "component.conversationPage.closedMessage"
|
|
52
|
+
})
|
|
53
|
+
]
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { ConversationResolvedFeedback };
|
|
59
|
+
//# sourceMappingURL=conversation-resolved-feedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-resolved-feedback.js","names":["Icon"],"sources":["../../../src/support/components/conversation-resolved-feedback.tsx"],"sourcesContent":["import { ConversationStatus } from \"@cossistant/types\";\nimport { Text, useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\n\ntype ConversationResolvedFeedbackProps = {\n\tstatus: ConversationStatus | null;\n\trating: number | null;\n\tonRate?: (rating: number) => void;\n\tisSubmitting?: boolean;\n\tclassName?: string;\n};\n\nconst STAR_COUNT = 5;\n\nexport function ConversationResolvedFeedback({\n\tstatus,\n\trating,\n\tonRate,\n\tisSubmitting = false,\n\tclassName,\n}: ConversationResolvedFeedbackProps) {\n\tconst text = useSupportText();\n\tconst isResolved = status === ConversationStatus.RESOLVED;\n\tconst isRated = rating != null;\n\tconst isInteractive = Boolean(onRate) && !isSubmitting && !isRated;\n\n\tif (!isResolved) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"m-4 flex items-center justify-center text-balance px-4 pb-6 text-center font-medium text-co-muted-foreground text-sm\",\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<Text as=\"p\" textKey=\"component.conversationPage.closedMessage\" />\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"m-4 rounded-md border border-co-border/60 bg-co-background-100 px-4 py-3 text-center text-sm shadow-sm\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t<Text\n\t\t\t\tas=\"p\"\n\t\t\t\tclassName=\"font-medium text-co-foreground\"\n\t\t\t\ttextKey={\n\t\t\t\t\tisRated\n\t\t\t\t\t\t? \"component.conversationPage.ratingThanks\"\n\t\t\t\t\t\t: \"component.conversationPage.ratingPrompt\"\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<div className=\"mt-2 flex items-center justify-center gap-1\">\n\t\t\t\t{Array.from({ length: STAR_COUNT }).map((_, index) => {\n\t\t\t\t\tconst value = index + 1;\n\t\t\t\t\tconst isFilled = rating ? value <= rating : false;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\taria-label={text(\"component.conversationPage.ratingLabel\", {\n\t\t\t\t\t\t\t\trating: value,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"group inline-flex h-8 w-8 items-center justify-center rounded-md transition-colors\",\n\t\t\t\t\t\t\t\tisInteractive\n\t\t\t\t\t\t\t\t\t? \"hover:bg-co-muted\"\n\t\t\t\t\t\t\t\t\t: \"cursor-default opacity-70\"\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tdisabled={!isInteractive}\n\t\t\t\t\t\t\tkey={value}\n\t\t\t\t\t\t\tonClick={() => onRate?.(value)}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon\n\t\t\t\t\t\t\t\tclassName=\"h-4 w-4 text-co-primary\"\n\t\t\t\t\t\t\t\tname=\"star\"\n\t\t\t\t\t\t\t\tvariant={isFilled ? \"filled\" : \"default\"}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t<Text\n\t\t\t\tas=\"p\"\n\t\t\t\tclassName=\"mt-2 text-co-muted-foreground text-xs\"\n\t\t\t\ttextKey=\"component.conversationPage.closedMessage\"\n\t\t\t/>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;;;AAaA,MAAM,aAAa;AAEnB,SAAgB,6BAA6B,EAC5C,QACA,QACA,QACA,eAAe,OACf,aACqC;CACrC,MAAM,OAAO,gBAAgB;CAC7B,MAAM,aAAa,WAAW,mBAAmB;CACjD,MAAM,UAAU,UAAU;CAC1B,MAAM,gBAAgB,QAAQ,OAAO,IAAI,CAAC,gBAAgB,CAAC;AAE3D,KAAI,CAAC,WACJ,QACC,oBAAC;EACA,WAAW,GACV,wHACA,UACA;YAED,oBAAC;GAAK,IAAG;GAAI,SAAQ;IAA6C;GAC7D;AAIR,QACC,qBAAC;EACA,WAAW,GACV,0GACA,UACA;;GAED,oBAAC;IACA,IAAG;IACH,WAAU;IACV,SACC,UACG,4CACA;KAEH;GACF,oBAAC;IAAI,WAAU;cACb,MAAM,KAAK,EAAE,QAAQ,YAAY,CAAC,CAAC,KAAK,GAAG,UAAU;KACrD,MAAM,QAAQ,QAAQ;KACtB,MAAM,WAAW,SAAS,SAAS,SAAS;AAE5C,YACC,oBAAC;MACA,cAAY,KAAK,0CAA0C,EAC1D,QAAQ,OACR,CAAC;MACF,WAAW,GACV,sFACA,gBACG,sBACA,4BACH;MACD,UAAU,CAAC;MAEX,eAAe,SAAS,MAAM;MAC9B,MAAK;gBAEL,oBAACA;OACA,WAAU;OACV,MAAK;OACL,SAAS,WAAW,WAAW;QAC9B;QARG,MASG;MAET;KACG;GACN,oBAAC;IACA,IAAG;IACH,WAAU;IACV,SAAQ;KACP;;GACG"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
//#region src/support/components/conversation-timeline-utils.d.ts
|
|
2
|
+
declare function filterSeenByIdsForViewer(seenByIds: readonly string[], viewerId?: string): readonly string[];
|
|
3
|
+
//#endregion
|
|
4
|
+
export { filterSeenByIdsForViewer };
|
|
5
|
+
//# sourceMappingURL=conversation-timeline-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-timeline-utils.d.ts","names":[],"sources":["../../../src/support/components/conversation-timeline-utils.ts"],"sourcesContent":[],"mappings":";iBAAgB,wBAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/support/components/conversation-timeline-utils.ts
|
|
2
|
+
function filterSeenByIdsForViewer(seenByIds, viewerId) {
|
|
3
|
+
if (!viewerId || seenByIds.length === 0) return seenByIds;
|
|
4
|
+
if (!seenByIds.includes(viewerId)) return seenByIds;
|
|
5
|
+
return seenByIds.filter((id) => id !== viewerId);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
export { filterSeenByIdsForViewer };
|
|
10
|
+
//# sourceMappingURL=conversation-timeline-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-timeline-utils.js","names":[],"sources":["../../../src/support/components/conversation-timeline-utils.ts"],"sourcesContent":["export function filterSeenByIdsForViewer(\n\tseenByIds: readonly string[],\n\tviewerId?: string\n): readonly string[] {\n\tif (!viewerId || seenByIds.length === 0) {\n\t\treturn seenByIds;\n\t}\n\n\tif (!seenByIds.includes(viewerId)) {\n\t\treturn seenByIds;\n\t}\n\n\treturn seenByIds.filter((id) => id !== viewerId);\n}\n"],"mappings":";AAAA,SAAgB,yBACf,WACA,UACoB;AACpB,KAAI,CAAC,YAAY,UAAU,WAAW,EACrC,QAAO;AAGR,KAAI,CAAC,UAAU,SAAS,SAAS,CAChC,QAAO;AAGR,QAAO,UAAU,QAAQ,OAAO,OAAO,SAAS"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-timeline.d.ts","names":[],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"conversation-timeline.d.ts","names":[],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":[],"mappings":";;;;;;KA0CY,6BAAA;QACL;EADK,cAAA,EAAA,MAAA;AAKZ,CAAA;AAIY,KAJA,kCAAA,GAMX;EAGW,SAAA,EARA,KAAA,CAAM,aAQmB,CARL,6BAQK,CAAA;CAE7B;AAEY,KATR,yBAAA,GAA4B,MASpB,CAAA,MAAA,EAPnB,kCAOmB,CAAA;AACG,KALX,yBAAA,GAKW;EAEd,cAAA,EAAA,MAAA;EAED,KAAA,EAPA,YAOA,EAAA;EACa,SAAA,CAAA,EAAA,MAAA;EACd,iBAAM,EAPO,gBAOP,EAAA;EAAS,oBAAA,EANC,mBAMD,EAAA;EAGT,gBAAA,CAAA,EAAA,MAAA;UAPJ;;UAED;uBACa;QACd,KAAA,CAAM;;cAGA,0BAA0B,KAAA,CAAM,GAAG"}
|
|
@@ -5,6 +5,7 @@ import { DaySeparator, DaySeparatorLabel, DaySeparatorLine, defaultFormatDate }
|
|
|
5
5
|
import { useTypingSound } from "../../hooks/use-typing-sound.js";
|
|
6
6
|
import { useConversationTimeline } from "../../hooks/use-conversation-timeline.js";
|
|
7
7
|
import { ConversationEvent } from "./conversation-event.js";
|
|
8
|
+
import { filterSeenByIdsForViewer } from "./conversation-timeline-utils.js";
|
|
8
9
|
import { TimelineMessageGroup } from "./timeline-message-group.js";
|
|
9
10
|
import { useCallback, useMemo } from "react";
|
|
10
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -97,7 +98,7 @@ const ConversationTimelineList = ({ conversationId, items: timelineItems, classN
|
|
|
97
98
|
item: item.item
|
|
98
99
|
}, toolKey);
|
|
99
100
|
}
|
|
100
|
-
const seenByIds = index === timeline.lastVisitorMessageGroupIndex && item.lastMessageId ? timeline.groupedMessages.getMessageSeenBy(item.lastMessageId) : EMPTY_SEEN_BY_IDS;
|
|
101
|
+
const seenByIds = filterSeenByIdsForViewer(index === timeline.lastVisitorMessageGroupIndex && item.lastMessageId ? timeline.groupedMessages.getMessageSeenBy(item.lastMessageId) : EMPTY_SEEN_BY_IDS, currentVisitorId);
|
|
101
102
|
const seenByNames = seenByIds.length > 0 ? getSeenByNames(seenByIds) : EMPTY_SEEN_BY_NAMES;
|
|
102
103
|
const groupKey = item.lastMessageId ?? item.items?.[0]?.id ?? `group-${item.items?.[0]?.createdAt ?? index}`;
|
|
103
104
|
return /* @__PURE__ */ jsx(TimelineMessageGroup, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-timeline.js","names":["EMPTY_SEEN_BY_IDS: readonly string[]","EMPTY_SEEN_BY_NAMES: readonly string[]","ConversationTimelineList: React.FC<ConversationTimelineProps>","names: string[]","PrimitiveConversationTimeline"],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport type {\n\tTimelineItem,\n\tTimelinePartEvent,\n} from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useCallback, useMemo } from \"react\";\nimport type { DaySeparatorItem } from \"../../hooks/private/use-grouped-messages\";\nimport { useConversationTimeline } from \"../../hooks/use-conversation-timeline\";\nimport { useTypingSound } from \"../../hooks/use-typing-sound\";\nimport {\n\tConversationTimelineContainer,\n\tConversationTimeline as PrimitiveConversationTimeline,\n} from \"../../primitives/conversation-timeline\";\nimport {\n\tDaySeparator,\n\tDaySeparatorLabel,\n\tDaySeparatorLine,\n\tdefaultFormatDate,\n} from \"../../primitives/day-separator\";\nimport { cn } from \"../utils\";\nimport { ConversationEvent } from \"./conversation-event\";\nimport { TimelineMessageGroup } from \"./timeline-message-group\";\nimport { TypingIndicator, type TypingParticipant } from \"./typing-indicator\";\n\n// Helper to extract event part from timeline item\nfunction extractEventPart(item: TimelineItem): TimelinePartEvent | null {\n\tif (item.type !== \"event\") {\n\t\treturn null;\n\t}\n\n\tconst eventPart = item.parts.find(\n\t\t(part): part is TimelinePartEvent => part.type === \"event\"\n\t);\n\n\treturn eventPart || null;\n}\n\nconst EMPTY_SEEN_BY_IDS: readonly string[] = Object.freeze([]);\nconst EMPTY_SEEN_BY_NAMES: readonly string[] = Object.freeze([]);\n\nexport type ConversationTimelineToolProps = {\n\titem: TimelineItem;\n\tconversationId: string;\n};\n\nexport type ConversationTimelineToolDefinition = {\n\tcomponent: React.ComponentType<ConversationTimelineToolProps>;\n};\n\nexport type ConversationTimelineTools = Record<\n\tstring,\n\tConversationTimelineToolDefinition\n>;\n\nexport type ConversationTimelineProps = {\n\tconversationId: string;\n\titems: TimelineItem[];\n\tclassName?: string;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcurrentVisitorId?: string;\n\ttools?: ConversationTimelineTools;\n\trenderDaySeparator?: (props: {\n\t\titem: DaySeparatorItem;\n\t\tformatDate: (date: Date) => string;\n\t}) => React.ReactNode;\n};\n\nexport const ConversationTimelineList: React.FC<ConversationTimelineProps> = ({\n\tconversationId,\n\titems: timelineItems,\n\tclassName,\n\tavailableAIAgents = [],\n\tavailableHumanAgents = [],\n\tcurrentVisitorId,\n\ttools,\n\trenderDaySeparator,\n}) => {\n\tconst timeline = useConversationTimeline({\n\t\tconversationId,\n\t\titems: timelineItems,\n\t\tcurrentVisitorId,\n\t});\n\n\tconst typingIndicatorParticipants = useMemo(\n\t\t() =>\n\t\t\ttimeline.typingParticipants.map<TypingParticipant>((participant) => ({\n\t\t\t\tid: participant.id,\n\t\t\t\ttype: participant.type,\n\t\t\t})),\n\t\t[timeline.typingParticipants]\n\t);\n\n\t// Play typing sound when someone is typing\n\tuseTypingSound(typingIndicatorParticipants.length > 0, {\n\t\tvolume: 1,\n\t\tplaybackRate: 1.3,\n\t});\n\n\tconst seenNameLookup = useMemo(() => {\n\t\tconst map = new Map<string, string>();\n\n\t\tfor (const agent of availableHumanAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\tfor (const agent of availableAIAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\treturn map;\n\t}, [availableHumanAgents, availableAIAgents]);\n\n\tconst getSeenByNames = useCallback(\n\t\t(ids: readonly string[] = EMPTY_SEEN_BY_IDS): readonly string[] => {\n\t\t\tif (ids.length === 0 || seenNameLookup.size === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\tconst uniqueNames = new Set<string>();\n\t\t\tconst names: string[] = [];\n\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst name = seenNameLookup.get(id);\n\t\t\t\tif (!name || uniqueNames.has(name)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tuniqueNames.add(name);\n\t\t\t\tnames.push(name);\n\t\t\t}\n\n\t\t\tif (names.length === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\treturn Object.freeze(names);\n\t\t},\n\t\t[seenNameLookup]\n\t);\n\n\treturn (\n\t\t<PrimitiveConversationTimeline\n\t\t\tautoScroll={true}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-y-scroll px-3 py-6\",\n\t\t\t\t\"co-scrollbar-thin\",\n\t\t\t\t\"h-full w-full\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tid=\"conversation-timeline\"\n\t\t\titems={timelineItems}\n\t\t>\n\t\t\t<ConversationTimelineContainer className=\"flex min-h-full w-full flex-col gap-5\">\n\t\t\t\t{timeline.groupedMessages.items.map((item, index) => {\n\t\t\t\t\tif (item.type === \"day_separator\") {\n\t\t\t\t\t\t// Render day separator - allow custom rendering via prop\n\t\t\t\t\t\tif (renderDaySeparator) {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div key={`day-separator-${item.dateString}`}>\n\t\t\t\t\t\t\t\t\t{renderDaySeparator({\n\t\t\t\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\t\t\t\tformatDate: defaultFormatDate,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Default day separator using the primitive\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<DaySeparator\n\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-center py-2\"\n\t\t\t\t\t\t\t\tdate={item.date}\n\t\t\t\t\t\t\t\tdateString={item.dateString}\n\t\t\t\t\t\t\t\tkey={`day-separator-${item.dateString}`}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{({ formattedDate }) => (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<DaySeparatorLine className=\"flex-1 border-gray-300/20 border-t dark:border-gray-600/20\" />\n\t\t\t\t\t\t\t\t\t\t<DaySeparatorLabel\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"px-3 text-gray-400/50 text-xs dark:text-gray-500/50\"\n\t\t\t\t\t\t\t\t\t\t\tformattedDate={formattedDate}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<DaySeparatorLine className=\"flex-1 border-gray-300/20 border-t dark:border-gray-600/20\" />\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</DaySeparator>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (item.type === \"timeline_event\") {\n\t\t\t\t\t\t// Extract event data from parts\n\t\t\t\t\t\tconst eventPart = extractEventPart(item.item);\n\n\t\t\t\t\t\t// Only render if we have valid event data\n\t\t\t\t\t\tif (!eventPart) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ConversationEvent\n\t\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\t\tcreatedAt={item.item.createdAt}\n\t\t\t\t\t\t\t\tevent={eventPart}\n\t\t\t\t\t\t\t\tkey={item.item.id ?? `timeline-event-${item.item.createdAt}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (item.type === \"timeline_tool\") {\n\t\t\t\t\t\tconst toolName = item.tool ?? item.item.tool ?? item.item.type;\n\t\t\t\t\t\tconst toolDefinition = toolName ? tools?.[toolName] : undefined;\n\n\t\t\t\t\t\tif (!toolDefinition) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst ToolComponent = toolDefinition.component;\n\n\t\t\t\t\t\tconst toolKey =\n\t\t\t\t\t\t\titem.item.id ?? `${toolName}-${item.item.createdAt}-${index}`;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ToolComponent\n\t\t\t\t\t\t\t\tconversationId={conversationId}\n\t\t\t\t\t\t\t\titem={item.item}\n\t\t\t\t\t\t\t\tkey={toolKey}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only show seen indicator on the LAST message group sent by the visitor\n\t\t\t\t\tconst isLastVisitorGroup =\n\t\t\t\t\t\tindex === timeline.lastVisitorMessageGroupIndex;\n\t\t\t\t\tconst seenByIds =\n\t\t\t\t\t\tisLastVisitorGroup && item.lastMessageId\n\t\t\t\t\t\t\t? timeline.groupedMessages.getMessageSeenBy(item.lastMessageId)\n\t\t\t\t\t\t\t: EMPTY_SEEN_BY_IDS;\n\t\t\t\t\tconst seenByNames =\n\t\t\t\t\t\tseenByIds.length > 0\n\t\t\t\t\t\t\t? getSeenByNames(seenByIds)\n\t\t\t\t\t\t\t: EMPTY_SEEN_BY_NAMES;\n\n\t\t\t\t\t// Use first timeline item ID as stable key\n\t\t\t\t\tconst groupKey =\n\t\t\t\t\t\titem.lastMessageId ??\n\t\t\t\t\t\titem.items?.[0]?.id ??\n\t\t\t\t\t\t`group-${item.items?.[0]?.createdAt ?? index}`;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<TimelineMessageGroup\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tcurrentVisitorId={currentVisitorId}\n\t\t\t\t\t\t\titems={item.items || []}\n\t\t\t\t\t\t\tkey={groupKey}\n\t\t\t\t\t\t\tseenByIds={seenByIds}\n\t\t\t\t\t\t\tseenByNames={seenByNames}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t\t<div className=\"h-6 w-full\">\n\t\t\t\t\t{typingIndicatorParticipants.length > 0 ? (\n\t\t\t\t\t\t<TypingIndicator\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tclassName=\"mt-2\"\n\t\t\t\t\t\t\tparticipants={typingIndicatorParticipants}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</ConversationTimelineContainer>\n\t\t</PrimitiveConversationTimeline>\n\t);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conversation-timeline.js","names":["EMPTY_SEEN_BY_IDS: readonly string[]","EMPTY_SEEN_BY_NAMES: readonly string[]","ConversationTimelineList: React.FC<ConversationTimelineProps>","names: string[]","PrimitiveConversationTimeline"],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport type {\n\tTimelineItem,\n\tTimelinePartEvent,\n} from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useCallback, useMemo } from \"react\";\nimport type { DaySeparatorItem } from \"../../hooks/private/use-grouped-messages\";\nimport { useConversationTimeline } from \"../../hooks/use-conversation-timeline\";\nimport { useTypingSound } from \"../../hooks/use-typing-sound\";\nimport {\n\tConversationTimelineContainer,\n\tConversationTimeline as PrimitiveConversationTimeline,\n} from \"../../primitives/conversation-timeline\";\nimport {\n\tDaySeparator,\n\tDaySeparatorLabel,\n\tDaySeparatorLine,\n\tdefaultFormatDate,\n} from \"../../primitives/day-separator\";\nimport { cn } from \"../utils\";\nimport { ConversationEvent } from \"./conversation-event\";\nimport { filterSeenByIdsForViewer } from \"./conversation-timeline-utils\";\nimport { TimelineMessageGroup } from \"./timeline-message-group\";\nimport { TypingIndicator, type TypingParticipant } from \"./typing-indicator\";\n\n// Helper to extract event part from timeline item\nfunction extractEventPart(item: TimelineItem): TimelinePartEvent | null {\n\tif (item.type !== \"event\") {\n\t\treturn null;\n\t}\n\n\tconst eventPart = item.parts.find(\n\t\t(part): part is TimelinePartEvent => part.type === \"event\"\n\t);\n\n\treturn eventPart || null;\n}\n\nconst EMPTY_SEEN_BY_IDS: readonly string[] = Object.freeze([]);\nconst EMPTY_SEEN_BY_NAMES: readonly string[] = Object.freeze([]);\n\nexport type ConversationTimelineToolProps = {\n\titem: TimelineItem;\n\tconversationId: string;\n};\n\nexport type ConversationTimelineToolDefinition = {\n\tcomponent: React.ComponentType<ConversationTimelineToolProps>;\n};\n\nexport type ConversationTimelineTools = Record<\n\tstring,\n\tConversationTimelineToolDefinition\n>;\n\nexport type ConversationTimelineProps = {\n\tconversationId: string;\n\titems: TimelineItem[];\n\tclassName?: string;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcurrentVisitorId?: string;\n\ttools?: ConversationTimelineTools;\n\trenderDaySeparator?: (props: {\n\t\titem: DaySeparatorItem;\n\t\tformatDate: (date: Date) => string;\n\t}) => React.ReactNode;\n};\n\nexport const ConversationTimelineList: React.FC<ConversationTimelineProps> = ({\n\tconversationId,\n\titems: timelineItems,\n\tclassName,\n\tavailableAIAgents = [],\n\tavailableHumanAgents = [],\n\tcurrentVisitorId,\n\ttools,\n\trenderDaySeparator,\n}) => {\n\tconst timeline = useConversationTimeline({\n\t\tconversationId,\n\t\titems: timelineItems,\n\t\tcurrentVisitorId,\n\t});\n\n\tconst typingIndicatorParticipants = useMemo(\n\t\t() =>\n\t\t\ttimeline.typingParticipants.map<TypingParticipant>((participant) => ({\n\t\t\t\tid: participant.id,\n\t\t\t\ttype: participant.type,\n\t\t\t})),\n\t\t[timeline.typingParticipants]\n\t);\n\n\t// Play typing sound when someone is typing\n\tuseTypingSound(typingIndicatorParticipants.length > 0, {\n\t\tvolume: 1,\n\t\tplaybackRate: 1.3,\n\t});\n\n\tconst seenNameLookup = useMemo(() => {\n\t\tconst map = new Map<string, string>();\n\n\t\tfor (const agent of availableHumanAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\tfor (const agent of availableAIAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\treturn map;\n\t}, [availableHumanAgents, availableAIAgents]);\n\n\tconst getSeenByNames = useCallback(\n\t\t(ids: readonly string[] = EMPTY_SEEN_BY_IDS): readonly string[] => {\n\t\t\tif (ids.length === 0 || seenNameLookup.size === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\tconst uniqueNames = new Set<string>();\n\t\t\tconst names: string[] = [];\n\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst name = seenNameLookup.get(id);\n\t\t\t\tif (!name || uniqueNames.has(name)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tuniqueNames.add(name);\n\t\t\t\tnames.push(name);\n\t\t\t}\n\n\t\t\tif (names.length === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\treturn Object.freeze(names);\n\t\t},\n\t\t[seenNameLookup]\n\t);\n\n\treturn (\n\t\t<PrimitiveConversationTimeline\n\t\t\tautoScroll={true}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-y-scroll px-3 py-6\",\n\t\t\t\t\"co-scrollbar-thin\",\n\t\t\t\t\"h-full w-full\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tid=\"conversation-timeline\"\n\t\t\titems={timelineItems}\n\t\t>\n\t\t\t<ConversationTimelineContainer className=\"flex min-h-full w-full flex-col gap-5\">\n\t\t\t\t{timeline.groupedMessages.items.map((item, index) => {\n\t\t\t\t\tif (item.type === \"day_separator\") {\n\t\t\t\t\t\t// Render day separator - allow custom rendering via prop\n\t\t\t\t\t\tif (renderDaySeparator) {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div key={`day-separator-${item.dateString}`}>\n\t\t\t\t\t\t\t\t\t{renderDaySeparator({\n\t\t\t\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\t\t\t\tformatDate: defaultFormatDate,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Default day separator using the primitive\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<DaySeparator\n\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-center py-2\"\n\t\t\t\t\t\t\t\tdate={item.date}\n\t\t\t\t\t\t\t\tdateString={item.dateString}\n\t\t\t\t\t\t\t\tkey={`day-separator-${item.dateString}`}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{({ formattedDate }) => (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<DaySeparatorLine className=\"flex-1 border-gray-300/20 border-t dark:border-gray-600/20\" />\n\t\t\t\t\t\t\t\t\t\t<DaySeparatorLabel\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"px-3 text-gray-400/50 text-xs dark:text-gray-500/50\"\n\t\t\t\t\t\t\t\t\t\t\tformattedDate={formattedDate}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<DaySeparatorLine className=\"flex-1 border-gray-300/20 border-t dark:border-gray-600/20\" />\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</DaySeparator>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (item.type === \"timeline_event\") {\n\t\t\t\t\t\t// Extract event data from parts\n\t\t\t\t\t\tconst eventPart = extractEventPart(item.item);\n\n\t\t\t\t\t\t// Only render if we have valid event data\n\t\t\t\t\t\tif (!eventPart) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ConversationEvent\n\t\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\t\tcreatedAt={item.item.createdAt}\n\t\t\t\t\t\t\t\tevent={eventPart}\n\t\t\t\t\t\t\t\tkey={item.item.id ?? `timeline-event-${item.item.createdAt}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (item.type === \"timeline_tool\") {\n\t\t\t\t\t\tconst toolName = item.tool ?? item.item.tool ?? item.item.type;\n\t\t\t\t\t\tconst toolDefinition = toolName ? tools?.[toolName] : undefined;\n\n\t\t\t\t\t\tif (!toolDefinition) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst ToolComponent = toolDefinition.component;\n\n\t\t\t\t\t\tconst toolKey =\n\t\t\t\t\t\t\titem.item.id ?? `${toolName}-${item.item.createdAt}-${index}`;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ToolComponent\n\t\t\t\t\t\t\t\tconversationId={conversationId}\n\t\t\t\t\t\t\t\titem={item.item}\n\t\t\t\t\t\t\t\tkey={toolKey}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only show seen indicator on the LAST message group sent by the visitor\n\t\t\t\t\tconst isLastVisitorGroup =\n\t\t\t\t\t\tindex === timeline.lastVisitorMessageGroupIndex;\n\t\t\t\t\tconst rawSeenByIds =\n\t\t\t\t\t\tisLastVisitorGroup && item.lastMessageId\n\t\t\t\t\t\t\t? timeline.groupedMessages.getMessageSeenBy(item.lastMessageId)\n\t\t\t\t\t\t\t: EMPTY_SEEN_BY_IDS;\n\t\t\t\t\tconst seenByIds = filterSeenByIdsForViewer(\n\t\t\t\t\t\trawSeenByIds,\n\t\t\t\t\t\tcurrentVisitorId\n\t\t\t\t\t);\n\t\t\t\t\tconst seenByNames =\n\t\t\t\t\t\tseenByIds.length > 0\n\t\t\t\t\t\t\t? getSeenByNames(seenByIds)\n\t\t\t\t\t\t\t: EMPTY_SEEN_BY_NAMES;\n\n\t\t\t\t\t// Use first timeline item ID as stable key\n\t\t\t\t\tconst groupKey =\n\t\t\t\t\t\titem.lastMessageId ??\n\t\t\t\t\t\titem.items?.[0]?.id ??\n\t\t\t\t\t\t`group-${item.items?.[0]?.createdAt ?? index}`;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<TimelineMessageGroup\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tcurrentVisitorId={currentVisitorId}\n\t\t\t\t\t\t\titems={item.items || []}\n\t\t\t\t\t\t\tkey={groupKey}\n\t\t\t\t\t\t\tseenByIds={seenByIds}\n\t\t\t\t\t\t\tseenByNames={seenByNames}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t\t<div className=\"h-6 w-full\">\n\t\t\t\t\t{typingIndicatorParticipants.length > 0 ? (\n\t\t\t\t\t\t<TypingIndicator\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tclassName=\"mt-2\"\n\t\t\t\t\t\t\tparticipants={typingIndicatorParticipants}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</ConversationTimelineContainer>\n\t\t</PrimitiveConversationTimeline>\n\t);\n};\n"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
|
|
3
3
|
//#region src/support/components/icons.d.ts
|
|
4
4
|
type IconVariant = "default" | "filled";
|
|
5
|
-
type IconName = "sidebar" | "check" | "x" | "clipboard" | "send" | "chevron-down" | "arrow-left" | "arrow-right" | "arrow-up-right" | "attachment" | "file" | "close" | "home" | "articles" | "chat";
|
|
5
|
+
type IconName = "sidebar" | "check" | "x" | "clipboard" | "send" | "chevron-down" | "arrow-left" | "arrow-right" | "arrow-up-right" | "attachment" | "file" | "close" | "home" | "articles" | "chat" | "star";
|
|
6
6
|
type IconProps = {
|
|
7
7
|
name: IconName;
|
|
8
8
|
variant?: IconVariant;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icons.d.ts","names":[],"sources":["../../../src/support/components/icons.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA;KAEA,QAAA;AAFA,
|
|
1
|
+
{"version":3,"file":"icons.d.ts","names":[],"sources":["../../../src/support/components/icons.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA;KAEA,QAAA;AAFA,KAoBA,SAAA,GApBW;EAEX,IAAA,EAmBL,QAnBa;EAkBR,OAAA,CAAA,EAED,WAFU;EAqGR,SAmGZ,CAAA,EAAA,MAAA;EAEW,aAAA,CAAA,EAAA,OAAkB;;cArGjB,MAAM,KAAA,CAAM,GAAG;KAqGhB,kBAAA"}
|