@cossistant/react 0.0.32 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/hooks/index.d.ts +2 -2
- package/hooks/index.js +2 -2
- package/hooks/private/store/use-store-selector.d.ts.map +1 -1
- package/hooks/private/store/use-store-selector.js +8 -4
- package/hooks/private/store/use-store-selector.js.map +1 -1
- package/hooks/private/use-client-query.js +5 -2
- package/hooks/private/use-client-query.js.map +1 -1
- package/hooks/private/use-grouped-messages.d.ts +27 -2
- package/hooks/private/use-grouped-messages.d.ts.map +1 -1
- package/hooks/private/use-grouped-messages.js +154 -106
- package/hooks/private/use-grouped-messages.js.map +1 -1
- package/hooks/private/use-rest-client.js +2 -1
- package/hooks/private/use-rest-client.js.map +1 -1
- package/hooks/use-conversation-auto-seen.d.ts.map +1 -1
- package/hooks/use-conversation-auto-seen.js +9 -3
- package/hooks/use-conversation-auto-seen.js.map +1 -1
- package/hooks/use-conversation-page.d.ts.map +1 -1
- package/hooks/use-conversation-page.js +13 -3
- package/hooks/use-conversation-page.js.map +1 -1
- package/hooks/use-new-message-sound.d.ts.map +1 -1
- package/hooks/use-new-message-sound.js +2 -2
- package/hooks/use-new-message-sound.js.map +1 -1
- package/hooks/use-typing-sound.d.ts.map +1 -1
- package/hooks/use-typing-sound.js +2 -2
- package/hooks/use-typing-sound.js.map +1 -1
- package/index.d.ts +3 -3
- package/index.js +3 -3
- package/package.json +6 -12
- package/packages/tiny-markdown/src/context/index.d.ts +1 -0
- package/packages/tiny-markdown/src/context/tiny-markdown-context.d.ts +3 -0
- package/packages/tiny-markdown/src/hooks/index.d.ts +4 -0
- package/packages/tiny-markdown/src/hooks/use-caret-position.d.ts +1 -0
- package/packages/tiny-markdown/src/hooks/use-tiny-markdown.d.ts +1 -0
- package/packages/tiny-markdown/src/hooks/use-tiny-mention.d.ts +1 -0
- package/packages/tiny-markdown/src/hooks/use-tiny-shortcuts.d.ts +1 -0
- package/packages/tiny-markdown/src/index.d.ts +4 -0
- package/packages/tiny-markdown/src/types.d.ts +75 -0
- package/packages/tiny-markdown/src/types.d.ts.map +1 -0
- package/packages/tiny-markdown/src/utils/index.d.ts +3 -0
- package/packages/tiny-markdown/src/utils/markdown-parser.d.ts +1 -0
- package/packages/tiny-markdown/src/utils/mention-parser.d.ts +1 -0
- package/packages/tiny-markdown/src/utils/merge-refs.d.ts +1 -0
- package/packages/types/src/api/conversation.d.ts +300 -0
- package/packages/types/src/api/conversation.d.ts.map +1 -1
- package/packages/types/src/api/timeline-item.d.ts +225 -0
- package/packages/types/src/api/timeline-item.d.ts.map +1 -1
- package/packages/types/src/realtime-events.d.ts +228 -3
- package/packages/types/src/realtime-events.d.ts.map +1 -1
- package/packages/types/src/schemas.d.ts +75 -0
- package/packages/types/src/schemas.d.ts.map +1 -1
- package/primitives/avatar/image.d.ts +1 -1
- package/primitives/command-block-utils.d.ts +26 -0
- package/primitives/command-block-utils.d.ts.map +1 -0
- package/primitives/command-block-utils.js +310 -0
- package/primitives/command-block-utils.js.map +1 -0
- package/primitives/index.d.ts +7 -3
- package/primitives/index.js +11 -2
- package/primitives/index.parts.d.ts +6 -2
- package/primitives/index.parts.js +5 -1
- package/primitives/timeline-code-block.d.ts +32 -0
- package/primitives/timeline-code-block.d.ts.map +1 -0
- package/primitives/timeline-code-block.js +66 -0
- package/primitives/timeline-code-block.js.map +1 -0
- package/primitives/timeline-command-block.d.ts +29 -0
- package/primitives/timeline-command-block.d.ts.map +1 -0
- package/primitives/timeline-command-block.js +97 -0
- package/primitives/timeline-command-block.js.map +1 -0
- package/primitives/timeline-item-group.d.ts.map +1 -1
- package/primitives/timeline-item-group.js +5 -15
- package/primitives/timeline-item-group.js.map +1 -1
- package/primitives/timeline-item.d.ts +21 -1
- package/primitives/timeline-item.d.ts.map +1 -1
- package/primitives/timeline-item.js +148 -83
- package/primitives/timeline-item.js.map +1 -1
- package/primitives/timeline-message-layout.d.ts +9 -0
- package/primitives/timeline-message-layout.d.ts.map +1 -0
- package/primitives/timeline-message-layout.js +20 -0
- package/primitives/timeline-message-layout.js.map +1 -0
- package/provider.d.ts.map +1 -1
- package/provider.js +1 -7
- package/provider.js.map +1 -1
- package/realtime/event-filter.js +4 -3
- package/realtime/event-filter.js.map +1 -1
- package/realtime/provider.d.ts +0 -1
- package/realtime/provider.d.ts.map +1 -1
- package/realtime/provider.js +29 -34
- package/realtime/provider.js.map +1 -1
- package/sounds/sound-data.d.ts +6 -0
- package/sounds/sound-data.d.ts.map +1 -0
- package/sounds/sound-data.js +7 -0
- package/sounds/sound-data.js.map +1 -0
- package/styles.css +2 -0
- package/support/components/avatar.js +3 -3
- package/support/components/avatar.js.map +1 -1
- package/support/components/button.d.ts +2 -2
- package/support/components/button.d.ts.map +1 -1
- package/support/components/button.js +1 -0
- package/support/components/button.js.map +1 -1
- package/support/components/conversation-event.d.ts +3 -0
- package/support/components/conversation-event.d.ts.map +1 -1
- package/support/components/conversation-event.js +47 -16
- package/support/components/conversation-event.js.map +1 -1
- package/support/components/conversation-timeline.d.ts.map +1 -1
- package/support/components/conversation-timeline.js +12 -0
- package/support/components/conversation-timeline.js.map +1 -1
- package/support/components/index.d.ts +2 -1
- package/support/components/index.js +2 -1
- package/support/components/timeline-activity-group.d.ts +25 -0
- package/support/components/timeline-activity-group.d.ts.map +1 -0
- package/support/components/timeline-activity-group.js +104 -0
- package/support/components/timeline-activity-group.js.map +1 -0
- package/support/components/timeline-code-block.d.ts +14 -0
- package/support/components/timeline-code-block.d.ts.map +1 -0
- package/support/components/timeline-code-block.js +44 -0
- package/support/components/timeline-code-block.js.map +1 -0
- package/support/components/timeline-command-block.d.ts +12 -0
- package/support/components/timeline-command-block.d.ts.map +1 -0
- package/support/components/timeline-command-block.js +42 -0
- package/support/components/timeline-command-block.js.map +1 -0
- package/support/components/timeline-message-item.d.ts +2 -1
- package/support/components/timeline-message-item.d.ts.map +1 -1
- package/support/components/timeline-message-item.js +23 -3
- package/support/components/timeline-message-item.js.map +1 -1
- package/support/pages/home.js +1 -1
- package/support/pages/home.js.map +1 -1
- package/support/store/support-store.d.ts.map +1 -1
- package/support/store/support-store.js +4 -4
- package/support/store/support-store.js.map +1 -1
- package/support/{support-DmViRaga.css → support-Dc5L__HC.css} +15 -15
- package/support/{support-DmViRaga.css.map → support-Dc5L__HC.css.map} +1 -1
- package/{tailwind.css → support/support.css} +14 -14
- package/support-config.d.ts +31 -4
- package/support-config.d.ts.map +1 -1
- package/support-config.js +52 -4
- package/support-config.js.map +1 -1
- package/support.css +1 -2
- package/utils/metadata-hash.d.ts +1 -1
- package/utils/metadata-hash.js +9 -4
- package/utils/metadata-hash.js.map +1 -1
- package/utils/timeline-item-sender.d.ts +17 -0
- package/utils/timeline-item-sender.d.ts.map +1 -0
- package/utils/timeline-item-sender.js +43 -0
- package/utils/timeline-item-sender.js.map +1 -0
- package/utils/use-render-element.d.ts.map +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { cn } from "../utils/index.js";
|
|
1
2
|
import { Avatar } from "./avatar.js";
|
|
2
3
|
import { useSupportText } from "../text/index.js";
|
|
3
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
5
|
import { motion } from "motion/react";
|
|
5
6
|
|
|
6
7
|
//#region src/support/components/conversation-event.tsx
|
|
7
|
-
const ConversationEvent = ({ event, availableAIAgents, createdAt, availableHumanAgents }) => {
|
|
8
|
+
const ConversationEvent = ({ event, availableAIAgents, createdAt, availableHumanAgents, compact = false, showAvatar = true, className }) => {
|
|
8
9
|
const text = useSupportText();
|
|
9
10
|
const isAI = event.actorAiAgentId !== null;
|
|
10
11
|
const humanAgent = availableHumanAgents.find((agent) => agent.id === event.actorUserId);
|
|
@@ -29,12 +30,52 @@ const ConversationEvent = ({ event, availableAIAgents, createdAt, availableHuman
|
|
|
29
30
|
default: return text("component.conversationEvent.default", { actorName });
|
|
30
31
|
}
|
|
31
32
|
};
|
|
33
|
+
const avatarContent = isAI ? /* @__PURE__ */ jsx(Avatar, {
|
|
34
|
+
className: "size-6 flex-shrink-0",
|
|
35
|
+
image: aiAgent?.image,
|
|
36
|
+
isAI: true,
|
|
37
|
+
name: aiAgent?.name || text("common.fallbacks.cossistant"),
|
|
38
|
+
showBackground: !!aiAgent?.image
|
|
39
|
+
}) : /* @__PURE__ */ jsx(Avatar, {
|
|
40
|
+
className: "size-6 flex-shrink-0",
|
|
41
|
+
image: humanAgent?.image,
|
|
42
|
+
name: humanAgent?.name || text("common.fallbacks.someone")
|
|
43
|
+
});
|
|
44
|
+
if (compact) return /* @__PURE__ */ jsxs(motion.div, {
|
|
45
|
+
animate: {
|
|
46
|
+
opacity: 1,
|
|
47
|
+
scale: 1
|
|
48
|
+
},
|
|
49
|
+
className: cn("flex items-center gap-2 text-co-muted-foreground text-sm", className),
|
|
50
|
+
initial: {
|
|
51
|
+
opacity: 0,
|
|
52
|
+
scale: .95
|
|
53
|
+
},
|
|
54
|
+
transition: {
|
|
55
|
+
duration: .3,
|
|
56
|
+
ease: "easeOut"
|
|
57
|
+
},
|
|
58
|
+
children: [
|
|
59
|
+
showAvatar ? avatarContent : null,
|
|
60
|
+
/* @__PURE__ */ jsx("span", {
|
|
61
|
+
className: "break-words",
|
|
62
|
+
children: getEventText()
|
|
63
|
+
}),
|
|
64
|
+
createdAt ? /* @__PURE__ */ jsx("time", {
|
|
65
|
+
className: "text-[10px]",
|
|
66
|
+
children: new Date(createdAt).toLocaleTimeString([], {
|
|
67
|
+
hour: "2-digit",
|
|
68
|
+
minute: "2-digit"
|
|
69
|
+
})
|
|
70
|
+
}) : null
|
|
71
|
+
]
|
|
72
|
+
});
|
|
32
73
|
return /* @__PURE__ */ jsx(motion.div, {
|
|
33
74
|
animate: {
|
|
34
75
|
opacity: 1,
|
|
35
76
|
scale: 1
|
|
36
77
|
},
|
|
37
|
-
className: "flex items-center
|
|
78
|
+
className: cn("flex items-center pt-4 pb-8", className),
|
|
38
79
|
initial: {
|
|
39
80
|
opacity: 0,
|
|
40
81
|
scale: .95
|
|
@@ -44,22 +85,12 @@ const ConversationEvent = ({ event, availableAIAgents, createdAt, availableHuman
|
|
|
44
85
|
ease: "easeOut"
|
|
45
86
|
},
|
|
46
87
|
children: /* @__PURE__ */ jsxs("div", {
|
|
47
|
-
className: "flex items-center gap-2 text-co-muted-foreground text-
|
|
88
|
+
className: "flex items-center gap-2 text-co-muted-foreground text-sm",
|
|
48
89
|
children: [
|
|
49
|
-
/* @__PURE__ */ jsx("div", {
|
|
90
|
+
showAvatar ? /* @__PURE__ */ jsx("div", {
|
|
50
91
|
className: "flex flex-col justify-end",
|
|
51
|
-
children:
|
|
52
|
-
|
|
53
|
-
image: aiAgent?.image,
|
|
54
|
-
isAI: true,
|
|
55
|
-
name: aiAgent?.name || text("common.fallbacks.cossistant"),
|
|
56
|
-
showBackground: !!aiAgent?.image
|
|
57
|
-
}) : /* @__PURE__ */ jsx(Avatar, {
|
|
58
|
-
className: "size-5 flex-shrink-0",
|
|
59
|
-
image: humanAgent?.image,
|
|
60
|
-
name: humanAgent?.name || text("common.fallbacks.someone")
|
|
61
|
-
})
|
|
62
|
-
}),
|
|
92
|
+
children: avatarContent
|
|
93
|
+
}) : null,
|
|
63
94
|
/* @__PURE__ */ jsx("span", {
|
|
64
95
|
className: "px-2",
|
|
65
96
|
children: getEventText()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-event.js","names":["ConversationEvent: React.FC<ConversationEventProps>"],"sources":["../../../src/support/components/conversation-event.tsx"],"sourcesContent":["import type {\n\tAvailableAIAgent,\n\tAvailableHumanAgent,\n\tTimelinePartEvent,\n} from \"@cossistant/types\";\nimport { motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useSupportText } from \"../text\";\nimport { Avatar } from \"./avatar\";\n\nexport type ConversationEventProps = {\n\tevent: TimelinePartEvent;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcreatedAt?: string;\n};\n\nexport const ConversationEvent: React.FC<ConversationEventProps> = ({\n\tevent,\n\tavailableAIAgents,\n\tcreatedAt,\n\tavailableHumanAgents,\n}) => {\n\tconst text = useSupportText();\n\tconst isAI = event.actorAiAgentId !== null;\n\tconst humanAgent = availableHumanAgents.find(\n\t\t(agent) => agent.id === event.actorUserId\n\t);\n\tconst aiAgent = availableAIAgents.find(\n\t\t(agent) => agent.id === event.actorAiAgentId\n\t);\n\n\t// Get the actor name\n\tconst actorName = isAI\n\t\t? aiAgent?.name || text(\"common.fallbacks.cossistant\")\n\t\t: humanAgent?.name || text(\"common.fallbacks.someone\");\n\n\t// Convert event type to plain English\n\tconst getEventText = () => {\n\t\tswitch (event.eventType) {\n\t\t\tcase \"assigned\":\n\t\t\t\treturn text(\"component.conversationEvent.assigned\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"unassigned\":\n\t\t\t\treturn text(\"component.conversationEvent.unassigned\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_requested\":\n\t\t\t\treturn text(\"component.conversationEvent.participantRequested\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_joined\":\n\t\t\t\treturn text(\"component.conversationEvent.participantJoined\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_left\":\n\t\t\t\treturn text(\"component.conversationEvent.participantLeft\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"status_changed\":\n\t\t\t\treturn text(\"component.conversationEvent.statusChanged\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"priority_changed\":\n\t\t\t\treturn text(\"component.conversationEvent.priorityChanged\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"tag_added\":\n\t\t\t\treturn text(\"component.conversationEvent.tagAdded\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"tag_removed\":\n\t\t\t\treturn text(\"component.conversationEvent.tagRemoved\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"resolved\":\n\t\t\t\treturn text(\"component.conversationEvent.resolved\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"reopened\":\n\t\t\t\treturn text(\"component.conversationEvent.reopened\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_blocked\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorBlocked\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_unblocked\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorUnblocked\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_identified\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorIdentified\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tdefault:\n\t\t\t\treturn text(\"component.conversationEvent.default\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t}\n\t};\n\n\treturn (\n\t\t<motion.div\n\t\t\tanimate={{ opacity: 1, scale: 1 }}\n\t\t\tclassName
|
|
1
|
+
{"version":3,"file":"conversation-event.js","names":["ConversationEvent: React.FC<ConversationEventProps>"],"sources":["../../../src/support/components/conversation-event.tsx"],"sourcesContent":["import type {\n\tAvailableAIAgent,\n\tAvailableHumanAgent,\n\tTimelinePartEvent,\n} from \"@cossistant/types\";\nimport { motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport { Avatar } from \"./avatar\";\n\nexport type ConversationEventProps = {\n\tevent: TimelinePartEvent;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcreatedAt?: string;\n\tcompact?: boolean;\n\tshowAvatar?: boolean;\n\tclassName?: string;\n};\n\nexport const ConversationEvent: React.FC<ConversationEventProps> = ({\n\tevent,\n\tavailableAIAgents,\n\tcreatedAt,\n\tavailableHumanAgents,\n\tcompact = false,\n\tshowAvatar = true,\n\tclassName,\n}) => {\n\tconst text = useSupportText();\n\tconst isAI = event.actorAiAgentId !== null;\n\tconst humanAgent = availableHumanAgents.find(\n\t\t(agent) => agent.id === event.actorUserId\n\t);\n\tconst aiAgent = availableAIAgents.find(\n\t\t(agent) => agent.id === event.actorAiAgentId\n\t);\n\n\t// Get the actor name\n\tconst actorName = isAI\n\t\t? aiAgent?.name || text(\"common.fallbacks.cossistant\")\n\t\t: humanAgent?.name || text(\"common.fallbacks.someone\");\n\n\t// Convert event type to plain English\n\tconst getEventText = () => {\n\t\tswitch (event.eventType) {\n\t\t\tcase \"assigned\":\n\t\t\t\treturn text(\"component.conversationEvent.assigned\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"unassigned\":\n\t\t\t\treturn text(\"component.conversationEvent.unassigned\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_requested\":\n\t\t\t\treturn text(\"component.conversationEvent.participantRequested\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_joined\":\n\t\t\t\treturn text(\"component.conversationEvent.participantJoined\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"participant_left\":\n\t\t\t\treturn text(\"component.conversationEvent.participantLeft\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"status_changed\":\n\t\t\t\treturn text(\"component.conversationEvent.statusChanged\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"priority_changed\":\n\t\t\t\treturn text(\"component.conversationEvent.priorityChanged\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"tag_added\":\n\t\t\t\treturn text(\"component.conversationEvent.tagAdded\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"tag_removed\":\n\t\t\t\treturn text(\"component.conversationEvent.tagRemoved\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"resolved\":\n\t\t\t\treturn text(\"component.conversationEvent.resolved\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"reopened\":\n\t\t\t\treturn text(\"component.conversationEvent.reopened\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_blocked\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorBlocked\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_unblocked\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorUnblocked\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tcase \"visitor_identified\":\n\t\t\t\treturn text(\"component.conversationEvent.visitorIdentified\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t\tdefault:\n\t\t\t\treturn text(\"component.conversationEvent.default\", {\n\t\t\t\t\tactorName,\n\t\t\t\t});\n\t\t}\n\t};\n\n\tconst avatarContent = isAI ? (\n\t\t<Avatar\n\t\t\tclassName=\"size-6 flex-shrink-0\"\n\t\t\timage={aiAgent?.image}\n\t\t\tisAI\n\t\t\tname={aiAgent?.name || text(\"common.fallbacks.cossistant\")}\n\t\t\tshowBackground={!!aiAgent?.image}\n\t\t/>\n\t) : (\n\t\t<Avatar\n\t\t\tclassName=\"size-6 flex-shrink-0\"\n\t\t\timage={humanAgent?.image}\n\t\t\tname={humanAgent?.name || text(\"common.fallbacks.someone\")}\n\t\t/>\n\t);\n\n\tif (compact) {\n\t\treturn (\n\t\t\t<motion.div\n\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex items-center gap-2 text-co-muted-foreground text-sm\",\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tinitial={{ opacity: 0, scale: 0.95 }}\n\t\t\t\ttransition={{ duration: 0.3, ease: \"easeOut\" }}\n\t\t\t>\n\t\t\t\t{showAvatar ? avatarContent : null}\n\t\t\t\t<span className=\"break-words\">{getEventText()}</span>\n\t\t\t\t{createdAt ? (\n\t\t\t\t\t<time className=\"text-[10px]\">\n\t\t\t\t\t\t{new Date(createdAt).toLocaleTimeString([], {\n\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t})}\n\t\t\t\t\t</time>\n\t\t\t\t) : null}\n\t\t\t</motion.div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<motion.div\n\t\t\tanimate={{ opacity: 1, scale: 1 }}\n\t\t\tclassName={cn(\"flex items-center pt-4 pb-8\", className)}\n\t\t\tinitial={{ opacity: 0, scale: 0.95 }}\n\t\t\ttransition={{ duration: 0.3, ease: \"easeOut\" }}\n\t\t>\n\t\t\t<div className=\"flex items-center gap-2 text-co-muted-foreground text-sm\">\n\t\t\t\t{showAvatar ? (\n\t\t\t\t\t<div className=\"flex flex-col justify-end\">{avatarContent}</div>\n\t\t\t\t) : null}\n\t\t\t\t<span className=\"px-2\">{getEventText()}</span>\n\t\t\t\t{createdAt && (\n\t\t\t\t\t<time className=\"text-[10px]\">\n\t\t\t\t\t\t{new Date(createdAt).toLocaleTimeString([], {\n\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t})}\n\t\t\t\t\t</time>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</motion.div>\n\t);\n};\n\nConversationEvent.displayName = \"ConversationEvent\";\n"],"mappings":"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"}
|
|
@@ -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":";;;;;;KA2CY,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"}
|
|
@@ -6,6 +6,7 @@ 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
8
|
import { filterSeenByIdsForViewer } from "./conversation-timeline-utils.js";
|
|
9
|
+
import { TimelineActivityGroup } from "./timeline-activity-group.js";
|
|
9
10
|
import { TimelineMessageGroup } from "./timeline-message-group.js";
|
|
10
11
|
import { useCallback, useMemo } from "react";
|
|
11
12
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -98,6 +99,17 @@ const ConversationTimelineList = ({ conversationId, items: timelineItems, classN
|
|
|
98
99
|
item: item.item
|
|
99
100
|
}, toolKey);
|
|
100
101
|
}
|
|
102
|
+
if (item.type === "activity_group") {
|
|
103
|
+
const groupKey$1 = item.firstItemId ?? item.items?.[0]?.id ?? `activity-group-${item.items?.[0]?.createdAt ?? index}`;
|
|
104
|
+
return /* @__PURE__ */ jsx(TimelineActivityGroup, {
|
|
105
|
+
availableAIAgents,
|
|
106
|
+
availableHumanAgents,
|
|
107
|
+
conversationId,
|
|
108
|
+
currentVisitorId,
|
|
109
|
+
group: item,
|
|
110
|
+
tools
|
|
111
|
+
}, groupKey$1);
|
|
112
|
+
}
|
|
101
113
|
const seenByIds = filterSeenByIdsForViewer(index === timeline.lastVisitorMessageGroupIndex && item.lastMessageId ? timeline.groupedMessages.getMessageSeenBy(item.lastMessageId) : EMPTY_SEEN_BY_IDS, currentVisitorId);
|
|
102
114
|
const seenByNames = seenByIds.length > 0 ? getSeenByNames(seenByIds) : EMPTY_SEEN_BY_NAMES;
|
|
103
115
|
const groupKey = item.lastMessageId ?? item.items?.[0]?.id ?? `group-${item.items?.[0]?.createdAt ?? index}`;
|
|
@@ -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 { 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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"}
|
|
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","groupKey"],"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 { TimelineActivityGroup } from \"./timeline-activity-group\";\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\tif (item.type === \"activity_group\") {\n\t\t\t\t\t\tconst groupKey =\n\t\t\t\t\t\t\titem.firstItemId ??\n\t\t\t\t\t\t\titem.items?.[0]?.id ??\n\t\t\t\t\t\t\t`activity-group-${item.items?.[0]?.createdAt ?? index}`;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<TimelineActivityGroup\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\tconversationId={conversationId}\n\t\t\t\t\t\t\t\tcurrentVisitorId={currentVisitorId}\n\t\t\t\t\t\t\t\tgroup={item}\n\t\t\t\t\t\t\t\tkey={groupKey}\n\t\t\t\t\t\t\t\ttools={tools}\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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"}
|
|
@@ -7,7 +7,8 @@ import { ConversationTimelineList, ConversationTimelineProps } from "./conversat
|
|
|
7
7
|
import { Icon, IconName, IconProps, IconVariant } from "./icons.js";
|
|
8
8
|
import { SendButton } from "./multimodal-input.js";
|
|
9
9
|
import { Root, RootProps } from "./root.js";
|
|
10
|
+
import { TimelineActivityGroup } from "./timeline-activity-group.js";
|
|
10
11
|
import { TimelineMessageGroup, TimelineMessageGroupProps } from "./timeline-message-group.js";
|
|
11
12
|
import { TimelineMessageItem, TimelineMessageItemProps } from "./timeline-message-item.js";
|
|
12
13
|
import { DefaultTrigger, DefaultTriggerProps } from "./trigger.js";
|
|
13
|
-
export { Content, type ContentProps, ConversationEvent, type ConversationEventProps, ConversationResolvedFeedback, ConversationTimelineList, type ConversationTimelineProps, DefaultTrigger, type DefaultTriggerProps, Icon, type IconName, type IconProps, type IconVariant, Root, type RootProps, SendButton, TimelineMessageGroup, type TimelineMessageGroupProps, TimelineMessageItem, type TimelineMessageItemProps, TypingIndicator, type TypingIndicatorProps, type TypingParticipant, type TypingParticipantType };
|
|
14
|
+
export { Content, type ContentProps, ConversationEvent, type ConversationEventProps, ConversationResolvedFeedback, ConversationTimelineList, type ConversationTimelineProps, DefaultTrigger, type DefaultTriggerProps, Icon, type IconName, type IconProps, type IconVariant, Root, type RootProps, SendButton, TimelineActivityGroup, TimelineMessageGroup, type TimelineMessageGroupProps, TimelineMessageItem, type TimelineMessageItemProps, TypingIndicator, type TypingIndicatorProps, type TypingParticipant, type TypingParticipantType };
|
|
@@ -5,9 +5,10 @@ import { Root } from "./root.js";
|
|
|
5
5
|
import { DefaultTrigger } from "./trigger.js";
|
|
6
6
|
import { ConversationResolvedFeedback } from "./conversation-resolved-feedback.js";
|
|
7
7
|
import { ConversationEvent } from "./conversation-event.js";
|
|
8
|
+
import { TimelineActivityGroup } from "./timeline-activity-group.js";
|
|
8
9
|
import { TimelineMessageItem } from "./timeline-message-item.js";
|
|
9
10
|
import { TimelineMessageGroup } from "./timeline-message-group.js";
|
|
10
11
|
import { ConversationTimelineList } from "./conversation-timeline.js";
|
|
11
12
|
import { SendButton } from "./multimodal-input.js";
|
|
12
13
|
|
|
13
|
-
export { Content, ConversationEvent, ConversationResolvedFeedback, ConversationTimelineList, DefaultTrigger, icons_default as Icon, Root, SendButton, TimelineMessageGroup, TimelineMessageItem, TypingIndicator };
|
|
14
|
+
export { Content, ConversationEvent, ConversationResolvedFeedback, ConversationTimelineList, DefaultTrigger, icons_default as Icon, Root, SendButton, TimelineActivityGroup, TimelineMessageGroup, TimelineMessageItem, TypingIndicator };
|
|
@@ -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":";;;;
|
|
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"}
|