@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.
Files changed (145) hide show
  1. package/README.md +3 -3
  2. package/hooks/index.d.ts +2 -2
  3. package/hooks/index.js +2 -2
  4. package/hooks/private/store/use-store-selector.d.ts.map +1 -1
  5. package/hooks/private/store/use-store-selector.js +8 -4
  6. package/hooks/private/store/use-store-selector.js.map +1 -1
  7. package/hooks/private/use-client-query.js +5 -2
  8. package/hooks/private/use-client-query.js.map +1 -1
  9. package/hooks/private/use-grouped-messages.d.ts +27 -2
  10. package/hooks/private/use-grouped-messages.d.ts.map +1 -1
  11. package/hooks/private/use-grouped-messages.js +154 -106
  12. package/hooks/private/use-grouped-messages.js.map +1 -1
  13. package/hooks/private/use-rest-client.js +2 -1
  14. package/hooks/private/use-rest-client.js.map +1 -1
  15. package/hooks/use-conversation-auto-seen.d.ts.map +1 -1
  16. package/hooks/use-conversation-auto-seen.js +9 -3
  17. package/hooks/use-conversation-auto-seen.js.map +1 -1
  18. package/hooks/use-conversation-page.d.ts.map +1 -1
  19. package/hooks/use-conversation-page.js +13 -3
  20. package/hooks/use-conversation-page.js.map +1 -1
  21. package/hooks/use-new-message-sound.d.ts.map +1 -1
  22. package/hooks/use-new-message-sound.js +2 -2
  23. package/hooks/use-new-message-sound.js.map +1 -1
  24. package/hooks/use-typing-sound.d.ts.map +1 -1
  25. package/hooks/use-typing-sound.js +2 -2
  26. package/hooks/use-typing-sound.js.map +1 -1
  27. package/index.d.ts +3 -3
  28. package/index.js +3 -3
  29. package/package.json +6 -12
  30. package/packages/tiny-markdown/src/context/index.d.ts +1 -0
  31. package/packages/tiny-markdown/src/context/tiny-markdown-context.d.ts +3 -0
  32. package/packages/tiny-markdown/src/hooks/index.d.ts +4 -0
  33. package/packages/tiny-markdown/src/hooks/use-caret-position.d.ts +1 -0
  34. package/packages/tiny-markdown/src/hooks/use-tiny-markdown.d.ts +1 -0
  35. package/packages/tiny-markdown/src/hooks/use-tiny-mention.d.ts +1 -0
  36. package/packages/tiny-markdown/src/hooks/use-tiny-shortcuts.d.ts +1 -0
  37. package/packages/tiny-markdown/src/index.d.ts +4 -0
  38. package/packages/tiny-markdown/src/types.d.ts +75 -0
  39. package/packages/tiny-markdown/src/types.d.ts.map +1 -0
  40. package/packages/tiny-markdown/src/utils/index.d.ts +3 -0
  41. package/packages/tiny-markdown/src/utils/markdown-parser.d.ts +1 -0
  42. package/packages/tiny-markdown/src/utils/mention-parser.d.ts +1 -0
  43. package/packages/tiny-markdown/src/utils/merge-refs.d.ts +1 -0
  44. package/packages/types/src/api/conversation.d.ts +300 -0
  45. package/packages/types/src/api/conversation.d.ts.map +1 -1
  46. package/packages/types/src/api/timeline-item.d.ts +225 -0
  47. package/packages/types/src/api/timeline-item.d.ts.map +1 -1
  48. package/packages/types/src/realtime-events.d.ts +228 -3
  49. package/packages/types/src/realtime-events.d.ts.map +1 -1
  50. package/packages/types/src/schemas.d.ts +75 -0
  51. package/packages/types/src/schemas.d.ts.map +1 -1
  52. package/primitives/avatar/image.d.ts +1 -1
  53. package/primitives/command-block-utils.d.ts +26 -0
  54. package/primitives/command-block-utils.d.ts.map +1 -0
  55. package/primitives/command-block-utils.js +310 -0
  56. package/primitives/command-block-utils.js.map +1 -0
  57. package/primitives/index.d.ts +7 -3
  58. package/primitives/index.js +11 -2
  59. package/primitives/index.parts.d.ts +6 -2
  60. package/primitives/index.parts.js +5 -1
  61. package/primitives/timeline-code-block.d.ts +32 -0
  62. package/primitives/timeline-code-block.d.ts.map +1 -0
  63. package/primitives/timeline-code-block.js +66 -0
  64. package/primitives/timeline-code-block.js.map +1 -0
  65. package/primitives/timeline-command-block.d.ts +29 -0
  66. package/primitives/timeline-command-block.d.ts.map +1 -0
  67. package/primitives/timeline-command-block.js +97 -0
  68. package/primitives/timeline-command-block.js.map +1 -0
  69. package/primitives/timeline-item-group.d.ts.map +1 -1
  70. package/primitives/timeline-item-group.js +5 -15
  71. package/primitives/timeline-item-group.js.map +1 -1
  72. package/primitives/timeline-item.d.ts +21 -1
  73. package/primitives/timeline-item.d.ts.map +1 -1
  74. package/primitives/timeline-item.js +148 -83
  75. package/primitives/timeline-item.js.map +1 -1
  76. package/primitives/timeline-message-layout.d.ts +9 -0
  77. package/primitives/timeline-message-layout.d.ts.map +1 -0
  78. package/primitives/timeline-message-layout.js +20 -0
  79. package/primitives/timeline-message-layout.js.map +1 -0
  80. package/provider.d.ts.map +1 -1
  81. package/provider.js +1 -7
  82. package/provider.js.map +1 -1
  83. package/realtime/event-filter.js +4 -3
  84. package/realtime/event-filter.js.map +1 -1
  85. package/realtime/provider.d.ts +0 -1
  86. package/realtime/provider.d.ts.map +1 -1
  87. package/realtime/provider.js +29 -34
  88. package/realtime/provider.js.map +1 -1
  89. package/sounds/sound-data.d.ts +6 -0
  90. package/sounds/sound-data.d.ts.map +1 -0
  91. package/sounds/sound-data.js +7 -0
  92. package/sounds/sound-data.js.map +1 -0
  93. package/styles.css +2 -0
  94. package/support/components/avatar.js +3 -3
  95. package/support/components/avatar.js.map +1 -1
  96. package/support/components/button.d.ts +2 -2
  97. package/support/components/button.d.ts.map +1 -1
  98. package/support/components/button.js +1 -0
  99. package/support/components/button.js.map +1 -1
  100. package/support/components/conversation-event.d.ts +3 -0
  101. package/support/components/conversation-event.d.ts.map +1 -1
  102. package/support/components/conversation-event.js +47 -16
  103. package/support/components/conversation-event.js.map +1 -1
  104. package/support/components/conversation-timeline.d.ts.map +1 -1
  105. package/support/components/conversation-timeline.js +12 -0
  106. package/support/components/conversation-timeline.js.map +1 -1
  107. package/support/components/index.d.ts +2 -1
  108. package/support/components/index.js +2 -1
  109. package/support/components/timeline-activity-group.d.ts +25 -0
  110. package/support/components/timeline-activity-group.d.ts.map +1 -0
  111. package/support/components/timeline-activity-group.js +104 -0
  112. package/support/components/timeline-activity-group.js.map +1 -0
  113. package/support/components/timeline-code-block.d.ts +14 -0
  114. package/support/components/timeline-code-block.d.ts.map +1 -0
  115. package/support/components/timeline-code-block.js +44 -0
  116. package/support/components/timeline-code-block.js.map +1 -0
  117. package/support/components/timeline-command-block.d.ts +12 -0
  118. package/support/components/timeline-command-block.d.ts.map +1 -0
  119. package/support/components/timeline-command-block.js +42 -0
  120. package/support/components/timeline-command-block.js.map +1 -0
  121. package/support/components/timeline-message-item.d.ts +2 -1
  122. package/support/components/timeline-message-item.d.ts.map +1 -1
  123. package/support/components/timeline-message-item.js +23 -3
  124. package/support/components/timeline-message-item.js.map +1 -1
  125. package/support/pages/home.js +1 -1
  126. package/support/pages/home.js.map +1 -1
  127. package/support/store/support-store.d.ts.map +1 -1
  128. package/support/store/support-store.js +4 -4
  129. package/support/store/support-store.js.map +1 -1
  130. package/support/{support-DmViRaga.css → support-Dc5L__HC.css} +15 -15
  131. package/support/{support-DmViRaga.css.map → support-Dc5L__HC.css.map} +1 -1
  132. package/{tailwind.css → support/support.css} +14 -14
  133. package/support-config.d.ts +31 -4
  134. package/support-config.d.ts.map +1 -1
  135. package/support-config.js +52 -4
  136. package/support-config.js.map +1 -1
  137. package/support.css +1 -2
  138. package/utils/metadata-hash.d.ts +1 -1
  139. package/utils/metadata-hash.js +9 -4
  140. package/utils/metadata-hash.js.map +1 -1
  141. package/utils/timeline-item-sender.d.ts +17 -0
  142. package/utils/timeline-item-sender.d.ts.map +1 -0
  143. package/utils/timeline-item-sender.js +43 -0
  144. package/utils/timeline-item-sender.js.map +1 -0
  145. 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 justify-center pt-4 pb-8",
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-xs",
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: isAI ? /* @__PURE__ */ jsx(Avatar, {
52
- className: "size-5 flex-shrink-0",
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=\"flex items-center justify-center pt-4 pb-8\"\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-xs\">\n\t\t\t\t<div className=\"flex flex-col justify-end\">\n\t\t\t\t\t{isAI ? (\n\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\tclassName=\"size-5 flex-shrink-0\"\n\t\t\t\t\t\t\timage={aiAgent?.image}\n\t\t\t\t\t\t\tisAI\n\t\t\t\t\t\t\tname={aiAgent?.name || text(\"common.fallbacks.cossistant\")}\n\t\t\t\t\t\t\tshowBackground={!!aiAgent?.image}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\tclassName=\"size-5 flex-shrink-0\"\n\t\t\t\t\t\t\timage={humanAgent?.image}\n\t\t\t\t\t\t\tname={humanAgent?.name || text(\"common.fallbacks.someone\")}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\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":";;;;;;AAiBA,MAAaA,qBAAuD,EACnE,OACA,mBACA,WACA,2BACK;CACL,MAAM,OAAO,gBAAgB;CAC7B,MAAM,OAAO,MAAM,mBAAmB;CACtC,MAAM,aAAa,qBAAqB,MACtC,UAAU,MAAM,OAAO,MAAM,YAC9B;CACD,MAAM,UAAU,kBAAkB,MAChC,UAAU,MAAM,OAAO,MAAM,eAC9B;CAGD,MAAM,YAAY,OACf,SAAS,QAAQ,KAAK,8BAA8B,GACpD,YAAY,QAAQ,KAAK,2BAA2B;CAGvD,MAAM,qBAAqB;AAC1B,UAAQ,MAAM,WAAd;GACC,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,aACJ,QAAO,KAAK,0CAA0C,EACrD,WACA,CAAC;GACH,KAAK,wBACJ,QAAO,KAAK,oDAAoD,EAC/D,WACA,CAAC;GACH,KAAK,qBACJ,QAAO,KAAK,iDAAiD,EAC5D,WACA,CAAC;GACH,KAAK,mBACJ,QAAO,KAAK,+CAA+C,EAC1D,WACA,CAAC;GACH,KAAK,iBACJ,QAAO,KAAK,6CAA6C,EACxD,WACA,CAAC;GACH,KAAK,mBACJ,QAAO,KAAK,+CAA+C,EAC1D,WACA,CAAC;GACH,KAAK,YACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,cACJ,QAAO,KAAK,0CAA0C,EACrD,WACA,CAAC;GACH,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,WACJ,QAAO,KAAK,wCAAwC,EACnD,WACA,CAAC;GACH,KAAK,kBACJ,QAAO,KAAK,8CAA8C,EACzD,WACA,CAAC;GACH,KAAK,oBACJ,QAAO,KAAK,gDAAgD,EAC3D,WACA,CAAC;GACH,KAAK,qBACJ,QAAO,KAAK,iDAAiD,EAC5D,WACA,CAAC;GACH,QACC,QAAO,KAAK,uCAAuC,EAClD,WACA,CAAC;;;AAIL,QACC,oBAAC,OAAO;EACP,SAAS;GAAE,SAAS;GAAG,OAAO;GAAG;EACjC,WAAU;EACV,SAAS;GAAE,SAAS;GAAG,OAAO;GAAM;EACpC,YAAY;GAAE,UAAU;GAAK,MAAM;GAAW;YAE9C,qBAAC;GAAI,WAAU;;IACd,oBAAC;KAAI,WAAU;eACb,OACA,oBAAC;MACA,WAAU;MACV,OAAO,SAAS;MAChB;MACA,MAAM,SAAS,QAAQ,KAAK,8BAA8B;MAC1D,gBAAgB,CAAC,CAAC,SAAS;OAC1B,GAEF,oBAAC;MACA,WAAU;MACV,OAAO,YAAY;MACnB,MAAM,YAAY,QAAQ,KAAK,2BAA2B;OACzD;MAEE;IACN,oBAAC;KAAK,WAAU;eAAQ,cAAc;MAAQ;IAC7C,aACA,oBAAC;KAAK,WAAU;eACd,IAAI,KAAK,UAAU,CAAC,mBAAmB,EAAE,EAAE;MAC3C,MAAM;MACN,QAAQ;MACR,CAAC;MACI;;IAEH;GACM;;AAIf,kBAAkB,cAAc"}
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":";;;;;;KA0CY,6BAAA;QACL;EADK,cAAA,EAAA,MAAA;AAKZ,CAAA;AAIY,KAJA,kCAAA,GAMX;EAGW,SAAA,EARA,KAAA,CAAM,aAQmB,CARL,6BAQK,CAAA;CAE7B;AAEY,KATR,yBAAA,GAA4B,MASpB,CAAA,MAAA,EAPnB,kCAOmB,CAAA;AACG,KALX,yBAAA,GAKW;EAEd,cAAA,EAAA,MAAA;EAED,KAAA,EAPA,YAOA,EAAA;EACa,SAAA,CAAA,EAAA,MAAA;EACd,iBAAM,EAPO,gBAOP,EAAA;EAAS,oBAAA,EANC,mBAMD,EAAA;EAGT,gBAAA,CAAA,EAAA,MAAA;UAPJ;;UAED;uBACa;QACd,KAAA,CAAM;;cAGA,0BAA0B,KAAA,CAAM,GAAG"}
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":";;;;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"}