@cossistant/react 0.0.31 → 0.0.33

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 (145) hide show
  1. package/hooks/index.d.ts +2 -2
  2. package/hooks/index.js +2 -2
  3. package/hooks/private/use-grouped-messages.d.ts +27 -2
  4. package/hooks/private/use-grouped-messages.d.ts.map +1 -1
  5. package/hooks/private/use-grouped-messages.js +156 -103
  6. package/hooks/private/use-grouped-messages.js.map +1 -1
  7. package/hooks/use-new-message-sound.d.ts.map +1 -1
  8. package/hooks/use-new-message-sound.js +2 -2
  9. package/hooks/use-new-message-sound.js.map +1 -1
  10. package/hooks/use-send-message.js +1 -1
  11. package/hooks/use-send-message.js.map +1 -1
  12. package/hooks/use-typing-sound.d.ts.map +1 -1
  13. package/hooks/use-typing-sound.js +2 -2
  14. package/hooks/use-typing-sound.js.map +1 -1
  15. package/index.d.ts +2 -2
  16. package/index.js +2 -2
  17. package/package.json +4 -6
  18. package/packages/tiny-markdown/src/context/index.d.ts +1 -0
  19. package/packages/tiny-markdown/src/context/tiny-markdown-context.d.ts +3 -0
  20. package/packages/tiny-markdown/src/hooks/index.d.ts +4 -0
  21. package/packages/tiny-markdown/src/hooks/use-caret-position.d.ts +1 -0
  22. package/packages/tiny-markdown/src/hooks/use-tiny-markdown.d.ts +1 -0
  23. package/packages/tiny-markdown/src/hooks/use-tiny-mention.d.ts +1 -0
  24. package/packages/tiny-markdown/src/hooks/use-tiny-shortcuts.d.ts +1 -0
  25. package/packages/tiny-markdown/src/index.d.ts +4 -0
  26. package/packages/tiny-markdown/src/types.d.ts +75 -0
  27. package/packages/tiny-markdown/src/types.d.ts.map +1 -0
  28. package/packages/tiny-markdown/src/utils/index.d.ts +3 -0
  29. package/packages/tiny-markdown/src/utils/markdown-parser.d.ts +1 -0
  30. package/packages/tiny-markdown/src/utils/mention-parser.d.ts +1 -0
  31. package/packages/tiny-markdown/src/utils/merge-refs.d.ts +1 -0
  32. package/packages/types/src/api/conversation.d.ts +316 -12
  33. package/packages/types/src/api/conversation.d.ts.map +1 -1
  34. package/packages/types/src/api/timeline-item.d.ts +236 -9
  35. package/packages/types/src/api/timeline-item.d.ts.map +1 -1
  36. package/packages/types/src/realtime-events.d.ts +259 -13
  37. package/packages/types/src/realtime-events.d.ts.map +1 -1
  38. package/packages/types/src/schemas.d.ts +79 -3
  39. package/packages/types/src/schemas.d.ts.map +1 -1
  40. package/primitives/avatar/image.d.ts +1 -1
  41. package/primitives/command-block-utils.d.ts +26 -0
  42. package/primitives/command-block-utils.d.ts.map +1 -0
  43. package/primitives/command-block-utils.js +310 -0
  44. package/primitives/command-block-utils.js.map +1 -0
  45. package/primitives/index.d.ts +7 -3
  46. package/primitives/index.js +11 -2
  47. package/primitives/index.parts.d.ts +6 -2
  48. package/primitives/index.parts.js +5 -1
  49. package/primitives/multimodal-input.d.ts +2 -2
  50. package/primitives/multimodal-input.d.ts.map +1 -1
  51. package/primitives/timeline-code-block.d.ts +32 -0
  52. package/primitives/timeline-code-block.d.ts.map +1 -0
  53. package/primitives/timeline-code-block.js +66 -0
  54. package/primitives/timeline-code-block.js.map +1 -0
  55. package/primitives/timeline-command-block.d.ts +29 -0
  56. package/primitives/timeline-command-block.d.ts.map +1 -0
  57. package/primitives/timeline-command-block.js +97 -0
  58. package/primitives/timeline-command-block.js.map +1 -0
  59. package/primitives/timeline-item-group.d.ts.map +1 -1
  60. package/primitives/timeline-item-group.js +5 -15
  61. package/primitives/timeline-item-group.js.map +1 -1
  62. package/primitives/timeline-item.d.ts +23 -3
  63. package/primitives/timeline-item.d.ts.map +1 -1
  64. package/primitives/timeline-item.js +151 -80
  65. package/primitives/timeline-item.js.map +1 -1
  66. package/primitives/timeline-message-layout.d.ts +9 -0
  67. package/primitives/timeline-message-layout.d.ts.map +1 -0
  68. package/primitives/timeline-message-layout.js +20 -0
  69. package/primitives/timeline-message-layout.js.map +1 -0
  70. package/provider.d.ts.map +1 -1
  71. package/provider.js +6 -3
  72. package/provider.js.map +1 -1
  73. package/realtime/event-filter.js +4 -3
  74. package/realtime/event-filter.js.map +1 -1
  75. package/sounds/sound-data.d.ts +6 -0
  76. package/sounds/sound-data.d.ts.map +1 -0
  77. package/sounds/sound-data.js +7 -0
  78. package/sounds/sound-data.js.map +1 -0
  79. package/support/components/avatar-stack.js +1 -1
  80. package/support/components/avatar-stack.js.map +1 -1
  81. package/support/components/avatar.d.ts +1 -2
  82. package/support/components/avatar.d.ts.map +1 -1
  83. package/support/components/avatar.js +9 -7
  84. package/support/components/avatar.js.map +1 -1
  85. package/support/components/button.d.ts +2 -2
  86. package/support/components/button.d.ts.map +1 -1
  87. package/support/components/button.js +1 -0
  88. package/support/components/button.js.map +1 -1
  89. package/support/components/conversation-button-link.js +2 -1
  90. package/support/components/conversation-button-link.js.map +1 -1
  91. package/support/components/conversation-event.d.ts +3 -0
  92. package/support/components/conversation-event.d.ts.map +1 -1
  93. package/support/components/conversation-event.js +46 -15
  94. package/support/components/conversation-event.js.map +1 -1
  95. package/support/components/conversation-resolved-feedback.d.ts +1 -1
  96. package/support/components/conversation-resolved-feedback.d.ts.map +1 -1
  97. package/support/components/conversation-resolved-feedback.js +56 -13
  98. package/support/components/conversation-resolved-feedback.js.map +1 -1
  99. package/support/components/conversation-timeline.d.ts.map +1 -1
  100. package/support/components/conversation-timeline.js +12 -0
  101. package/support/components/conversation-timeline.js.map +1 -1
  102. package/support/components/index.d.ts +2 -1
  103. package/support/components/index.js +2 -1
  104. package/support/components/timeline-activity-group.d.ts +25 -0
  105. package/support/components/timeline-activity-group.d.ts.map +1 -0
  106. package/support/components/timeline-activity-group.js +104 -0
  107. package/support/components/timeline-activity-group.js.map +1 -0
  108. package/support/components/timeline-code-block.d.ts +14 -0
  109. package/support/components/timeline-code-block.d.ts.map +1 -0
  110. package/support/components/timeline-code-block.js +44 -0
  111. package/support/components/timeline-code-block.js.map +1 -0
  112. package/support/components/timeline-command-block.d.ts +12 -0
  113. package/support/components/timeline-command-block.d.ts.map +1 -0
  114. package/support/components/timeline-command-block.js +42 -0
  115. package/support/components/timeline-command-block.js.map +1 -0
  116. package/support/components/timeline-message-item.d.ts +2 -1
  117. package/support/components/timeline-message-item.d.ts.map +1 -1
  118. package/support/components/timeline-message-item.js +23 -3
  119. package/support/components/timeline-message-item.js.map +1 -1
  120. package/support/components/typing-indicator.d.ts.map +1 -1
  121. package/support/components/typing-indicator.js +15 -7
  122. package/support/components/typing-indicator.js.map +1 -1
  123. package/support/index.d.ts +4 -4
  124. package/support/pages/conversation-history.js +1 -1
  125. package/support/pages/conversation.js +4 -2
  126. package/support/pages/conversation.js.map +1 -1
  127. package/support/pages/home.js +1 -1
  128. package/support/store/support-store.d.ts +5 -5
  129. package/support/text/locales/en.js +3 -0
  130. package/support/text/locales/en.js.map +1 -1
  131. package/support/text/locales/es.js +3 -0
  132. package/support/text/locales/es.js.map +1 -1
  133. package/support/text/locales/fr.js +3 -0
  134. package/support/text/locales/fr.js.map +1 -1
  135. package/support/text/locales/keys.d.ts +9 -0
  136. package/support/text/locales/keys.d.ts.map +1 -1
  137. package/support/text/locales/keys.js +3 -0
  138. package/support/text/locales/keys.js.map +1 -1
  139. package/utils/metadata-hash.d.ts +1 -1
  140. package/utils/metadata-hash.js +9 -4
  141. package/utils/metadata-hash.js.map +1 -1
  142. package/utils/timeline-item-sender.d.ts +17 -0
  143. package/utils/timeline-item-sender.d.ts.map +1 -0
  144. package/utils/timeline-item-sender.js +43 -0
  145. package/utils/timeline-item-sender.js.map +1 -0
@@ -0,0 +1,25 @@
1
+ import { TimelineItem } from "../../packages/types/src/api/timeline-item.js";
2
+ import { GroupedActivity } from "../../hooks/private/use-grouped-messages.js";
3
+ import React from "react";
4
+ import { AvailableAIAgent, AvailableHumanAgent } from "@cossistant/types";
5
+
6
+ //#region src/support/components/timeline-activity-group.d.ts
7
+ type TimelineActivityToolProps = {
8
+ item: TimelineItem;
9
+ conversationId: string;
10
+ };
11
+ type TimelineActivityTools = Record<string, {
12
+ component: React.ComponentType<TimelineActivityToolProps>;
13
+ }>;
14
+ type TimelineActivityGroupProps = {
15
+ group: GroupedActivity;
16
+ conversationId: string;
17
+ availableAIAgents: AvailableAIAgent[];
18
+ availableHumanAgents: AvailableHumanAgent[];
19
+ currentVisitorId?: string;
20
+ tools?: TimelineActivityTools;
21
+ };
22
+ declare const TimelineActivityGroup: React.FC<TimelineActivityGroupProps>;
23
+ //#endregion
24
+ export { TimelineActivityGroup };
25
+ //# sourceMappingURL=timeline-activity-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-activity-group.d.ts","names":[],"sources":["../../../src/support/components/timeline-activity-group.tsx"],"sourcesContent":[],"mappings":";;;;;;KAkBK,yBAAA;QACE;EADF,cAAA,EAAA,MAAA;AACc,CAAA;KAId,qBAAA,GAAwB,MAGI,CAAA,MAAA,EAAA;EAApB,SAAM,EAAN,KAAA,CAAM,aAAA,CAAc,yBAAd,CAAA;CAHU,CAAA;KAOxB,0BAAA,GAP8B;EAO9B,KAAA,EACG,eADH;EACG,cAAA,EAAA,MAAA;EAEY,iBAAA,EAAA,gBAAA,EAAA;EACG,oBAAA,EAAA,mBAAA,EAAA;EAEd,gBAAA,CAAA,EAAA,MAAA;EAAqB,KAAA,CAAA,EAArB,qBAAqB;AAmD9B,CAAA;cAAa,uBAAuB,KAAA,CAAM,GAAG"}
@@ -0,0 +1,104 @@
1
+ import { Avatar } from "./avatar.js";
2
+ import { TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent } from "../../primitives/timeline-item-group.js";
3
+ import { ConversationEvent } from "./conversation-event.js";
4
+ import { useMemo } from "react";
5
+ import { SenderType } from "@cossistant/types";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+
8
+ //#region src/support/components/timeline-activity-group.tsx
9
+ function extractEventPart(item) {
10
+ if (item.type !== "event") return null;
11
+ return item.parts.find((part) => part.type === "event") || null;
12
+ }
13
+ function getToolNameFromTimelineItem(item) {
14
+ if (item.tool) return item.tool;
15
+ for (const part of item.parts) if (typeof part === "object" && part !== null && "type" in part && "toolName" in part && typeof part.type === "string" && part.type.startsWith("tool-") && typeof part.toolName === "string") return part.toolName;
16
+ return null;
17
+ }
18
+ const TimelineActivityGroup = ({ group, conversationId, availableAIAgents, availableHumanAgents, currentVisitorId, tools }) => {
19
+ const activityRows = useMemo(() => {
20
+ const rows = [];
21
+ for (let index = 0; index < group.items.length; index++) {
22
+ const item = group.items[index];
23
+ if (!item) continue;
24
+ if (item.type === "event") {
25
+ const eventPart = extractEventPart(item);
26
+ if (!eventPart) continue;
27
+ rows.push({
28
+ type: "event",
29
+ key: item.id ?? `activity-event-${item.createdAt}-${index}`,
30
+ item,
31
+ event: eventPart
32
+ });
33
+ continue;
34
+ }
35
+ if (item.type === "tool") {
36
+ const toolName = getToolNameFromTimelineItem(item);
37
+ if (!toolName) continue;
38
+ const toolDefinition = tools?.[toolName];
39
+ if (!toolDefinition) continue;
40
+ rows.push({
41
+ type: "tool",
42
+ key: item.id ?? `activity-tool-${item.createdAt}-${index}`,
43
+ item,
44
+ ToolComponent: toolDefinition.component
45
+ });
46
+ }
47
+ }
48
+ return rows;
49
+ }, [group.items, tools]);
50
+ if (activityRows.length === 0) return null;
51
+ const humanAgent = availableHumanAgents.find((agent) => agent.id === group.senderId);
52
+ const aiAgent = availableAIAgents.find((agent) => agent.id === group.senderId);
53
+ return /* @__PURE__ */ jsx(TimelineItemGroup, {
54
+ items: group.items,
55
+ viewerId: currentVisitorId,
56
+ viewerType: SenderType.VISITOR,
57
+ children: ({ isAI, isTeamMember }) => /* @__PURE__ */ jsxs("div", {
58
+ className: "flex w-full flex-row gap-2",
59
+ children: [/* @__PURE__ */ jsx(TimelineItemGroupAvatar, {
60
+ className: "flex shrink-0 flex-col justify-start",
61
+ children: isAI ? /* @__PURE__ */ jsx(Avatar, {
62
+ className: "size-6",
63
+ image: aiAgent?.image,
64
+ isAI: true,
65
+ name: aiAgent?.name || "AI Assistant",
66
+ showBackground: !!aiAgent?.image
67
+ }) : /* @__PURE__ */ jsx(Avatar, {
68
+ className: "size-6",
69
+ image: humanAgent?.image,
70
+ name: isTeamMember ? humanAgent?.name || "Support" : "Visitor"
71
+ })
72
+ }), /* @__PURE__ */ jsx(TimelineItemGroupContent, {
73
+ className: "flex min-w-0 flex-1 flex-col gap-1",
74
+ children: /* @__PURE__ */ jsx("div", {
75
+ className: "flex w-full min-w-0 flex-col gap-2",
76
+ children: activityRows.map((row) => {
77
+ if (row.type === "event") return /* @__PURE__ */ jsx(ConversationEvent, {
78
+ availableAIAgents,
79
+ availableHumanAgents,
80
+ className: "w-full",
81
+ compact: true,
82
+ createdAt: row.item.createdAt,
83
+ event: row.event,
84
+ showAvatar: false
85
+ }, row.key);
86
+ const ToolComponent = row.ToolComponent;
87
+ return /* @__PURE__ */ jsx("div", {
88
+ className: "w-full",
89
+ children: /* @__PURE__ */ jsx(ToolComponent, {
90
+ conversationId,
91
+ item: row.item
92
+ })
93
+ }, row.key);
94
+ })
95
+ })
96
+ })]
97
+ })
98
+ });
99
+ };
100
+ TimelineActivityGroup.displayName = "TimelineActivityGroup";
101
+
102
+ //#endregion
103
+ export { TimelineActivityGroup };
104
+ //# sourceMappingURL=timeline-activity-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-activity-group.js","names":["TimelineActivityGroup: React.FC<TimelineActivityGroupProps>","rows: ActivityRow[]","PrimitiveTimelineItemGroup"],"sources":["../../../src/support/components/timeline-activity-group.tsx"],"sourcesContent":["import type {\n\tAvailableAIAgent,\n\tAvailableHumanAgent,\n\tTimelinePartEvent,\n} from \"@cossistant/types\";\nimport { SenderType } from \"@cossistant/types\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useMemo } from \"react\";\nimport type { GroupedActivity } from \"../../hooks/private/use-grouped-messages\";\nimport {\n\tTimelineItemGroup as PrimitiveTimelineItemGroup,\n\tTimelineItemGroupAvatar,\n\tTimelineItemGroupContent,\n} from \"../../primitives/timeline-item-group\";\nimport { Avatar } from \"./avatar\";\nimport { ConversationEvent } from \"./conversation-event\";\n\ntype TimelineActivityToolProps = {\n\titem: TimelineItem;\n\tconversationId: string;\n};\n\ntype TimelineActivityTools = Record<\n\tstring,\n\t{\n\t\tcomponent: React.ComponentType<TimelineActivityToolProps>;\n\t}\n>;\n\ntype TimelineActivityGroupProps = {\n\tgroup: GroupedActivity;\n\tconversationId: string;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcurrentVisitorId?: string;\n\ttools?: TimelineActivityTools;\n};\n\ntype ActivityRow =\n\t| {\n\t\t\ttype: \"event\";\n\t\t\tkey: string;\n\t\t\titem: TimelineItem;\n\t\t\tevent: TimelinePartEvent;\n\t }\n\t| {\n\t\t\ttype: \"tool\";\n\t\t\tkey: string;\n\t\t\titem: TimelineItem;\n\t\t\tToolComponent: React.ComponentType<TimelineActivityToolProps>;\n\t };\n\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\nfunction getToolNameFromTimelineItem(item: TimelineItem): string | null {\n\tif (item.tool) {\n\t\treturn item.tool;\n\t}\n\n\tfor (const part of item.parts) {\n\t\tif (\n\t\t\ttypeof part === \"object\" &&\n\t\t\tpart !== null &&\n\t\t\t\"type\" in part &&\n\t\t\t\"toolName\" in part &&\n\t\t\ttypeof part.type === \"string\" &&\n\t\t\tpart.type.startsWith(\"tool-\") &&\n\t\t\ttypeof part.toolName === \"string\"\n\t\t) {\n\t\t\treturn part.toolName;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nexport const TimelineActivityGroup: React.FC<TimelineActivityGroupProps> = ({\n\tgroup,\n\tconversationId,\n\tavailableAIAgents,\n\tavailableHumanAgents,\n\tcurrentVisitorId,\n\ttools,\n}) => {\n\tconst activityRows = useMemo<ActivityRow[]>(() => {\n\t\tconst rows: ActivityRow[] = [];\n\n\t\tfor (let index = 0; index < group.items.length; index++) {\n\t\t\tconst item = group.items[index];\n\t\t\tif (!item) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (item.type === \"event\") {\n\t\t\t\tconst eventPart = extractEventPart(item);\n\t\t\t\tif (!eventPart) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\trows.push({\n\t\t\t\t\ttype: \"event\",\n\t\t\t\t\tkey: item.id ?? `activity-event-${item.createdAt}-${index}`,\n\t\t\t\t\titem,\n\t\t\t\t\tevent: eventPart,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (item.type === \"tool\") {\n\t\t\t\tconst toolName = getToolNameFromTimelineItem(item);\n\t\t\t\tif (!toolName) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst toolDefinition = tools?.[toolName];\n\t\t\t\tif (!toolDefinition) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\trows.push({\n\t\t\t\t\ttype: \"tool\",\n\t\t\t\t\tkey: item.id ?? `activity-tool-${item.createdAt}-${index}`,\n\t\t\t\t\titem,\n\t\t\t\t\tToolComponent: toolDefinition.component,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn rows;\n\t}, [group.items, tools]);\n\n\tif (activityRows.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst humanAgent = availableHumanAgents.find(\n\t\t(agent) => agent.id === group.senderId\n\t);\n\tconst aiAgent = availableAIAgents.find(\n\t\t(agent) => agent.id === group.senderId\n\t);\n\n\treturn (\n\t\t<PrimitiveTimelineItemGroup\n\t\t\titems={group.items}\n\t\t\tviewerId={currentVisitorId}\n\t\t\tviewerType={SenderType.VISITOR}\n\t\t>\n\t\t\t{({ isAI, isTeamMember }) => (\n\t\t\t\t<div className=\"flex w-full flex-row gap-2\">\n\t\t\t\t\t<TimelineItemGroupAvatar className=\"flex shrink-0 flex-col justify-start\">\n\t\t\t\t\t\t{isAI ? (\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tclassName=\"size-6\"\n\t\t\t\t\t\t\t\timage={aiAgent?.image}\n\t\t\t\t\t\t\t\tisAI\n\t\t\t\t\t\t\t\tname={aiAgent?.name || \"AI Assistant\"}\n\t\t\t\t\t\t\t\tshowBackground={!!aiAgent?.image}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tclassName=\"size-6\"\n\t\t\t\t\t\t\t\timage={humanAgent?.image}\n\t\t\t\t\t\t\t\tname={isTeamMember ? humanAgent?.name || \"Support\" : \"Visitor\"}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</TimelineItemGroupAvatar>\n\n\t\t\t\t\t<TimelineItemGroupContent className=\"flex min-w-0 flex-1 flex-col gap-1\">\n\t\t\t\t\t\t<div className=\"flex w-full min-w-0 flex-col gap-2\">\n\t\t\t\t\t\t\t{activityRows.map((row) => {\n\t\t\t\t\t\t\t\tif (row.type === \"event\") {\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<ConversationEvent\n\t\t\t\t\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-full\"\n\t\t\t\t\t\t\t\t\t\t\tcompact\n\t\t\t\t\t\t\t\t\t\t\tcreatedAt={row.item.createdAt}\n\t\t\t\t\t\t\t\t\t\t\tevent={row.event}\n\t\t\t\t\t\t\t\t\t\t\tkey={row.key}\n\t\t\t\t\t\t\t\t\t\t\tshowAvatar={false}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tconst ToolComponent = row.ToolComponent;\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div className=\"w-full\" key={row.key}>\n\t\t\t\t\t\t\t\t\t\t<ToolComponent\n\t\t\t\t\t\t\t\t\t\t\tconversationId={conversationId}\n\t\t\t\t\t\t\t\t\t\t\titem={row.item}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</TimelineItemGroupContent>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</PrimitiveTimelineItemGroup>\n\t);\n};\n\nTimelineActivityGroup.displayName = \"TimelineActivityGroup\";\n"],"mappings":";;;;;;;;AAqDA,SAAS,iBAAiB,MAA8C;AACvE,KAAI,KAAK,SAAS,QACjB,QAAO;AAOR,QAJkB,KAAK,MAAM,MAC3B,SAAoC,KAAK,SAAS,QACnD,IAEmB;;AAGrB,SAAS,4BAA4B,MAAmC;AACvE,KAAI,KAAK,KACR,QAAO,KAAK;AAGb,MAAK,MAAM,QAAQ,KAAK,MACvB,KACC,OAAO,SAAS,YAChB,SAAS,QACT,UAAU,QACV,cAAc,QACd,OAAO,KAAK,SAAS,YACrB,KAAK,KAAK,WAAW,QAAQ,IAC7B,OAAO,KAAK,aAAa,SAEzB,QAAO,KAAK;AAId,QAAO;;AAGR,MAAaA,yBAA+D,EAC3E,OACA,gBACA,mBACA,sBACA,kBACA,YACK;CACL,MAAM,eAAe,cAA6B;EACjD,MAAMC,OAAsB,EAAE;AAE9B,OAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,MAAM,QAAQ,SAAS;GACxD,MAAM,OAAO,MAAM,MAAM;AACzB,OAAI,CAAC,KACJ;AAGD,OAAI,KAAK,SAAS,SAAS;IAC1B,MAAM,YAAY,iBAAiB,KAAK;AACxC,QAAI,CAAC,UACJ;AAGD,SAAK,KAAK;KACT,MAAM;KACN,KAAK,KAAK,MAAM,kBAAkB,KAAK,UAAU,GAAG;KACpD;KACA,OAAO;KACP,CAAC;AACF;;AAGD,OAAI,KAAK,SAAS,QAAQ;IACzB,MAAM,WAAW,4BAA4B,KAAK;AAClD,QAAI,CAAC,SACJ;IAGD,MAAM,iBAAiB,QAAQ;AAC/B,QAAI,CAAC,eACJ;AAGD,SAAK,KAAK;KACT,MAAM;KACN,KAAK,KAAK,MAAM,iBAAiB,KAAK,UAAU,GAAG;KACnD;KACA,eAAe,eAAe;KAC9B,CAAC;;;AAIJ,SAAO;IACL,CAAC,MAAM,OAAO,MAAM,CAAC;AAExB,KAAI,aAAa,WAAW,EAC3B,QAAO;CAGR,MAAM,aAAa,qBAAqB,MACtC,UAAU,MAAM,OAAO,MAAM,SAC9B;CACD,MAAM,UAAU,kBAAkB,MAChC,UAAU,MAAM,OAAO,MAAM,SAC9B;AAED,QACC,oBAACC;EACA,OAAO,MAAM;EACb,UAAU;EACV,YAAY,WAAW;aAErB,EAAE,MAAM,mBACT,qBAAC;GAAI,WAAU;cACd,oBAAC;IAAwB,WAAU;cACjC,OACA,oBAAC;KACA,WAAU;KACV,OAAO,SAAS;KAChB;KACA,MAAM,SAAS,QAAQ;KACvB,gBAAgB,CAAC,CAAC,SAAS;MAC1B,GAEF,oBAAC;KACA,WAAU;KACV,OAAO,YAAY;KACnB,MAAM,eAAe,YAAY,QAAQ,YAAY;MACpD;KAEsB,EAE1B,oBAAC;IAAyB,WAAU;cACnC,oBAAC;KAAI,WAAU;eACb,aAAa,KAAK,QAAQ;AAC1B,UAAI,IAAI,SAAS,QAChB,QACC,oBAAC;OACmB;OACG;OACtB,WAAU;OACV;OACA,WAAW,IAAI,KAAK;OACpB,OAAO,IAAI;OAEX,YAAY;SADP,IAAI,IAER;MAIJ,MAAM,gBAAgB,IAAI;AAC1B,aACC,oBAAC;OAAI,WAAU;iBACd,oBAAC;QACgB;QAChB,MAAM,IAAI;SACT;SAJ0B,IAAI,IAK3B;OAEN;MACG;KACoB;IACtB;GAEqB;;AAI/B,sBAAsB,cAAc"}
@@ -0,0 +1,14 @@
1
+ import { TimelineCodeBlockProps as TimelineCodeBlockProps$1 } from "../../primitives/timeline-code-block.js";
2
+ import React from "react";
3
+
4
+ //#region src/support/components/timeline-code-block.d.ts
5
+ type TimelineCodeBlockProps = TimelineCodeBlockProps$1;
6
+ declare function TimelineCodeBlock({
7
+ code,
8
+ language,
9
+ fileName,
10
+ className
11
+ }: TimelineCodeBlockProps): React.ReactElement;
12
+ //#endregion
13
+ export { TimelineCodeBlock, TimelineCodeBlockProps };
14
+ //# sourceMappingURL=timeline-code-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-code-block.d.ts","names":[],"sources":["../../../src/support/components/timeline-code-block.tsx"],"sourcesContent":[],"mappings":";;;;KAOY,sBAAA,GAAyB;iBAErB,iBAAA;;;;;GAKb,yBAAyB,KAAA,CAAM"}
@@ -0,0 +1,44 @@
1
+ import { TimelineCodeBlock as TimelineCodeBlock$1 } from "../../primitives/timeline-code-block.js";
2
+ import { CoButton } from "./button.js";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+
5
+ //#region src/support/components/timeline-code-block.tsx
6
+ function TimelineCodeBlock({ code, language, fileName, className }) {
7
+ return /* @__PURE__ */ jsx(TimelineCodeBlock$1, {
8
+ className: `mt-1 w-full overflow-hidden rounded border border-co-border bg-co-background-200 ${className ?? ""}`.trim(),
9
+ code,
10
+ fileName,
11
+ language,
12
+ children: ({ code: content, codeClassName, fileName: resolvedFileName, languageLabel, hasCopied, onCopy }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
13
+ className: "flex items-center justify-between gap-2 px-2 py-1.5",
14
+ children: [/* @__PURE__ */ jsxs("div", {
15
+ className: "flex min-w-0 items-center gap-2",
16
+ children: [resolvedFileName ? /* @__PURE__ */ jsx("span", {
17
+ className: "truncate font-medium text-xs",
18
+ children: resolvedFileName
19
+ }) : null, /* @__PURE__ */ jsx("span", {
20
+ className: "rounded border border-co-border/70 bg-co-background-500 px-1.5 py-0.5 font-medium text-[10px] uppercase tracking-wide",
21
+ children: languageLabel
22
+ })]
23
+ }), /* @__PURE__ */ jsx(CoButton, {
24
+ onClick: () => {
25
+ onCopy();
26
+ },
27
+ size: "small",
28
+ type: "button",
29
+ variant: "ghost",
30
+ children: hasCopied ? "Copied" : "Copy"
31
+ })]
32
+ }), /* @__PURE__ */ jsx("pre", {
33
+ className: "no-scrollbar overflow-x-auto p-3 text-xs leading-relaxed",
34
+ children: /* @__PURE__ */ jsx("code", {
35
+ className: codeClassName,
36
+ children: content
37
+ })
38
+ })] })
39
+ });
40
+ }
41
+
42
+ //#endregion
43
+ export { TimelineCodeBlock };
44
+ //# sourceMappingURL=timeline-code-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-code-block.js","names":["PrimitiveTimelineCodeBlock"],"sources":["../../../src/support/components/timeline-code-block.tsx"],"sourcesContent":["import type React from \"react\";\nimport {\n\tTimelineCodeBlock as PrimitiveTimelineCodeBlock,\n\ttype TimelineCodeBlockProps as PrimitiveTimelineCodeBlockProps,\n} from \"../../primitives/timeline-code-block\";\nimport { CoButton } from \"./button\";\n\nexport type TimelineCodeBlockProps = PrimitiveTimelineCodeBlockProps;\n\nexport function TimelineCodeBlock({\n\tcode,\n\tlanguage,\n\tfileName,\n\tclassName,\n}: TimelineCodeBlockProps): React.ReactElement {\n\treturn (\n\t\t<PrimitiveTimelineCodeBlock\n\t\t\tclassName={`mt-1 w-full overflow-hidden rounded border border-co-border bg-co-background-200 ${className ?? \"\"}`.trim()}\n\t\t\tcode={code}\n\t\t\tfileName={fileName}\n\t\t\tlanguage={language}\n\t\t>\n\t\t\t{({\n\t\t\t\tcode: content,\n\t\t\t\tcodeClassName,\n\t\t\t\tfileName: resolvedFileName,\n\t\t\t\tlanguageLabel,\n\t\t\t\thasCopied,\n\t\t\t\tonCopy,\n\t\t\t}) => (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"flex items-center justify-between gap-2 px-2 py-1.5\">\n\t\t\t\t\t\t<div className=\"flex min-w-0 items-center gap-2\">\n\t\t\t\t\t\t\t{resolvedFileName ? (\n\t\t\t\t\t\t\t\t<span className=\"truncate font-medium text-xs\">\n\t\t\t\t\t\t\t\t\t{resolvedFileName}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t<span className=\"rounded border border-co-border/70 bg-co-background-500 px-1.5 py-0.5 font-medium text-[10px] uppercase tracking-wide\">\n\t\t\t\t\t\t\t\t{languageLabel}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<CoButton\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tvoid onCopy();\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{hasCopied ? \"Copied\" : \"Copy\"}\n\t\t\t\t\t\t</CoButton>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<pre className=\"no-scrollbar overflow-x-auto p-3 text-xs leading-relaxed\">\n\t\t\t\t\t\t<code className={codeClassName}>{content}</code>\n\t\t\t\t\t</pre>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</PrimitiveTimelineCodeBlock>\n\t);\n}\n"],"mappings":";;;;;AASA,SAAgB,kBAAkB,EACjC,MACA,UACA,UACA,aAC8C;AAC9C,QACC,oBAACA;EACA,WAAW,oFAAoF,aAAa,KAAK,MAAM;EACjH;EACI;EACA;aAER,EACD,MAAM,SACN,eACA,UAAU,kBACV,eACA,WACA,aAEA,4CACC,qBAAC;GAAI,WAAU;cACd,qBAAC;IAAI,WAAU;eACb,mBACA,oBAAC;KAAK,WAAU;eACd;MACK,GACJ,MACJ,oBAAC;KAAK,WAAU;eACd;MACK;KACF,EAEN,oBAAC;IACA,eAAe;AACd,KAAK,QAAQ;;IAEd,MAAK;IACL,MAAK;IACL,SAAQ;cAEP,YAAY,WAAW;KACd;IACN,EAEN,oBAAC;GAAI,WAAU;aACd,oBAAC;IAAK,WAAW;cAAgB;KAAe;IAC3C,IACJ;GAEwB"}
@@ -0,0 +1,12 @@
1
+ import { TimelineCommandBlockProps as TimelineCommandBlockProps$1 } from "../../primitives/timeline-command-block.js";
2
+ import React from "react";
3
+
4
+ //#region src/support/components/timeline-command-block.d.ts
5
+ type TimelineCommandBlockProps = TimelineCommandBlockProps$1;
6
+ declare function TimelineCommandBlock({
7
+ commands,
8
+ className
9
+ }: TimelineCommandBlockProps): React.ReactElement;
10
+ //#endregion
11
+ export { TimelineCommandBlock, TimelineCommandBlockProps };
12
+ //# sourceMappingURL=timeline-command-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-command-block.d.ts","names":[],"sources":["../../../src/support/components/timeline-command-block.tsx"],"sourcesContent":[],"mappings":";;;;KAOY,yBAAA,GAA4B;iBAExB,oBAAA;;;GAGb,4BAA4B,KAAA,CAAM"}
@@ -0,0 +1,42 @@
1
+ import { TimelineCommandBlock as TimelineCommandBlock$1 } from "../../primitives/timeline-command-block.js";
2
+ import { CoButton } from "./button.js";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+
5
+ //#region src/support/components/timeline-command-block.tsx
6
+ function TimelineCommandBlock({ commands, className }) {
7
+ return /* @__PURE__ */ jsx(TimelineCommandBlock$1, {
8
+ className: `mt-1 w-full overflow-hidden rounded border border-co-border bg-co-background-200 ${className ?? ""}`.trim(),
9
+ commands,
10
+ children: ({ activeCommand, activePackageManager, hasCopied, onCopy, packageManagers, setPackageManager }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
11
+ className: "flex items-center justify-between gap-2 px-2 py-1.5",
12
+ children: [/* @__PURE__ */ jsx("div", {
13
+ className: "flex items-center gap-1",
14
+ children: packageManagers.map((packageManager) => /* @__PURE__ */ jsx(CoButton, {
15
+ onClick: () => setPackageManager(packageManager),
16
+ size: "small",
17
+ type: "button",
18
+ variant: activePackageManager === packageManager ? "outline" : "ghost",
19
+ children: packageManager
20
+ }, packageManager))
21
+ }), /* @__PURE__ */ jsx(CoButton, {
22
+ onClick: () => {
23
+ onCopy();
24
+ },
25
+ size: "small",
26
+ type: "button",
27
+ variant: "ghost",
28
+ children: hasCopied ? "Copied" : "Copy"
29
+ })]
30
+ }), /* @__PURE__ */ jsx("pre", {
31
+ className: "no-scrollbar overflow-x-auto p-3 text-xs leading-relaxed",
32
+ children: /* @__PURE__ */ jsx("code", {
33
+ className: "language-bash",
34
+ children: activeCommand
35
+ })
36
+ })] })
37
+ });
38
+ }
39
+
40
+ //#endregion
41
+ export { TimelineCommandBlock };
42
+ //# sourceMappingURL=timeline-command-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-command-block.js","names":["PrimitiveTimelineCommandBlock"],"sources":["../../../src/support/components/timeline-command-block.tsx"],"sourcesContent":["import type React from \"react\";\nimport {\n\tTimelineCommandBlock as PrimitiveTimelineCommandBlock,\n\ttype TimelineCommandBlockProps as PrimitiveTimelineCommandBlockProps,\n} from \"../../primitives/timeline-command-block\";\nimport { CoButton } from \"./button\";\n\nexport type TimelineCommandBlockProps = PrimitiveTimelineCommandBlockProps;\n\nexport function TimelineCommandBlock({\n\tcommands,\n\tclassName,\n}: TimelineCommandBlockProps): React.ReactElement {\n\treturn (\n\t\t<PrimitiveTimelineCommandBlock\n\t\t\tclassName={`mt-1 w-full overflow-hidden rounded border border-co-border bg-co-background-200 ${className ?? \"\"}`.trim()}\n\t\t\tcommands={commands}\n\t\t>\n\t\t\t{({\n\t\t\t\tactiveCommand,\n\t\t\t\tactivePackageManager,\n\t\t\t\thasCopied,\n\t\t\t\tonCopy,\n\t\t\t\tpackageManagers,\n\t\t\t\tsetPackageManager,\n\t\t\t}) => (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"flex items-center justify-between gap-2 px-2 py-1.5\">\n\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t{packageManagers.map((packageManager) => (\n\t\t\t\t\t\t\t\t<CoButton\n\t\t\t\t\t\t\t\t\tkey={packageManager}\n\t\t\t\t\t\t\t\t\tonClick={() => setPackageManager(packageManager)}\n\t\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant={\n\t\t\t\t\t\t\t\t\t\tactivePackageManager === packageManager\n\t\t\t\t\t\t\t\t\t\t\t? \"outline\"\n\t\t\t\t\t\t\t\t\t\t\t: \"ghost\"\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\t\t{packageManager}\n\t\t\t\t\t\t\t\t</CoButton>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<CoButton\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tvoid onCopy();\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{hasCopied ? \"Copied\" : \"Copy\"}\n\t\t\t\t\t\t</CoButton>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<pre className=\"no-scrollbar overflow-x-auto p-3 text-xs leading-relaxed\">\n\t\t\t\t\t\t<code className=\"language-bash\">{activeCommand}</code>\n\t\t\t\t\t</pre>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</PrimitiveTimelineCommandBlock>\n\t);\n}\n"],"mappings":";;;;;AASA,SAAgB,qBAAqB,EACpC,UACA,aACiD;AACjD,QACC,oBAACA;EACA,WAAW,oFAAoF,aAAa,KAAK,MAAM;EAC7G;aAER,EACD,eACA,sBACA,WACA,QACA,iBACA,wBAEA,4CACC,qBAAC;GAAI,WAAU;cACd,oBAAC;IAAI,WAAU;cACb,gBAAgB,KAAK,mBACrB,oBAAC;KAEA,eAAe,kBAAkB,eAAe;KAChD,MAAK;KACL,MAAK;KACL,SACC,yBAAyB,iBACtB,YACA;eAGH;OAVI,eAWK,CACV;KACG,EAEN,oBAAC;IACA,eAAe;AACd,KAAK,QAAQ;;IAEd,MAAK;IACL,MAAK;IACL,SAAQ;cAEP,YAAY,WAAW;KACd;IACN,EAEN,oBAAC;GAAI,WAAU;aACd,oBAAC;IAAK,WAAU;cAAiB;KAAqB;IACjD,IACJ;GAE2B"}
@@ -7,6 +7,7 @@ type TimelineMessageItemProps = {
7
7
  isLast?: boolean;
8
8
  isSentByViewer?: boolean;
9
9
  };
10
+ declare function getSupportMessageWidthClasses(text: string | null | undefined): string;
10
11
  /**
11
12
  * Message bubble renderer that adapts layout depending on whether the visitor
12
13
  * or an agent sent the message.
@@ -17,5 +18,5 @@ declare function TimelineMessageItem({
17
18
  isSentByViewer
18
19
  }: TimelineMessageItemProps): React.ReactElement;
19
20
  //#endregion
20
- export { TimelineMessageItem, TimelineMessageItemProps };
21
+ export { TimelineMessageItem, TimelineMessageItemProps, getSupportMessageWidthClasses };
21
22
  //# sourceMappingURL=timeline-message-item.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-message-item.d.ts","names":[],"sources":["../../../src/support/components/timeline-message-item.tsx"],"sourcesContent":[],"mappings":";;;;KAkBY,wBAAA;QACL;EADK,MAAA,CAAA,EAAA,OAAA;EAUI,cAAA,CAAA,EAAA,OAAmB;CAClC;;;;;AAG+C,iBAJhC,mBAAA,CAIgC;EAAA,IAAA;EAAA,MAAA;EAAA;AAAA,CAAA,EAA7C,wBAA6C,CAAA,EAAlB,KAAA,CAAM,YAAY"}
1
+ {"version":3,"file":"timeline-message-item.d.ts","names":[],"sources":["../../../src/support/components/timeline-message-item.tsx"],"sourcesContent":[],"mappings":";;;;KAsBY,wBAAA;QACL;EADK,MAAA,CAAA,EAAA,OAAA;EAMI,cAAA,CAAA,EAAA,OAAA;AAYhB,CAAA;AACC,iBAbe,6BAAA,CAaf,IAAA,EAAA,MAAA,GAAA,IAAA,GAAA,SAAA,CAAA,EAAA,MAAA;;;;;AAG+C,iBAJhC,mBAAA,CAIgC;EAAA,IAAA;EAAA,MAAA;EAAA;AAAA,CAAA,EAA7C,wBAA6C,CAAA,EAAlB,KAAA,CAAM,YAAY"}
@@ -1,14 +1,20 @@
1
1
  import { cn } from "../utils/index.js";
2
2
  import { TimelineItem, TimelineItemContent, TimelineItemTimestamp } from "../../primitives/timeline-item.js";
3
3
  import { extractFileParts, extractImageParts } from "../../primitives/timeline-item-attachments.js";
4
+ import { hasExpandedTimelineContent } from "../../primitives/timeline-message-layout.js";
4
5
  import icons_default from "./icons.js";
5
6
  import { useSupportText } from "../text/index.js";
6
7
  import { ImageLightbox } from "./image-lightbox.js";
7
- import { useState } from "react";
8
+ import { TimelineCodeBlock } from "./timeline-code-block.js";
9
+ import { TimelineCommandBlock } from "./timeline-command-block.js";
10
+ import { useMemo, useState } from "react";
8
11
  import { formatFileSize } from "@cossistant/core";
9
12
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
13
 
11
14
  //#region src/support/components/timeline-message-item.tsx
15
+ function getSupportMessageWidthClasses(text) {
16
+ return hasExpandedTimelineContent(text) ? "w-full max-w-full" : "max-w-[300px]";
17
+ }
12
18
  /**
13
19
  * Message bubble renderer that adapts layout depending on whether the visitor
14
20
  * or an agent sent the message.
@@ -21,6 +27,19 @@ function TimelineMessageItem({ item, isLast = false, isSentByViewer = false }) {
21
27
  const files = extractFileParts(item.parts);
22
28
  const hasAttachments = images.length > 0 || files.length > 0;
23
29
  const hasText = item.text && item.text.trim().length > 0;
30
+ const messageWidthClassName = getSupportMessageWidthClasses(item.text);
31
+ const markdownRenderers = useMemo(() => ({
32
+ codeBlock: ({ code, fileName, language }) => /* @__PURE__ */ jsx(TimelineCodeBlock, {
33
+ code,
34
+ fileName,
35
+ language
36
+ }),
37
+ commandBlock: ({ commands }) => /* @__PURE__ */ jsx(TimelineCommandBlock, { commands }),
38
+ inlineCode: ({ code }) => /* @__PURE__ */ jsx("code", {
39
+ className: "rounded bg-co-background-300 px-1 py-0.5 text-xs",
40
+ children: code
41
+ })
42
+ }), []);
24
43
  const openLightbox = (index) => {
25
44
  setLightboxIndex(index);
26
45
  setLightboxOpen(true);
@@ -35,12 +54,13 @@ function TimelineMessageItem({ item, isLast = false, isSentByViewer = false }) {
35
54
  className: cn("flex w-full min-w-0 flex-1 flex-col gap-1", isSentByViewerFinal && "items-end"),
36
55
  children: [
37
56
  hasText && /* @__PURE__ */ jsx(TimelineItemContent, {
38
- className: cn("block min-w-0 max-w-[300px] break-words rounded-lg px-3.5 py-2.5 text-sm", {
57
+ className: cn("block min-w-0 break-words rounded-lg px-3.5 py-2.5 text-sm", messageWidthClassName, {
39
58
  "bg-co-background-300 text-co-foreground dark:bg-co-background-600": !isSentByViewerFinal,
40
59
  "bg-co-primary text-co-primary-foreground": isSentByViewerFinal,
41
60
  "rounded-br-sm": isLast && isSentByViewerFinal && !hasAttachments,
42
61
  "rounded-bl-sm": isLast && !isSentByViewerFinal && !hasAttachments
43
62
  }),
63
+ markdownRenderers,
44
64
  renderMarkdown: true,
45
65
  text: item.text
46
66
  }),
@@ -106,5 +126,5 @@ function TimelineMessageItem({ item, isLast = false, isSentByViewer = false }) {
106
126
  }
107
127
 
108
128
  //#endregion
109
- export { TimelineMessageItem };
129
+ export { TimelineMessageItem, getSupportMessageWidthClasses };
110
130
  //# sourceMappingURL=timeline-message-item.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-message-item.js","names":["PrimitiveTimelineItem","Icon"],"sources":["../../../src/support/components/timeline-message-item.tsx"],"sourcesContent":["import { formatFileSize } from \"@cossistant/core\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useState } from \"react\";\nimport {\n\tTimelineItem as PrimitiveTimelineItem,\n\tTimelineItemContent,\n\tTimelineItemTimestamp,\n} from \"../../primitives/timeline-item\";\nimport {\n\textractFileParts,\n\textractImageParts,\n} from \"../../primitives/timeline-item-attachments\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { ImageLightbox } from \"./image-lightbox\";\n\nexport type TimelineMessageItemProps = {\n\titem: TimelineItem;\n\tisLast?: boolean;\n\tisSentByViewer?: boolean;\n};\n\n/**\n * Message bubble renderer that adapts layout depending on whether the visitor\n * or an agent sent the message.\n */\nexport function TimelineMessageItem({\n\titem,\n\tisLast = false,\n\tisSentByViewer = false,\n}: TimelineMessageItemProps): React.ReactElement {\n\tconst text = useSupportText();\n\tconst [lightboxOpen, setLightboxOpen] = useState(false);\n\tconst [lightboxIndex, setLightboxIndex] = useState(0);\n\n\t// Extract image and file parts\n\tconst images = extractImageParts(item.parts);\n\tconst files = extractFileParts(item.parts);\n\tconst hasAttachments = images.length > 0 || files.length > 0;\n\tconst hasText = item.text && item.text.trim().length > 0;\n\n\tconst openLightbox = (index: number) => {\n\t\tsetLightboxIndex(index);\n\t\tsetLightboxOpen(true);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<PrimitiveTimelineItem item={item}>\n\t\t\t\t{({ isAI, timestamp }) => {\n\t\t\t\t\t// isSentByViewer defaults to false, meaning messages are treated as received\n\t\t\t\t\t// (left side with background) unless explicitly marked as sent by viewer\n\t\t\t\t\tconst isSentByViewerFinal = isSentByViewer;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full gap-2\",\n\t\t\t\t\t\t\t\tisSentByViewerFinal && \"flex-row-reverse\",\n\t\t\t\t\t\t\t\t!isSentByViewerFinal && \"flex-row\"\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"flex w-full min-w-0 flex-1 flex-col gap-1\",\n\t\t\t\t\t\t\t\t\tisSentByViewerFinal && \"items-end\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{/* Text content */}\n\t\t\t\t\t\t\t\t{hasText && (\n\t\t\t\t\t\t\t\t\t<TimelineItemContent\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"block min-w-0 max-w-[300px] break-words rounded-lg px-3.5 py-2.5 text-sm\",\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-background-300 text-co-foreground dark:bg-co-background-600\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t!isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-primary text-co-primary-foreground\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\"rounded-br-sm\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisLast && isSentByViewerFinal && !hasAttachments,\n\t\t\t\t\t\t\t\t\t\t\t\t\"rounded-bl-sm\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisLast && !isSentByViewerFinal && !hasAttachments,\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\trenderMarkdown\n\t\t\t\t\t\t\t\t\t\ttext={item.text}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{/* Image attachments */}\n\t\t\t\t\t\t\t\t{images.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"flex flex-wrap gap-2\",\n\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal && \"justify-end\"\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{images.map((image, index) => (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"group relative overflow-hidden rounded-lg focus:outline-none focus:ring-2 focus:ring-co-primary/50\"\n\t\t\t\t\t\t\t\t\t\t\t\tkey={image.url}\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => openLightbox(index)}\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{/* biome-ignore lint/performance/noImgElement: React package, not Next.js specific */}\n\t\t\t\t\t\t\t\t\t\t\t\t{/* biome-ignore lint/nursery/useImageSize: Dynamic image dimensions not known at render time */}\n\t\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\t\talt={image.filename || `Image ${index + 1}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"max-h-[150px] max-w-[200px] cursor-pointer rounded-lg object-cover transition-transform group-hover:scale-105\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsrc={image.url}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{/* File attachments */}\n\t\t\t\t\t\t\t\t{files.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t\t\t\t\t{files.map((file) => (\n\t\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"flex items-center gap-2 rounded-lg px-3 py-2 text-xs transition-colors\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-background-300 text-co-foreground hover:bg-co-background-400 dark:bg-co-background-600 dark:hover:bg-co-background-500\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t!isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-primary/80 text-co-primary-foreground hover:bg-co-primary\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\tdownload={file.filename}\n\t\t\t\t\t\t\t\t\t\t\t\thref={file.url}\n\t\t\t\t\t\t\t\t\t\t\t\tkey={file.url}\n\t\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4 shrink-0\" name=\"file\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"flex-1 truncate font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{file.filename || \"Download file\"}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t{file.size && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground opacity-70\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{isLast && (\n\t\t\t\t\t\t\t\t\t<TimelineItemTimestamp\n\t\t\t\t\t\t\t\t\t\tclassName=\"px-1 text-co-muted-foreground text-xs\"\n\t\t\t\t\t\t\t\t\t\ttimestamp={timestamp}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{() => (\n\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t{timestamp.toLocaleTimeString([], {\n\t\t\t\t\t\t\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t{isAI &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t` ${text(\"component.message.timestamp.aiIndicator\")}`}\n\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</TimelineItemTimestamp>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}}\n\t\t\t</PrimitiveTimelineItem>\n\n\t\t\t{/* Lightbox for images */}\n\t\t\t{images.length > 0 && (\n\t\t\t\t<ImageLightbox\n\t\t\t\t\timages={images}\n\t\t\t\t\tinitialIndex={lightboxIndex}\n\t\t\t\t\tisOpen={lightboxOpen}\n\t\t\t\t\tonClose={() => setLightboxOpen(false)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;AA4BA,SAAgB,oBAAoB,EACnC,MACA,SAAS,OACT,iBAAiB,SAC+B;CAChD,MAAM,OAAO,gBAAgB;CAC7B,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;CACvD,MAAM,CAAC,eAAe,oBAAoB,SAAS,EAAE;CAGrD,MAAM,SAAS,kBAAkB,KAAK,MAAM;CAC5C,MAAM,QAAQ,iBAAiB,KAAK,MAAM;CAC1C,MAAM,iBAAiB,OAAO,SAAS,KAAK,MAAM,SAAS;CAC3D,MAAM,UAAU,KAAK,QAAQ,KAAK,KAAK,MAAM,CAAC,SAAS;CAEvD,MAAM,gBAAgB,UAAkB;AACvC,mBAAiB,MAAM;AACvB,kBAAgB,KAAK;;AAGtB,QACC,4CACC,oBAACA;EAA4B;aAC1B,EAAE,MAAM,gBAAgB;GAGzB,MAAM,sBAAsB;AAE5B,UACC,oBAAC;IACA,WAAW,GACV,qBACA,uBAAuB,oBACvB,CAAC,uBAAuB,WACxB;cAED,qBAAC;KACA,WAAW,GACV,6CACA,uBAAuB,YACvB;;MAGA,WACA,oBAAC;OACA,WAAW,GACV,4EACA;QACC,qEACC,CAAC;QACF,4CACC;QACD,iBACC,UAAU,uBAAuB,CAAC;QACnC,iBACC,UAAU,CAAC,uBAAuB,CAAC;QACpC,CACD;OACD;OACA,MAAM,KAAK;QACV;MAIF,OAAO,SAAS,KAChB,oBAAC;OACA,WAAW,GACV,wBACA,uBAAuB,cACvB;iBAEA,OAAO,KAAK,OAAO,UACnB,oBAAC;QACA,WAAU;QAEV,eAAe,aAAa,MAAM;QAClC,MAAK;kBAIL,oBAAC;SACA,KAAK,MAAM,YAAY,SAAS,QAAQ;SACxC,WAAU;SACV,SAAQ;SACR,KAAK,MAAM;UACV;UAXG,MAAM,IAYH,CACR;QACG;MAIN,MAAM,SAAS,KACf,oBAAC;OAAI,WAAU;iBACb,MAAM,KAAK,SACX,qBAAC;QACA,WAAW,GACV,0EACA;SACC,gIACC,CAAC;SACF,mEACC;SACD,CACD;QACD,UAAU,KAAK;QACf,MAAM,KAAK;QAEX,KAAI;QACJ,QAAO;;SAEP,oBAACC;UAAK,WAAU;UAAmB,MAAK;WAAS;SACjD,oBAAC;UAAK,WAAU;oBACd,KAAK,YAAY;WACZ;SACN,KAAK,QACL,oBAAC;UAAK,WAAU;oBACd,eAAe,KAAK,KAAK;WACpB;;UAXH,KAAK,IAaP,CACH;QACG;MAGN,UACA,oBAAC;OACA,WAAU;OACC;uBAGV,4CACE,UAAU,mBAAmB,EAAE,EAAE;QACjC,MAAM;QACN,QAAQ;QACR,CAAC,EACD,QACA,IAAI,KAAK,0CAA0C,MAClD;QAEmB;;MAEpB;KACD;;GAGe,EAGvB,OAAO,SAAS,KAChB,oBAAC;EACQ;EACR,cAAc;EACd,QAAQ;EACR,eAAe,gBAAgB,MAAM;GACpC,IAED"}
1
+ {"version":3,"file":"timeline-message-item.js","names":["PrimitiveTimelineItem","Icon"],"sources":["../../../src/support/components/timeline-message-item.tsx"],"sourcesContent":["import { formatFileSize } from \"@cossistant/core\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport {\n\tTimelineItem as PrimitiveTimelineItem,\n\tTimelineItemContent,\n\ttype TimelineItemContentMarkdownRenderers,\n\tTimelineItemTimestamp,\n} from \"../../primitives/timeline-item\";\nimport {\n\textractFileParts,\n\textractImageParts,\n} from \"../../primitives/timeline-item-attachments\";\nimport { hasExpandedTimelineContent } from \"../../primitives/timeline-message-layout\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { ImageLightbox } from \"./image-lightbox\";\nimport { TimelineCodeBlock } from \"./timeline-code-block\";\nimport { TimelineCommandBlock } from \"./timeline-command-block\";\n\nexport type TimelineMessageItemProps = {\n\titem: TimelineItem;\n\tisLast?: boolean;\n\tisSentByViewer?: boolean;\n};\n\nexport function getSupportMessageWidthClasses(\n\ttext: string | null | undefined\n): string {\n\treturn hasExpandedTimelineContent(text)\n\t\t? \"w-full max-w-full\"\n\t\t: \"max-w-[300px]\";\n}\n\n/**\n * Message bubble renderer that adapts layout depending on whether the visitor\n * or an agent sent the message.\n */\nexport function TimelineMessageItem({\n\titem,\n\tisLast = false,\n\tisSentByViewer = false,\n}: TimelineMessageItemProps): React.ReactElement {\n\tconst text = useSupportText();\n\tconst [lightboxOpen, setLightboxOpen] = useState(false);\n\tconst [lightboxIndex, setLightboxIndex] = useState(0);\n\n\t// Extract image and file parts\n\tconst images = extractImageParts(item.parts);\n\tconst files = extractFileParts(item.parts);\n\tconst hasAttachments = images.length > 0 || files.length > 0;\n\tconst hasText = item.text && item.text.trim().length > 0;\n\tconst messageWidthClassName = getSupportMessageWidthClasses(item.text);\n\tconst markdownRenderers = useMemo<TimelineItemContentMarkdownRenderers>(\n\t\t() => ({\n\t\t\tcodeBlock: ({ code, fileName, language }) => (\n\t\t\t\t<TimelineCodeBlock\n\t\t\t\t\tcode={code}\n\t\t\t\t\tfileName={fileName}\n\t\t\t\t\tlanguage={language}\n\t\t\t\t/>\n\t\t\t),\n\t\t\tcommandBlock: ({ commands }) => (\n\t\t\t\t<TimelineCommandBlock commands={commands} />\n\t\t\t),\n\t\t\tinlineCode: ({ code }) => (\n\t\t\t\t<code className=\"rounded bg-co-background-300 px-1 py-0.5 text-xs\">\n\t\t\t\t\t{code}\n\t\t\t\t</code>\n\t\t\t),\n\t\t}),\n\t\t[]\n\t);\n\n\tconst openLightbox = (index: number) => {\n\t\tsetLightboxIndex(index);\n\t\tsetLightboxOpen(true);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<PrimitiveTimelineItem item={item}>\n\t\t\t\t{({ isAI, timestamp }) => {\n\t\t\t\t\t// isSentByViewer defaults to false, meaning messages are treated as received\n\t\t\t\t\t// (left side with background) unless explicitly marked as sent by viewer\n\t\t\t\t\tconst isSentByViewerFinal = isSentByViewer;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full gap-2\",\n\t\t\t\t\t\t\t\tisSentByViewerFinal && \"flex-row-reverse\",\n\t\t\t\t\t\t\t\t!isSentByViewerFinal && \"flex-row\"\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"flex w-full min-w-0 flex-1 flex-col gap-1\",\n\t\t\t\t\t\t\t\t\tisSentByViewerFinal && \"items-end\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{/* Text content */}\n\t\t\t\t\t\t\t\t{hasText && (\n\t\t\t\t\t\t\t\t\t<TimelineItemContent\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"block min-w-0 break-words rounded-lg px-3.5 py-2.5 text-sm\",\n\t\t\t\t\t\t\t\t\t\t\tmessageWidthClassName,\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-background-300 text-co-foreground dark:bg-co-background-600\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t!isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-primary text-co-primary-foreground\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\"rounded-br-sm\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisLast && isSentByViewerFinal && !hasAttachments,\n\t\t\t\t\t\t\t\t\t\t\t\t\"rounded-bl-sm\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisLast && !isSentByViewerFinal && !hasAttachments,\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\tmarkdownRenderers={markdownRenderers}\n\t\t\t\t\t\t\t\t\t\trenderMarkdown\n\t\t\t\t\t\t\t\t\t\ttext={item.text}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{/* Image attachments */}\n\t\t\t\t\t\t\t\t{images.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"flex flex-wrap gap-2\",\n\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal && \"justify-end\"\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{images.map((image, index) => (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"group relative overflow-hidden rounded-lg focus:outline-none focus:ring-2 focus:ring-co-primary/50\"\n\t\t\t\t\t\t\t\t\t\t\t\tkey={image.url}\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => openLightbox(index)}\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{/* biome-ignore lint/performance/noImgElement: React package, not Next.js specific */}\n\t\t\t\t\t\t\t\t\t\t\t\t{/* biome-ignore lint/nursery/useImageSize: Dynamic image dimensions not known at render time */}\n\t\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\t\talt={image.filename || `Image ${index + 1}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"max-h-[150px] max-w-[200px] cursor-pointer rounded-lg object-cover transition-transform group-hover:scale-105\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsrc={image.url}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{/* File attachments */}\n\t\t\t\t\t\t\t\t{files.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t\t\t\t\t{files.map((file) => (\n\t\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"flex items-center gap-2 rounded-lg px-3 py-2 text-xs transition-colors\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-background-300 text-co-foreground hover:bg-co-background-400 dark:bg-co-background-600 dark:hover:bg-co-background-500\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t!isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-primary/80 text-co-primary-foreground hover:bg-co-primary\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\tdownload={file.filename}\n\t\t\t\t\t\t\t\t\t\t\t\thref={file.url}\n\t\t\t\t\t\t\t\t\t\t\t\tkey={file.url}\n\t\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4 shrink-0\" name=\"file\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"flex-1 truncate font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{file.filename || \"Download file\"}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t{file.size && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground opacity-70\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{isLast && (\n\t\t\t\t\t\t\t\t\t<TimelineItemTimestamp\n\t\t\t\t\t\t\t\t\t\tclassName=\"px-1 text-co-muted-foreground text-xs\"\n\t\t\t\t\t\t\t\t\t\ttimestamp={timestamp}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{() => (\n\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t{timestamp.toLocaleTimeString([], {\n\t\t\t\t\t\t\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t{isAI &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t` ${text(\"component.message.timestamp.aiIndicator\")}`}\n\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</TimelineItemTimestamp>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}}\n\t\t\t</PrimitiveTimelineItem>\n\n\t\t\t{/* Lightbox for images */}\n\t\t\t{images.length > 0 && (\n\t\t\t\t<ImageLightbox\n\t\t\t\t\timages={images}\n\t\t\t\t\tinitialIndex={lightboxIndex}\n\t\t\t\t\tisOpen={lightboxOpen}\n\t\t\t\t\tonClose={() => setLightboxOpen(false)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;AA4BA,SAAgB,8BACf,MACS;AACT,QAAO,2BAA2B,KAAK,GACpC,sBACA;;;;;;AAOJ,SAAgB,oBAAoB,EACnC,MACA,SAAS,OACT,iBAAiB,SAC+B;CAChD,MAAM,OAAO,gBAAgB;CAC7B,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;CACvD,MAAM,CAAC,eAAe,oBAAoB,SAAS,EAAE;CAGrD,MAAM,SAAS,kBAAkB,KAAK,MAAM;CAC5C,MAAM,QAAQ,iBAAiB,KAAK,MAAM;CAC1C,MAAM,iBAAiB,OAAO,SAAS,KAAK,MAAM,SAAS;CAC3D,MAAM,UAAU,KAAK,QAAQ,KAAK,KAAK,MAAM,CAAC,SAAS;CACvD,MAAM,wBAAwB,8BAA8B,KAAK,KAAK;CACtE,MAAM,oBAAoB,eAClB;EACN,YAAY,EAAE,MAAM,UAAU,eAC7B,oBAAC;GACM;GACI;GACA;IACT;EAEH,eAAe,EAAE,eAChB,oBAAC,wBAA+B,WAAY;EAE7C,aAAa,EAAE,WACd,oBAAC;GAAK,WAAU;aACd;IACK;EAER,GACD,EAAE,CACF;CAED,MAAM,gBAAgB,UAAkB;AACvC,mBAAiB,MAAM;AACvB,kBAAgB,KAAK;;AAGtB,QACC,4CACC,oBAACA;EAA4B;aAC1B,EAAE,MAAM,gBAAgB;GAGzB,MAAM,sBAAsB;AAE5B,UACC,oBAAC;IACA,WAAW,GACV,qBACA,uBAAuB,oBACvB,CAAC,uBAAuB,WACxB;cAED,qBAAC;KACA,WAAW,GACV,6CACA,uBAAuB,YACvB;;MAGA,WACA,oBAAC;OACA,WAAW,GACV,8DACA,uBACA;QACC,qEACC,CAAC;QACF,4CACC;QACD,iBACC,UAAU,uBAAuB,CAAC;QACnC,iBACC,UAAU,CAAC,uBAAuB,CAAC;QACpC,CACD;OACkB;OACnB;OACA,MAAM,KAAK;QACV;MAIF,OAAO,SAAS,KAChB,oBAAC;OACA,WAAW,GACV,wBACA,uBAAuB,cACvB;iBAEA,OAAO,KAAK,OAAO,UACnB,oBAAC;QACA,WAAU;QAEV,eAAe,aAAa,MAAM;QAClC,MAAK;kBAIL,oBAAC;SACA,KAAK,MAAM,YAAY,SAAS,QAAQ;SACxC,WAAU;SACV,SAAQ;SACR,KAAK,MAAM;UACV;UAXG,MAAM,IAYH,CACR;QACG;MAIN,MAAM,SAAS,KACf,oBAAC;OAAI,WAAU;iBACb,MAAM,KAAK,SACX,qBAAC;QACA,WAAW,GACV,0EACA;SACC,gIACC,CAAC;SACF,mEACC;SACD,CACD;QACD,UAAU,KAAK;QACf,MAAM,KAAK;QAEX,KAAI;QACJ,QAAO;;SAEP,oBAACC;UAAK,WAAU;UAAmB,MAAK;WAAS;SACjD,oBAAC;UAAK,WAAU;oBACd,KAAK,YAAY;WACZ;SACN,KAAK,QACL,oBAAC;UAAK,WAAU;oBACd,eAAe,KAAK,KAAK;WACpB;;UAXH,KAAK,IAaP,CACH;QACG;MAGN,UACA,oBAAC;OACA,WAAU;OACC;uBAGV,4CACE,UAAU,mBAAmB,EAAE,EAAE;QACjC,MAAM;QACN,QAAQ;QACR,CAAC,EACD,QACA,IAAI,KAAK,0CAA0C,MAClD;QAEmB;;MAEpB;KACD;;GAGe,EAGvB,OAAO,SAAS,KAChB,oBAAC;EACQ;EACR,cAAc;EACd,QAAQ;EACR,eAAe,gBAAgB,MAAM;GACpC,IAED"}
@@ -1 +1 @@
1
- {"version":3,"file":"typing-indicator.d.ts","names":[],"sources":["../../../src/support/components/typing-indicator.tsx"],"sourcesContent":[],"mappings":";;;;KAKY,qBAAA;KAEA,iBAAA;EAFA,EAAA,EAAA,MAAA;EAEA,IAAA,EAEL,qBAFsB;AAK7B,CAAA;AAAwD,KAA5C,oBAAA,GAAuB,OAAA,CAAM,cAAe,CAAA,cAAA,CAAA,GAAA;EAArB,YAAM,EAC1B,iBAD0B,EAAA;EAC1B,iBAAA,CAAA,EACM,gBADN,EAAA;EACM,oBAAA,CAAA,EACG,mBADH,EAAA;EACG,WAAA,CAAA,EAAA,OAAA;CAAmB;AAI9B,cAAA,YAAgB,EAAA,CAAA;EAAA;CAIzB,EAAM;EAuBG,SAAA,CAAA,EAAA,MAwDZ;CAxD2B,EAAA,GAvBxB,OAAA,CAAM,YAuBkB;AAAA,cAAf,eAAe,EAAA,OAAA,CAAA,yBAAA,CAAA,OAAA,CAAA,cAAA,CAAA,cAAA,CAAA,GAAA;EAjCb,YAAA,EAAA,iBAAA,EAAA;EACM,iBAAA,CAAA,EAAA,gBAAA,EAAA;EACG,oBAAA,CAAA,EAAA,mBAAA,EAAA"}
1
+ {"version":3,"file":"typing-indicator.d.ts","names":[],"sources":["../../../src/support/components/typing-indicator.tsx"],"sourcesContent":[],"mappings":";;;;KAKY,qBAAA;KAEA,iBAAA;EAFA,EAAA,EAAA,MAAA;EAEA,IAAA,EAEL,qBAFsB;AAK7B,CAAA;AAAwD,KAA5C,oBAAA,GAAuB,OAAA,CAAM,cAAe,CAAA,cAAA,CAAA,GAAA;EAArB,YAAM,EAC1B,iBAD0B,EAAA;EAC1B,iBAAA,CAAA,EACM,gBADN,EAAA;EACM,oBAAA,CAAA,EACG,mBADH,EAAA;EACG,WAAA,CAAA,EAAA,OAAA;CAAmB;AAI9B,cAAA,YAAgB,EAAA,CAAA;EAAA;CAIzB,EAAM;EAuBG,SAAA,CAAA,EAAA,MAsEZ;CAtE2B,EAAA,GAvBxB,OAAA,CAAM,YAuBkB;AAAA,cAAf,eAAe,EAAA,OAAA,CAAA,yBAAA,CAAA,OAAA,CAAA,cAAA,CAAA,cAAA,CAAA,GAAA;EAjCb,YAAA,EAAA,iBAAA,EAAA;EACM,iBAAA,CAAA,EAAA,gBAAA,EAAA;EACG,oBAAA,CAAA,EAAA,mBAAA,EAAA"}
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../utils/index.js";
2
- import { AvatarStack } from "./avatar-stack.js";
2
+ import { Avatar } from "./avatar.js";
3
3
  import * as React$1 from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
 
@@ -22,12 +22,20 @@ const TypingIndicator = React$1.forwardRef(({ participants, availableAIAgents =
22
22
  className: cn("flex items-center gap-6", className),
23
23
  ref,
24
24
  ...props,
25
- children: [withAvatars && /* @__PURE__ */ jsx(AvatarStack, {
26
- aiAgents: typingAIAgents,
27
- hideDefaultAIAgent: typingAIAgents.length === 0,
28
- humanAgents: typingHumanAgents,
29
- size: 24,
30
- spacing: 16
25
+ children: [withAvatars && /* @__PURE__ */ jsxs("div", {
26
+ className: "flex items-center",
27
+ children: [typingAIAgents.map((agent) => /* @__PURE__ */ jsx(Avatar, {
28
+ className: "size-6",
29
+ image: agent.image,
30
+ isAI: true,
31
+ name: agent.name,
32
+ showBackground: !!agent.image
33
+ }, agent.id)), typingHumanAgents.map((agent) => /* @__PURE__ */ jsx(Avatar, {
34
+ className: "size-6",
35
+ image: agent.image,
36
+ lastSeenAt: agent.lastSeenAt,
37
+ name: agent.name
38
+ }, agent.id))]
31
39
  }), /* @__PURE__ */ jsx(BouncingDots, {})]
32
40
  });
33
41
  });
@@ -1 +1 @@
1
- {"version":3,"file":"typing-indicator.js","names":["React"],"sources":["../../../src/support/components/typing-indicator.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport * as React from \"react\";\nimport { cn } from \"../utils\";\nimport { AvatarStack } from \"./avatar-stack\";\n\nexport type TypingParticipantType = \"visitor\" | \"team_member\" | \"ai\";\n\nexport type TypingParticipant = {\n\tid: string;\n\ttype: TypingParticipantType;\n};\n\nexport type TypingIndicatorProps = React.HTMLAttributes<HTMLDivElement> & {\n\tparticipants: TypingParticipant[];\n\tavailableAIAgents?: AvailableAIAgent[];\n\tavailableHumanAgents?: AvailableHumanAgent[];\n\twithAvatars?: boolean;\n};\n\nexport const BouncingDots = ({\n\tclassName,\n}: {\n\tclassName?: string;\n}): React.ReactElement => (\n\t<div className=\"flex gap-1\">\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-1 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-2 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-3 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t</div>\n);\n\nexport const TypingIndicator = React.forwardRef<\n\tHTMLDivElement,\n\tTypingIndicatorProps\n>(\n\t(\n\t\t{\n\t\t\tparticipants,\n\t\t\tavailableAIAgents = [],\n\t\t\tavailableHumanAgents = [],\n\t\t\twithAvatars = true,\n\t\t\tclassName,\n\t\t\t...props\n\t\t},\n\t\tref\n\t) => {\n\t\tif (!participants || participants.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Separate AI and human participants\n\t\tconst humanParticipantIds = participants\n\t\t\t.filter((p) => p.type === \"team_member\")\n\t\t\t.map((p) => p.id);\n\n\t\tconst aiParticipantIds = participants\n\t\t\t.filter((p) => p.type === \"ai\")\n\t\t\t.map((p) => p.id);\n\n\t\t// Get matching agents\n\t\tconst typingHumanAgents = availableHumanAgents.filter((agent) =>\n\t\t\thumanParticipantIds.includes(agent.id)\n\t\t);\n\n\t\tconst typingAIAgents = availableAIAgents.filter((agent) =>\n\t\t\taiParticipantIds.includes(agent.id)\n\t\t);\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\"flex items-center gap-6\", className)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{withAvatars && (\n\t\t\t\t\t<AvatarStack\n\t\t\t\t\t\taiAgents={typingAIAgents}\n\t\t\t\t\t\thideDefaultAIAgent={typingAIAgents.length === 0}\n\t\t\t\t\t\thumanAgents={typingHumanAgents}\n\t\t\t\t\t\tsize={24}\n\t\t\t\t\t\tspacing={16}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<BouncingDots />\n\t\t\t</div>\n\t\t);\n\t}\n);\n\nTypingIndicator.displayName = \"TypingIndicator\";\n"],"mappings":";;;;;;AAmBA,MAAa,gBAAgB,EAC5B,gBAIA,qBAAC;CAAI,WAAU;;EACd,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;EACF,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;EACF,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;;EACG;AAGP,MAAa,kBAAkBA,QAAM,YAKnC,EACC,cACA,oBAAoB,EAAE,EACtB,uBAAuB,EAAE,EACzB,cAAc,MACd,WACA,GAAG,SAEJ,QACI;AACJ,KAAI,CAAC,gBAAgB,aAAa,WAAW,EAC5C,QAAO;CAIR,MAAM,sBAAsB,aAC1B,QAAQ,MAAM,EAAE,SAAS,cAAc,CACvC,KAAK,MAAM,EAAE,GAAG;CAElB,MAAM,mBAAmB,aACvB,QAAQ,MAAM,EAAE,SAAS,KAAK,CAC9B,KAAK,MAAM,EAAE,GAAG;CAGlB,MAAM,oBAAoB,qBAAqB,QAAQ,UACtD,oBAAoB,SAAS,MAAM,GAAG,CACtC;CAED,MAAM,iBAAiB,kBAAkB,QAAQ,UAChD,iBAAiB,SAAS,MAAM,GAAG,CACnC;AAED,QACC,qBAAC;EACA,WAAW,GAAG,2BAA2B,UAAU;EAC9C;EACL,GAAI;aAEH,eACA,oBAAC;GACA,UAAU;GACV,oBAAoB,eAAe,WAAW;GAC9C,aAAa;GACb,MAAM;GACN,SAAS;IACR,EAEH,oBAAC,iBAAe;GACX;EAGR;AAED,gBAAgB,cAAc"}
1
+ {"version":3,"file":"typing-indicator.js","names":["React"],"sources":["../../../src/support/components/typing-indicator.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport * as React from \"react\";\nimport { cn } from \"../utils\";\nimport { Avatar } from \"./avatar\";\n\nexport type TypingParticipantType = \"visitor\" | \"team_member\" | \"ai\";\n\nexport type TypingParticipant = {\n\tid: string;\n\ttype: TypingParticipantType;\n};\n\nexport type TypingIndicatorProps = React.HTMLAttributes<HTMLDivElement> & {\n\tparticipants: TypingParticipant[];\n\tavailableAIAgents?: AvailableAIAgent[];\n\tavailableHumanAgents?: AvailableHumanAgent[];\n\twithAvatars?: boolean;\n};\n\nexport const BouncingDots = ({\n\tclassName,\n}: {\n\tclassName?: string;\n}): React.ReactElement => (\n\t<div className=\"flex gap-1\">\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-1 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-2 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-3 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t</div>\n);\n\nexport const TypingIndicator = React.forwardRef<\n\tHTMLDivElement,\n\tTypingIndicatorProps\n>(\n\t(\n\t\t{\n\t\t\tparticipants,\n\t\t\tavailableAIAgents = [],\n\t\t\tavailableHumanAgents = [],\n\t\t\twithAvatars = true,\n\t\t\tclassName,\n\t\t\t...props\n\t\t},\n\t\tref\n\t) => {\n\t\tif (!participants || participants.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Separate AI and human participants\n\t\tconst humanParticipantIds = participants\n\t\t\t.filter((p) => p.type === \"team_member\")\n\t\t\t.map((p) => p.id);\n\n\t\tconst aiParticipantIds = participants\n\t\t\t.filter((p) => p.type === \"ai\")\n\t\t\t.map((p) => p.id);\n\n\t\t// Get matching agents\n\t\tconst typingHumanAgents = availableHumanAgents.filter((agent) =>\n\t\t\thumanParticipantIds.includes(agent.id)\n\t\t);\n\n\t\tconst typingAIAgents = availableAIAgents.filter((agent) =>\n\t\t\taiParticipantIds.includes(agent.id)\n\t\t);\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\"flex items-center gap-6\", className)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{withAvatars && (\n\t\t\t\t\t<div className=\"flex items-center\">\n\t\t\t\t\t\t{typingAIAgents.map((agent) => (\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tclassName=\"size-6\"\n\t\t\t\t\t\t\t\timage={agent.image}\n\t\t\t\t\t\t\t\tisAI\n\t\t\t\t\t\t\t\tkey={agent.id}\n\t\t\t\t\t\t\t\tname={agent.name}\n\t\t\t\t\t\t\t\tshowBackground={!!agent.image}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t{typingHumanAgents.map((agent) => (\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tclassName=\"size-6\"\n\t\t\t\t\t\t\t\timage={agent.image}\n\t\t\t\t\t\t\t\tkey={agent.id}\n\t\t\t\t\t\t\t\tlastSeenAt={agent.lastSeenAt}\n\t\t\t\t\t\t\t\tname={agent.name}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<BouncingDots />\n\t\t\t</div>\n\t\t);\n\t}\n);\n\nTypingIndicator.displayName = \"TypingIndicator\";\n"],"mappings":";;;;;;AAmBA,MAAa,gBAAgB,EAC5B,gBAIA,qBAAC;CAAI,WAAU;;EACd,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;EACF,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;EACF,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;;EACG;AAGP,MAAa,kBAAkBA,QAAM,YAKnC,EACC,cACA,oBAAoB,EAAE,EACtB,uBAAuB,EAAE,EACzB,cAAc,MACd,WACA,GAAG,SAEJ,QACI;AACJ,KAAI,CAAC,gBAAgB,aAAa,WAAW,EAC5C,QAAO;CAIR,MAAM,sBAAsB,aAC1B,QAAQ,MAAM,EAAE,SAAS,cAAc,CACvC,KAAK,MAAM,EAAE,GAAG;CAElB,MAAM,mBAAmB,aACvB,QAAQ,MAAM,EAAE,SAAS,KAAK,CAC9B,KAAK,MAAM,EAAE,GAAG;CAGlB,MAAM,oBAAoB,qBAAqB,QAAQ,UACtD,oBAAoB,SAAS,MAAM,GAAG,CACtC;CAED,MAAM,iBAAiB,kBAAkB,QAAQ,UAChD,iBAAiB,SAAS,MAAM,GAAG,CACnC;AAED,QACC,qBAAC;EACA,WAAW,GAAG,2BAA2B,UAAU;EAC9C;EACL,GAAI;aAEH,eACA,qBAAC;GAAI,WAAU;cACb,eAAe,KAAK,UACpB,oBAAC;IACA,WAAU;IACV,OAAO,MAAM;IACb;IAEA,MAAM,MAAM;IACZ,gBAAgB,CAAC,CAAC,MAAM;MAFnB,MAAM,GAGV,CACD,EACD,kBAAkB,KAAK,UACvB,oBAAC;IACA,WAAU;IACV,OAAO,MAAM;IAEb,YAAY,MAAM;IAClB,MAAM,MAAM;MAFP,MAAM,GAGV,CACD;IACG,EAEP,oBAAC,iBAAe;GACX;EAGR;AAED,gBAAgB,cAAc"}
@@ -11,7 +11,7 @@ import { WebSocketContextValue, WebSocketProvider, useWebSocket } from "./contex
11
11
  import { useSupportConfig, useSupportNavigation, useSupportStore } from "./store/support-store.js";
12
12
  import "./store/index.js";
13
13
  import * as React$1 from "react";
14
- import * as _cossistant_core0 from "@cossistant/core";
14
+ import * as _cossistant_core7 from "@cossistant/core";
15
15
  import { DefaultRoutes, NavigationState, RouteRegistry, SupportPage as SupportPageType } from "@cossistant/core";
16
16
  import { DefaultMessage } from "@cossistant/types";
17
17
 
@@ -179,10 +179,10 @@ type SupportRouterProps = {
179
179
  */
180
180
  children?: React$1.ReactNode;
181
181
  };
182
- type SupportPageProps<K extends keyof _cossistant_core0.RouteRegistry = keyof _cossistant_core0.RouteRegistry> = {
182
+ type SupportPageProps<K extends keyof _cossistant_core7.RouteRegistry = keyof _cossistant_core7.RouteRegistry> = {
183
183
  name: K;
184
184
  component: React$1.ComponentType<{
185
- params?: _cossistant_core0.RouteRegistry[K];
185
+ params?: _cossistant_core7.RouteRegistry[K];
186
186
  }>;
187
187
  };
188
188
  type SupportRootProps = {
@@ -250,7 +250,7 @@ declare const Support: (<Locale extends string = SupportLocale>(props: SupportPr
250
250
  } & React$1.RefAttributes<HTMLButtonElement>>;
251
251
  Content: React$1.FC<SupportContentProps>;
252
252
  Router: React$1.FC<SupportRouterProps>;
253
- Page: <K extends keyof _cossistant_core0.RouteRegistry>(_props: PageProps<K>) => null;
253
+ Page: <K extends keyof _cossistant_core7.RouteRegistry>(_props: PageProps<K>) => null;
254
254
  Header: React$1.FC<SlotProps>;
255
255
  Footer: React$1.FC<SlotProps>;
256
256
  };
@@ -1,10 +1,10 @@
1
- import { AvatarStack } from "../components/avatar-stack.js";
2
1
  import { useSupportNavigation } from "../store/support-store.js";
3
2
  import { CoButton } from "../components/button.js";
4
3
  import icons_default from "../components/icons.js";
5
4
  import { PENDING_CONVERSATION_ID } from "../../utils/id.js";
6
5
  import { Header } from "../components/header.js";
7
6
  import { Text, useSupportText } from "../text/index.js";
7
+ import { AvatarStack } from "../components/avatar-stack.js";
8
8
  import { Watermark } from "../components/watermark.js";
9
9
  import { useConversationHistoryPage } from "../../hooks/use-conversation-history-page.js";
10
10
  import { ConversationButtonLink } from "../components/conversation-button-link.js";
@@ -1,10 +1,10 @@
1
1
  import { useStoreSelector } from "../../hooks/private/store/use-store-selector.js";
2
- import { AvatarStack } from "../components/avatar-stack.js";
3
2
  import { useSupportConfig, useSupportNavigation } from "../store/support-store.js";
4
3
  import { useNewMessageSound } from "../../hooks/use-new-message-sound.js";
5
4
  import { Header } from "../components/header.js";
6
5
  import { Text, useSupportText } from "../text/index.js";
7
6
  import { useConversationPage } from "../../hooks/use-conversation-page.js";
7
+ import { AvatarStack } from "../components/avatar-stack.js";
8
8
  import { ConversationResolvedFeedback } from "../components/conversation-resolved-feedback.js";
9
9
  import { ConversationTimelineList } from "../components/conversation-timeline.js";
10
10
  import { MultimodalInput } from "../components/multimodal-input.js";
@@ -50,7 +50,7 @@ const ConversationPage = ({ params, conversationId: legacyConversationId, initia
50
50
  setPendingRating(null);
51
51
  setIsSubmittingRating(false);
52
52
  }, [activeConversation?.id]);
53
- const handleRateConversation = async (value) => {
53
+ const handleRateConversation = async (value, comment) => {
54
54
  if (!(client && activeConversation)) return;
55
55
  if (activeConversation.status !== ConversationStatus.RESOLVED || activeConversation.visitorRating) return;
56
56
  if (isSubmittingRating) return;
@@ -60,6 +60,7 @@ const ConversationPage = ({ params, conversationId: legacyConversationId, initia
60
60
  await client.submitConversationRating({
61
61
  conversationId: activeConversation.id,
62
62
  rating: value,
63
+ comment,
63
64
  visitorId: visitor?.id ?? void 0
64
65
  });
65
66
  } catch (error) {
@@ -105,6 +106,7 @@ const ConversationPage = ({ params, conversationId: legacyConversationId, initia
105
106
  }), /* @__PURE__ */ jsx(AvatarStack, {
106
107
  aiAgents: availableAIAgents,
107
108
  gapWidth: 2,
109
+ hideDefaultAIAgent: false,
108
110
  humanAgents: availableHumanAgents,
109
111
  size: 32,
110
112
  spacing: 28