@memberjunction/ng-conversations 5.43.0 → 5.45.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 (405) hide show
  1. package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts +0 -1
  2. package/dist/lib/components/active-tasks/active-tasks-panel.component.d.ts.map +1 -1
  3. package/dist/lib/components/active-tasks/active-tasks-panel.component.js +56 -52
  4. package/dist/lib/components/active-tasks/active-tasks-panel.component.js.map +1 -1
  5. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts +3 -1
  6. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts.map +1 -1
  7. package/dist/lib/components/artifact/artifact-share-modal.component.js +52 -52
  8. package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
  9. package/dist/lib/components/collection/collection-form-modal.component.d.ts.map +1 -1
  10. package/dist/lib/components/collection/collection-form-modal.component.js +10 -14
  11. package/dist/lib/components/collection/collection-form-modal.component.js.map +1 -1
  12. package/dist/lib/components/collection/collection-share-modal.component.d.ts +3 -1
  13. package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
  14. package/dist/lib/components/collection/collection-share-modal.component.js +56 -56
  15. package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
  16. package/dist/lib/components/collection/collection-tree.component.d.ts +3 -1
  17. package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
  18. package/dist/lib/components/collection/collection-tree.component.js +10 -7
  19. package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
  20. package/dist/lib/components/collection/collection-view.component.d.ts +3 -1
  21. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  22. package/dist/lib/components/collection/collection-view.component.js +29 -41
  23. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  24. package/dist/lib/components/collection/collections-full-view.component.d.ts +4 -0
  25. package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
  26. package/dist/lib/components/collection/collections-full-view.component.js +134 -166
  27. package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
  28. package/dist/lib/components/composer/ai-composer.component.d.ts +103 -0
  29. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -0
  30. package/dist/lib/components/composer/ai-composer.component.js +263 -0
  31. package/dist/lib/components/composer/ai-composer.component.js.map +1 -0
  32. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +76 -12
  33. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  34. package/dist/lib/components/conversation/conversation-chat-area.component.js +522 -158
  35. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  36. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +1 -1
  37. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  38. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  39. package/dist/lib/components/conversation/pinned-messages-panel.component.js +6 -9
  40. package/dist/lib/components/conversation/pinned-messages-panel.component.js.map +1 -1
  41. package/dist/lib/components/library/library-full-view.component.d.ts.map +1 -1
  42. package/dist/lib/components/library/library-full-view.component.js +20 -24
  43. package/dist/lib/components/library/library-full-view.component.js.map +1 -1
  44. package/dist/lib/components/members/members-modal.component.d.ts.map +1 -1
  45. package/dist/lib/components/members/members-modal.component.js +10 -11
  46. package/dist/lib/components/members/members-modal.component.js.map +1 -1
  47. package/dist/lib/components/message/message-input.component.d.ts +87 -23
  48. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  49. package/dist/lib/components/message/message-input.component.js +245 -158
  50. package/dist/lib/components/message/message-input.component.js.map +1 -1
  51. package/dist/lib/components/message/message-item.component.d.ts +11 -3
  52. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  53. package/dist/lib/components/message/message-item.component.js +73 -21
  54. package/dist/lib/components/message/message-item.component.js.map +1 -1
  55. package/dist/lib/components/message/message-list.component.js +6 -9
  56. package/dist/lib/components/message/message-list.component.js.map +1 -1
  57. package/dist/lib/components/overlay/chat-overlay.component.d.ts +4 -1
  58. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  59. package/dist/lib/components/overlay/chat-overlay.component.js +9 -4
  60. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  61. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +45 -0
  62. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -1
  63. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +10 -0
  64. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -1
  65. package/dist/lib/components/realtime/channels/client-context-channel.d.ts +46 -0
  66. package/dist/lib/components/realtime/channels/client-context-channel.d.ts.map +1 -0
  67. package/dist/lib/components/realtime/channels/client-context-channel.js +174 -0
  68. package/dist/lib/components/realtime/channels/client-context-channel.js.map +1 -0
  69. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts +123 -0
  70. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.d.ts.map +1 -0
  71. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js +397 -0
  72. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js.map +1 -0
  73. package/dist/lib/components/realtime/media/media-channel-state.d.ts +103 -0
  74. package/dist/lib/components/realtime/media/media-channel-state.d.ts.map +1 -0
  75. package/dist/lib/components/realtime/media/media-channel-state.js +143 -0
  76. package/dist/lib/components/realtime/media/media-channel-state.js.map +1 -0
  77. package/dist/lib/components/realtime/media/media-channel-tools.d.ts +24 -0
  78. package/dist/lib/components/realtime/media/media-channel-tools.d.ts.map +1 -0
  79. package/dist/lib/components/realtime/media/media-channel-tools.js +107 -0
  80. package/dist/lib/components/realtime/media/media-channel-tools.js.map +1 -0
  81. package/dist/lib/components/realtime/media/media-channel.d.ts +89 -0
  82. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -0
  83. package/dist/lib/components/realtime/media/media-channel.js +253 -0
  84. package/dist/lib/components/realtime/media/media-channel.js.map +1 -0
  85. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts +141 -0
  86. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts.map +1 -0
  87. package/dist/lib/components/realtime/media/realtime-media-surface.component.js +574 -0
  88. package/dist/lib/components/realtime/media/realtime-media-surface.component.js.map +1 -0
  89. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +59 -14
  90. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
  91. package/dist/lib/components/realtime/realtime-activity-rail.component.js +277 -74
  92. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
  93. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +28 -27
  94. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  95. package/dist/lib/components/realtime/realtime-agent-banner.component.js +144 -143
  96. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  97. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +12 -0
  98. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  99. package/dist/lib/components/realtime/realtime-agent-picker.component.js +105 -43
  100. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  101. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts +2 -2
  102. package/dist/lib/components/realtime/realtime-audio-visuals.d.ts.map +1 -1
  103. package/dist/lib/components/realtime/realtime-audio-visuals.js.map +1 -1
  104. package/dist/lib/components/realtime/realtime-composer.component.d.ts +41 -7
  105. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  106. package/dist/lib/components/realtime/realtime-composer.component.js +216 -102
  107. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  108. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +0 -2
  109. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
  110. package/dist/lib/components/realtime/realtime-delegation-card.component.js +67 -71
  111. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
  112. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +364 -44
  113. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  114. package/dist/lib/components/realtime/realtime-session-overlay.component.js +839 -153
  115. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  116. package/dist/lib/components/realtime/realtime-session-state.d.ts +5 -5
  117. package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
  118. package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
  119. package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts +70 -0
  120. package/dist/lib/components/realtime/realtime-surface-tab-style.d.ts.map +1 -0
  121. package/dist/lib/components/realtime/realtime-surface-tab-style.js +115 -0
  122. package/dist/lib/components/realtime/realtime-surface-tab-style.js.map +1 -0
  123. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts +55 -57
  124. package/dist/lib/components/realtime/realtime-surface-tabs.component.d.ts.map +1 -1
  125. package/dist/lib/components/realtime/realtime-surface-tabs.component.js +165 -143
  126. package/dist/lib/components/realtime/realtime-surface-tabs.component.js.map +1 -1
  127. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts +80 -71
  128. package/dist/lib/components/realtime/realtime-surface-tabs.model.d.ts.map +1 -1
  129. package/dist/lib/components/realtime/realtime-surface-tabs.model.js +83 -113
  130. package/dist/lib/components/realtime/realtime-surface-tabs.model.js.map +1 -1
  131. package/dist/lib/components/realtime/realtime-ui-config.d.ts +270 -0
  132. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -0
  133. package/dist/lib/components/realtime/realtime-ui-config.js +212 -0
  134. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -0
  135. package/dist/lib/components/search/search-panel.component.d.ts +2 -0
  136. package/dist/lib/components/search/search-panel.component.d.ts.map +1 -1
  137. package/dist/lib/components/search/search-panel.component.js +92 -101
  138. package/dist/lib/components/search/search-panel.component.js.map +1 -1
  139. package/dist/lib/components/share/share-modal.component.d.ts.map +1 -1
  140. package/dist/lib/components/share/share-modal.component.js +10 -11
  141. package/dist/lib/components/share/share-modal.component.js.map +1 -1
  142. package/dist/lib/components/shared/user-picker.component.d.ts.map +1 -1
  143. package/dist/lib/components/shared/user-picker.component.js +12 -15
  144. package/dist/lib/components/shared/user-picker.component.js.map +1 -1
  145. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +11 -3
  146. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
  147. package/dist/lib/components/sidebar/conversation-sidebar.component.js +34 -10
  148. package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
  149. package/dist/lib/components/sidebar/routines-section.component.d.ts +73 -0
  150. package/dist/lib/components/sidebar/routines-section.component.d.ts.map +1 -0
  151. package/dist/lib/components/sidebar/routines-section.component.js +211 -0
  152. package/dist/lib/components/sidebar/routines-section.component.js.map +1 -0
  153. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +12 -0
  154. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
  155. package/dist/lib/components/tasks/tasks-dropdown.component.js +37 -1
  156. package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
  157. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +16 -5
  158. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  159. package/dist/lib/components/workspace/conversation-workspace.component.js +51 -31
  160. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  161. package/dist/lib/composer-plugins/agent-mention.provider.d.ts +16 -0
  162. package/dist/lib/composer-plugins/agent-mention.provider.d.ts.map +1 -0
  163. package/dist/lib/composer-plugins/agent-mention.provider.js +28 -0
  164. package/dist/lib/composer-plugins/agent-mention.provider.js.map +1 -0
  165. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts +20 -0
  166. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts.map +1 -0
  167. package/dist/lib/composer-plugins/base-conversation-mention.provider.js +32 -0
  168. package/dist/lib/composer-plugins/base-conversation-mention.provider.js.map +1 -0
  169. package/dist/lib/composer-plugins/load-composer-plugins.d.ts +9 -0
  170. package/dist/lib/composer-plugins/load-composer-plugins.d.ts.map +1 -0
  171. package/dist/lib/composer-plugins/load-composer-plugins.js +17 -0
  172. package/dist/lib/composer-plugins/load-composer-plugins.js.map +1 -0
  173. package/dist/lib/composer-plugins/record-mention.provider.d.ts +14 -0
  174. package/dist/lib/composer-plugins/record-mention.provider.d.ts.map +1 -0
  175. package/dist/lib/composer-plugins/record-mention.provider.js +26 -0
  176. package/dist/lib/composer-plugins/record-mention.provider.js.map +1 -0
  177. package/dist/lib/composer-plugins/skill-command.provider.d.ts +15 -0
  178. package/dist/lib/composer-plugins/skill-command.provider.d.ts.map +1 -0
  179. package/dist/lib/composer-plugins/skill-command.provider.js +27 -0
  180. package/dist/lib/composer-plugins/skill-command.provider.js.map +1 -0
  181. package/dist/lib/conversations.module.d.ts +68 -64
  182. package/dist/lib/conversations.module.d.ts.map +1 -1
  183. package/dist/lib/conversations.module.js +69 -18
  184. package/dist/lib/conversations.module.js.map +1 -1
  185. package/dist/lib/models/conversation-state.model.d.ts +6 -3
  186. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  187. package/dist/lib/models/conversation-state.model.js.map +1 -1
  188. package/dist/lib/services/conversation-agent.service.d.ts +9 -2
  189. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  190. package/dist/lib/services/conversation-agent.service.js +26 -2
  191. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  192. package/dist/lib/services/conversation-attachment.service.d.ts +1 -1
  193. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  194. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  195. package/dist/lib/services/mention-autocomplete.service.d.ts +42 -19
  196. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  197. package/dist/lib/services/mention-autocomplete.service.js +113 -18
  198. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  199. package/dist/lib/services/realtime-audio-recorder.d.ts +143 -0
  200. package/dist/lib/services/realtime-audio-recorder.d.ts.map +1 -0
  201. package/dist/lib/services/realtime-audio-recorder.js +379 -0
  202. package/dist/lib/services/realtime-audio-recorder.js.map +1 -0
  203. package/dist/lib/services/realtime-pcm-wav.d.ts +75 -0
  204. package/dist/lib/services/realtime-pcm-wav.d.ts.map +1 -0
  205. package/dist/lib/services/realtime-pcm-wav.js +205 -0
  206. package/dist/lib/services/realtime-pcm-wav.js.map +1 -0
  207. package/dist/lib/services/realtime-session-review.service.d.ts +28 -1
  208. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
  209. package/dist/lib/services/realtime-session-review.service.js +12 -3
  210. package/dist/lib/services/realtime-session-review.service.js.map +1 -1
  211. package/dist/lib/services/realtime-session.service.d.ts +210 -20
  212. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  213. package/dist/lib/services/realtime-session.service.js +452 -21
  214. package/dist/lib/services/realtime-session.service.js.map +1 -1
  215. package/dist/lib/services/realtime-sessions-adapter.js +1 -1
  216. package/dist/lib/services/realtime-sessions-adapter.js.map +1 -1
  217. package/dist/lib/services/ui-command-handler.service.d.ts +7 -2
  218. package/dist/lib/services/ui-command-handler.service.d.ts.map +1 -1
  219. package/dist/lib/services/ui-command-handler.service.js +6 -2
  220. package/dist/lib/services/ui-command-handler.service.js.map +1 -1
  221. package/dist/lib/utils/plan-mode-preference.d.ts +62 -0
  222. package/dist/lib/utils/plan-mode-preference.d.ts.map +1 -0
  223. package/dist/lib/utils/plan-mode-preference.js +130 -0
  224. package/dist/lib/utils/plan-mode-preference.js.map +1 -0
  225. package/dist/public-api.d.ts +29 -3
  226. package/dist/public-api.d.ts.map +1 -1
  227. package/dist/public-api.js +46 -3
  228. package/dist/public-api.js.map +1 -1
  229. package/package.json +30 -26
  230. package/dist/__tests__/attachment-badge.test.d.ts +0 -2
  231. package/dist/__tests__/attachment-badge.test.d.ts.map +0 -1
  232. package/dist/__tests__/attachment-badge.test.js +0 -66
  233. package/dist/__tests__/attachment-badge.test.js.map +0 -1
  234. package/dist/__tests__/channel-optional-surface.test.d.ts +0 -2
  235. package/dist/__tests__/channel-optional-surface.test.d.ts.map +0 -1
  236. package/dist/__tests__/channel-optional-surface.test.js +0 -53
  237. package/dist/__tests__/channel-optional-surface.test.js.map +0 -1
  238. package/dist/__tests__/chat-events.test.d.ts +0 -14
  239. package/dist/__tests__/chat-events.test.d.ts.map +0 -1
  240. package/dist/__tests__/chat-events.test.js +0 -109
  241. package/dist/__tests__/chat-events.test.js.map +0 -1
  242. package/dist/__tests__/collections-full-view.test.d.ts +0 -2
  243. package/dist/__tests__/collections-full-view.test.d.ts.map +0 -1
  244. package/dist/__tests__/collections-full-view.test.js +0 -225
  245. package/dist/__tests__/collections-full-view.test.js.map +0 -1
  246. package/dist/__tests__/conversation-cache.test.d.ts +0 -2
  247. package/dist/__tests__/conversation-cache.test.d.ts.map +0 -1
  248. package/dist/__tests__/conversation-cache.test.js +0 -233
  249. package/dist/__tests__/conversation-cache.test.js.map +0 -1
  250. package/dist/__tests__/conversation-naming.test.d.ts +0 -2
  251. package/dist/__tests__/conversation-naming.test.d.ts.map +0 -1
  252. package/dist/__tests__/conversation-naming.test.js +0 -110
  253. package/dist/__tests__/conversation-naming.test.js.map +0 -1
  254. package/dist/__tests__/delegation-result-parser.test.d.ts +0 -2
  255. package/dist/__tests__/delegation-result-parser.test.d.ts.map +0 -1
  256. package/dist/__tests__/delegation-result-parser.test.js +0 -107
  257. package/dist/__tests__/delegation-result-parser.test.js.map +0 -1
  258. package/dist/__tests__/distinct-artifacts.test.d.ts +0 -2
  259. package/dist/__tests__/distinct-artifacts.test.d.ts.map +0 -1
  260. package/dist/__tests__/distinct-artifacts.test.js +0 -56
  261. package/dist/__tests__/distinct-artifacts.test.js.map +0 -1
  262. package/dist/__tests__/event-wiring.test.d.ts +0 -15
  263. package/dist/__tests__/event-wiring.test.d.ts.map +0 -1
  264. package/dist/__tests__/event-wiring.test.js +0 -100
  265. package/dist/__tests__/event-wiring.test.js.map +0 -1
  266. package/dist/__tests__/index.test.d.ts +0 -2
  267. package/dist/__tests__/index.test.d.ts.map +0 -1
  268. package/dist/__tests__/index.test.js +0 -7
  269. package/dist/__tests__/index.test.js.map +0 -1
  270. package/dist/__tests__/narration-template.test.d.ts +0 -2
  271. package/dist/__tests__/narration-template.test.d.ts.map +0 -1
  272. package/dist/__tests__/narration-template.test.js +0 -76
  273. package/dist/__tests__/narration-template.test.js.map +0 -1
  274. package/dist/__tests__/notification-model.test.d.ts +0 -2
  275. package/dist/__tests__/notification-model.test.d.ts.map +0 -1
  276. package/dist/__tests__/notification-model.test.js +0 -68
  277. package/dist/__tests__/notification-model.test.js.map +0 -1
  278. package/dist/__tests__/realtime-agent-picker-models.test.d.ts +0 -2
  279. package/dist/__tests__/realtime-agent-picker-models.test.d.ts.map +0 -1
  280. package/dist/__tests__/realtime-agent-picker-models.test.js +0 -49
  281. package/dist/__tests__/realtime-agent-picker-models.test.js.map +0 -1
  282. package/dist/__tests__/realtime-audio-visuals.test.d.ts +0 -2
  283. package/dist/__tests__/realtime-audio-visuals.test.d.ts.map +0 -1
  284. package/dist/__tests__/realtime-audio-visuals.test.js +0 -123
  285. package/dist/__tests__/realtime-audio-visuals.test.js.map +0 -1
  286. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts +0 -2
  287. package/dist/__tests__/realtime-delegation-card-cancel.test.d.ts.map +0 -1
  288. package/dist/__tests__/realtime-delegation-card-cancel.test.js +0 -48
  289. package/dist/__tests__/realtime-delegation-card-cancel.test.js.map +0 -1
  290. package/dist/__tests__/realtime-disclosure.test.d.ts +0 -2
  291. package/dist/__tests__/realtime-disclosure.test.d.ts.map +0 -1
  292. package/dist/__tests__/realtime-disclosure.test.js +0 -164
  293. package/dist/__tests__/realtime-disclosure.test.js.map +0 -1
  294. package/dist/__tests__/realtime-pairing.test.d.ts +0 -2
  295. package/dist/__tests__/realtime-pairing.test.d.ts.map +0 -1
  296. package/dist/__tests__/realtime-pairing.test.js +0 -207
  297. package/dist/__tests__/realtime-pairing.test.js.map +0 -1
  298. package/dist/__tests__/realtime-review-lifecycle.test.d.ts +0 -2
  299. package/dist/__tests__/realtime-review-lifecycle.test.d.ts.map +0 -1
  300. package/dist/__tests__/realtime-review-lifecycle.test.js +0 -154
  301. package/dist/__tests__/realtime-review-lifecycle.test.js.map +0 -1
  302. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts +0 -2
  303. package/dist/__tests__/realtime-session-cancel-usage.test.d.ts.map +0 -1
  304. package/dist/__tests__/realtime-session-cancel-usage.test.js +0 -230
  305. package/dist/__tests__/realtime-session-cancel-usage.test.js.map +0 -1
  306. package/dist/__tests__/realtime-session-channels.test.d.ts +0 -2
  307. package/dist/__tests__/realtime-session-channels.test.d.ts.map +0 -1
  308. package/dist/__tests__/realtime-session-channels.test.js +0 -252
  309. package/dist/__tests__/realtime-session-channels.test.js.map +0 -1
  310. package/dist/__tests__/realtime-session-client-tools.test.d.ts +0 -2
  311. package/dist/__tests__/realtime-session-client-tools.test.d.ts.map +0 -1
  312. package/dist/__tests__/realtime-session-client-tools.test.js +0 -103
  313. package/dist/__tests__/realtime-session-client-tools.test.js.map +0 -1
  314. package/dist/__tests__/realtime-session-minimized.test.d.ts +0 -2
  315. package/dist/__tests__/realtime-session-minimized.test.d.ts.map +0 -1
  316. package/dist/__tests__/realtime-session-minimized.test.js +0 -32
  317. package/dist/__tests__/realtime-session-minimized.test.js.map +0 -1
  318. package/dist/__tests__/realtime-session-mint.test.d.ts +0 -2
  319. package/dist/__tests__/realtime-session-mint.test.d.ts.map +0 -1
  320. package/dist/__tests__/realtime-session-mint.test.js +0 -69
  321. package/dist/__tests__/realtime-session-mint.test.js.map +0 -1
  322. package/dist/__tests__/realtime-session-policy.test.d.ts +0 -2
  323. package/dist/__tests__/realtime-session-policy.test.d.ts.map +0 -1
  324. package/dist/__tests__/realtime-session-policy.test.js +0 -303
  325. package/dist/__tests__/realtime-session-policy.test.js.map +0 -1
  326. package/dist/__tests__/realtime-session-review.service.test.d.ts +0 -2
  327. package/dist/__tests__/realtime-session-review.service.test.d.ts.map +0 -1
  328. package/dist/__tests__/realtime-session-review.service.test.js +0 -743
  329. package/dist/__tests__/realtime-session-review.service.test.js.map +0 -1
  330. package/dist/__tests__/realtime-session-state.test.d.ts +0 -2
  331. package/dist/__tests__/realtime-session-state.test.d.ts.map +0 -1
  332. package/dist/__tests__/realtime-session-state.test.js +0 -83
  333. package/dist/__tests__/realtime-session-state.test.js.map +0 -1
  334. package/dist/__tests__/realtime-session-timeline-card.test.d.ts +0 -2
  335. package/dist/__tests__/realtime-session-timeline-card.test.d.ts.map +0 -1
  336. package/dist/__tests__/realtime-session-timeline-card.test.js +0 -106
  337. package/dist/__tests__/realtime-session-timeline-card.test.js.map +0 -1
  338. package/dist/__tests__/realtime-session-timeline.test.d.ts +0 -2
  339. package/dist/__tests__/realtime-session-timeline.test.d.ts.map +0 -1
  340. package/dist/__tests__/realtime-session-timeline.test.js +0 -142
  341. package/dist/__tests__/realtime-session-timeline.test.js.map +0 -1
  342. package/dist/__tests__/realtime-sessions-adapter.test.d.ts +0 -19
  343. package/dist/__tests__/realtime-sessions-adapter.test.d.ts.map +0 -1
  344. package/dist/__tests__/realtime-sessions-adapter.test.js +0 -188
  345. package/dist/__tests__/realtime-sessions-adapter.test.js.map +0 -1
  346. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts +0 -2
  347. package/dist/__tests__/realtime-surface-panel-prefs.test.d.ts.map +0 -1
  348. package/dist/__tests__/realtime-surface-panel-prefs.test.js +0 -100
  349. package/dist/__tests__/realtime-surface-panel-prefs.test.js.map +0 -1
  350. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts +0 -2
  351. package/dist/__tests__/realtime-surface-tabs-model.test.d.ts.map +0 -1
  352. package/dist/__tests__/realtime-surface-tabs-model.test.js +0 -193
  353. package/dist/__tests__/realtime-surface-tabs-model.test.js.map +0 -1
  354. package/dist/__tests__/remote-browser-audio-player.test.d.ts +0 -2
  355. package/dist/__tests__/remote-browser-audio-player.test.d.ts.map +0 -1
  356. package/dist/__tests__/remote-browser-audio-player.test.js +0 -137
  357. package/dist/__tests__/remote-browser-audio-player.test.js.map +0 -1
  358. package/dist/__tests__/remote-browser-channel.test.d.ts +0 -2
  359. package/dist/__tests__/remote-browser-channel.test.d.ts.map +0 -1
  360. package/dist/__tests__/remote-browser-channel.test.js +0 -585
  361. package/dist/__tests__/remote-browser-channel.test.js.map +0 -1
  362. package/dist/__tests__/search-service.test.d.ts +0 -2
  363. package/dist/__tests__/search-service.test.d.ts.map +0 -1
  364. package/dist/__tests__/search-service.test.js +0 -114
  365. package/dist/__tests__/search-service.test.js.map +0 -1
  366. package/dist/__tests__/slot-defaults.test.d.ts +0 -24
  367. package/dist/__tests__/slot-defaults.test.d.ts.map +0 -1
  368. package/dist/__tests__/slot-defaults.test.js +0 -63
  369. package/dist/__tests__/slot-defaults.test.js.map +0 -1
  370. package/dist/__tests__/toast-service.test.d.ts +0 -2
  371. package/dist/__tests__/toast-service.test.d.ts.map +0 -1
  372. package/dist/__tests__/toast-service.test.js +0 -143
  373. package/dist/__tests__/toast-service.test.js.map +0 -1
  374. package/dist/__tests__/user-authorization.test.d.ts +0 -2
  375. package/dist/__tests__/user-authorization.test.d.ts.map +0 -1
  376. package/dist/__tests__/user-authorization.test.js +0 -97
  377. package/dist/__tests__/user-authorization.test.js.map +0 -1
  378. package/dist/__tests__/voice-session-narration.test.d.ts +0 -2
  379. package/dist/__tests__/voice-session-narration.test.d.ts.map +0 -1
  380. package/dist/__tests__/voice-session-narration.test.js +0 -609
  381. package/dist/__tests__/voice-session-narration.test.js.map +0 -1
  382. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts +0 -2
  383. package/dist/__tests__/whiteboard-artifact-viewer.test.d.ts.map +0 -1
  384. package/dist/__tests__/whiteboard-artifact-viewer.test.js +0 -101
  385. package/dist/__tests__/whiteboard-artifact-viewer.test.js.map +0 -1
  386. package/dist/__tests__/whiteboard-channel.test.d.ts +0 -2
  387. package/dist/__tests__/whiteboard-channel.test.d.ts.map +0 -1
  388. package/dist/__tests__/whiteboard-channel.test.js +0 -260
  389. package/dist/__tests__/whiteboard-channel.test.js.map +0 -1
  390. package/dist/__tests__/whiteboard-restore-state.test.d.ts +0 -2
  391. package/dist/__tests__/whiteboard-restore-state.test.d.ts.map +0 -1
  392. package/dist/__tests__/whiteboard-restore-state.test.js +0 -108
  393. package/dist/__tests__/whiteboard-restore-state.test.js.map +0 -1
  394. package/dist/lib/components/mention/mention-dropdown.component.d.ts +0 -53
  395. package/dist/lib/components/mention/mention-dropdown.component.d.ts.map +0 -1
  396. package/dist/lib/components/mention/mention-dropdown.component.js +0 -276
  397. package/dist/lib/components/mention/mention-dropdown.component.js.map +0 -1
  398. package/dist/lib/components/mention/mention-editor.component.d.ts +0 -256
  399. package/dist/lib/components/mention/mention-editor.component.d.ts.map +0 -1
  400. package/dist/lib/components/mention/mention-editor.component.js +0 -1233
  401. package/dist/lib/components/mention/mention-editor.component.js.map +0 -1
  402. package/dist/lib/components/message/message-input-box.component.d.ts +0 -137
  403. package/dist/lib/components/message/message-input-box.component.d.ts.map +0 -1
  404. package/dist/lib/components/message/message-input-box.component.js +0 -321
  405. package/dist/lib/components/message/message-input-box.component.js.map +0 -1
@@ -6,6 +6,7 @@ import { RealtimeSessionTimelineCardComponent } from '../realtime/realtime-sessi
6
6
  import { selectDistinctLatestArtifacts } from '../../utils/distinct-artifacts';
7
7
  import { BuildConversationTimeline } from '../../utils/realtime-session-timeline';
8
8
  import * as i0 from "@angular/core";
9
+ import * as i1 from "@memberjunction/ng-ui-components";
9
10
  const _c0 = ["messageContainer"];
10
11
  const _c1 = ["scrollContainer"];
11
12
  function MessageListComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
@@ -44,11 +45,7 @@ function MessageListComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
44
45
  i0.ɵɵclassProp("show", ctx_r1.showDateNav);
45
46
  } }
46
47
  function MessageListComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
47
- i0.ɵɵelementStart(0, "div", 4);
48
- i0.ɵɵelement(1, "i", 11);
49
- i0.ɵɵelementStart(2, "p");
50
- i0.ɵɵtext(3, "No messages yet. Start a conversation!");
51
- i0.ɵɵelementEnd()();
48
+ i0.ɵɵelement(0, "mj-empty-state", 4);
52
49
  } }
53
50
  /**
54
51
  * Container component for displaying a list of messages
@@ -550,22 +547,22 @@ export class MessageListComponent extends BaseAngularComponent {
550
547
  let _t;
551
548
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.messageContainerRef = _t.first);
552
549
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.scrollContainer = _t.first);
553
- } }, inputs: { messages: "messages", conversation: "conversation", currentUser: "currentUser", isProcessing: "isProcessing", artifactMap: "artifactMap", agentRunMap: "agentRunMap", ratingsMap: "ratingsMap", userAvatarMap: "userAvatarMap", attachmentsMap: "attachmentsMap", sessionMetaMap: "sessionMetaMap", messageRendererTemplate: "messageRendererTemplate", messageExtraTemplate: "messageExtraTemplate", messagesUpdate: "messagesUpdate" }, outputs: { editMessage: "editMessage", deleteMessage: "deleteMessage", retryMessage: "retryMessage", testFeedbackMessage: "testFeedbackMessage", artifactClicked: "artifactClicked", replyInThread: "replyInThread", viewThread: "viewThread", messageEdited: "messageEdited", openEntityRecord: "openEntityRecord", suggestedResponseSelected: "suggestedResponseSelected", attachmentClicked: "attachmentClicked", diagnosticRequested: "diagnosticRequested", messagePinToggled: "messagePinToggled", realtimeSessionOpenRequested: "realtimeSessionOpenRequested", beforeResponseFormSubmitted: "beforeResponseFormSubmitted", afterResponseFormSubmitted: "afterResponseFormSubmitted" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 6, vars: 2, consts: [["scrollContainer", ""], ["messageContainer", ""], [1, "message-list-container"], [1, "sticky-date-header"], [1, "empty-state"], [1, "sticky-date-wrapper"], [1, "sticky-date-button", 3, "click"], [1, "fas", "fa-chevron-down"], [1, "date-nav-dropdown"], [1, "date-nav-option", "jump-to"], [1, "date-nav-option", 3, "click"], [1, "fas", "fa-comments"]], template: function MessageListComponent_Template(rf, ctx) { if (rf & 1) {
550
+ } }, inputs: { messages: "messages", conversation: "conversation", currentUser: "currentUser", isProcessing: "isProcessing", artifactMap: "artifactMap", agentRunMap: "agentRunMap", ratingsMap: "ratingsMap", userAvatarMap: "userAvatarMap", attachmentsMap: "attachmentsMap", sessionMetaMap: "sessionMetaMap", messageRendererTemplate: "messageRendererTemplate", messageExtraTemplate: "messageExtraTemplate", messagesUpdate: "messagesUpdate" }, outputs: { editMessage: "editMessage", deleteMessage: "deleteMessage", retryMessage: "retryMessage", testFeedbackMessage: "testFeedbackMessage", artifactClicked: "artifactClicked", replyInThread: "replyInThread", viewThread: "viewThread", messageEdited: "messageEdited", openEntityRecord: "openEntityRecord", suggestedResponseSelected: "suggestedResponseSelected", attachmentClicked: "attachmentClicked", diagnosticRequested: "diagnosticRequested", messagePinToggled: "messagePinToggled", realtimeSessionOpenRequested: "realtimeSessionOpenRequested", beforeResponseFormSubmitted: "beforeResponseFormSubmitted", afterResponseFormSubmitted: "afterResponseFormSubmitted" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 6, vars: 2, consts: [["scrollContainer", ""], ["messageContainer", ""], [1, "message-list-container"], [1, "sticky-date-header"], ["Icon", "fa-solid fa-comments", "Title", "No messages yet. Start a conversation!", 1, "messages-empty-fill"], [1, "sticky-date-wrapper"], [1, "sticky-date-button", 3, "click"], [1, "fas", "fa-chevron-down"], [1, "date-nav-dropdown"], [1, "date-nav-option", "jump-to"], [1, "date-nav-option", 3, "click"]], template: function MessageListComponent_Template(rf, ctx) { if (rf & 1) {
554
551
  i0.ɵɵelementStart(0, "div", 2, 0);
555
552
  i0.ɵɵconditionalCreate(2, MessageListComponent_Conditional_2_Template, 17, 3, "div", 3);
556
553
  i0.ɵɵelementContainer(3, null, 1);
557
- i0.ɵɵconditionalCreate(5, MessageListComponent_Conditional_5_Template, 4, 0, "div", 4);
554
+ i0.ɵɵconditionalCreate(5, MessageListComponent_Conditional_5_Template, 1, 0, "mj-empty-state", 4);
558
555
  i0.ɵɵelementEnd();
559
556
  } if (rf & 2) {
560
557
  i0.ɵɵadvance(2);
561
558
  i0.ɵɵconditional(ctx.shouldShowDateFilter && ctx.messages.length > 0 ? 2 : -1);
562
559
  i0.ɵɵadvance(3);
563
560
  i0.ɵɵconditional(ctx.messages.length === 0 ? 5 : -1);
564
- } }, styles: [".message-list-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background-color: var(--mj-bg-surface-card);\n position: relative;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-muted);\n padding: 40px;\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 16px;\n margin: 0;\n}\n\n\n\n.sticky-date-header[_ngcontent-%COMP%] {\n position: sticky;\n top: 12px;\n z-index: 100;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n margin: 0;\n pointer-events: none;\n}\n\n.sticky-date-wrapper[_ngcontent-%COMP%] {\n pointer-events: auto;\n position: relative;\n}\n\n.sticky-date-button[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.sticky-date-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n box-shadow: var(--mj-shadow-md);\n}\n\n.sticky-date-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.date-nav-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 200px;\n display: none;\n z-index: 101;\n}\n\n.date-nav-dropdown.show[_ngcontent-%COMP%] {\n display: block;\n}\n\n.date-nav-option[_ngcontent-%COMP%] {\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.date-nav-option[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.date-nav-option.jump-to[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 12px;\n cursor: default;\n padding: 8px 16px 4px 16px;\n}\n\n.date-nav-option.jump-to[_ngcontent-%COMP%]:hover {\n background: none;\n}"] });
561
+ } }, dependencies: [i1.MJEmptyStateComponent], styles: [".message-list-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background-color: var(--mj-bg-surface-card);\n position: relative;\n}\n\n\n\n.messages-empty-fill[_ngcontent-%COMP%] {\n height: 100%;\n}\n\n\n\n.sticky-date-header[_ngcontent-%COMP%] {\n position: sticky;\n top: 12px;\n z-index: 100;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n margin: 0;\n pointer-events: none;\n}\n\n.sticky-date-wrapper[_ngcontent-%COMP%] {\n pointer-events: auto;\n position: relative;\n}\n\n.sticky-date-button[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.sticky-date-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n box-shadow: var(--mj-shadow-md);\n}\n\n.sticky-date-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.date-nav-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 200px;\n display: none;\n z-index: 101;\n}\n\n.date-nav-dropdown.show[_ngcontent-%COMP%] {\n display: block;\n}\n\n.date-nav-option[_ngcontent-%COMP%] {\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.date-nav-option[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.date-nav-option.jump-to[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 12px;\n cursor: default;\n padding: 8px 16px 4px 16px;\n}\n\n.date-nav-option.jump-to[_ngcontent-%COMP%]:hover {\n background: none;\n}"] });
565
562
  }
566
563
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageListComponent, [{
567
564
  type: Component,
568
- args: [{ standalone: false, selector: 'mj-conversation-message-list', template: "<div class=\"message-list-container\" #scrollContainer>\n <!-- Sticky Date Header (only show for long conversations spanning multiple days) -->\n @if (shouldShowDateFilter && messages.length > 0) {\n <div class=\"sticky-date-header\">\n <div class=\"sticky-date-wrapper\">\n <button class=\"sticky-date-button\" (click)=\"toggleDateNav()\">\n <span>{{ currentDateDisplay }}</span>\n <i class=\"fas fa-chevron-down\"></i>\n </button>\n <div class=\"date-nav-dropdown\" [class.show]=\"showDateNav\">\n <div class=\"date-nav-option jump-to\">Jump to...</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('today')\">Today</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('yesterday')\">Yesterday</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-week')\">Last week</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-month')\">Last month</div>\n </div>\n </div>\n </div>\n }\n\n <ng-container #messageContainer></ng-container>\n\n @if (messages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fas fa-comments\"></i>\n <p>No messages yet. Start a conversation!</p>\n </div>\n }\n</div>", styles: [".message-list-container {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background-color: var(--mj-bg-surface-card);\n position: relative;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-muted);\n padding: 40px;\n text-align: center;\n}\n\n.empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n}\n\n.empty-state p {\n font-size: 16px;\n margin: 0;\n}\n\n/* Sticky Date Header */\n.sticky-date-header {\n position: sticky;\n top: 12px;\n z-index: 100;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n margin: 0;\n pointer-events: none;\n}\n\n.sticky-date-wrapper {\n pointer-events: auto;\n position: relative;\n}\n\n.sticky-date-button {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.sticky-date-button:hover {\n background: var(--mj-bg-surface-sunken);\n box-shadow: var(--mj-shadow-md);\n}\n\n.sticky-date-button i {\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n/* Date Navigation Dropdown */\n.date-nav-dropdown {\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 200px;\n display: none;\n z-index: 101;\n}\n\n.date-nav-dropdown.show {\n display: block;\n}\n\n.date-nav-option {\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.date-nav-option:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.date-nav-option.jump-to {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 12px;\n cursor: default;\n padding: 8px 16px 4px 16px;\n}\n\n.date-nav-option.jump-to:hover {\n background: none;\n}\n"] }]
565
+ args: [{ standalone: false, selector: 'mj-conversation-message-list', template: "<div class=\"message-list-container\" #scrollContainer>\n <!-- Sticky Date Header (only show for long conversations spanning multiple days) -->\n @if (shouldShowDateFilter && messages.length > 0) {\n <div class=\"sticky-date-header\">\n <div class=\"sticky-date-wrapper\">\n <button class=\"sticky-date-button\" (click)=\"toggleDateNav()\">\n <span>{{ currentDateDisplay }}</span>\n <i class=\"fas fa-chevron-down\"></i>\n </button>\n <div class=\"date-nav-dropdown\" [class.show]=\"showDateNav\">\n <div class=\"date-nav-option jump-to\">Jump to...</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('today')\">Today</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('yesterday')\">Yesterday</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-week')\">Last week</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-month')\">Last month</div>\n </div>\n </div>\n </div>\n }\n\n <ng-container #messageContainer></ng-container>\n\n @if (messages.length === 0) {\n <mj-empty-state\n class=\"messages-empty-fill\"\n Icon=\"fa-solid fa-comments\"\n Title=\"No messages yet. Start a conversation!\" />\n }\n</div>", styles: [".message-list-container {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n background-color: var(--mj-bg-surface-card);\n position: relative;\n}\n\n/* Empty-state fills the message pane vertically */\n.messages-empty-fill {\n height: 100%;\n}\n\n/* Sticky Date Header */\n.sticky-date-header {\n position: sticky;\n top: 12px;\n z-index: 100;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 0;\n margin: 0;\n pointer-events: none;\n}\n\n.sticky-date-wrapper {\n pointer-events: auto;\n position: relative;\n}\n\n.sticky-date-button {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: var(--mj-shadow-sm);\n}\n\n.sticky-date-button:hover {\n background: var(--mj-bg-surface-sunken);\n box-shadow: var(--mj-shadow-md);\n}\n\n.sticky-date-button i {\n font-size: 10px;\n color: var(--mj-text-secondary);\n}\n\n/* Date Navigation Dropdown */\n.date-nav-dropdown {\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 8px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 200px;\n display: none;\n z-index: 101;\n}\n\n.date-nav-dropdown.show {\n display: block;\n}\n\n.date-nav-option {\n padding: 10px 16px;\n cursor: pointer;\n transition: background 0.2s;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.date-nav-option:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.date-nav-option.jump-to {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 12px;\n cursor: default;\n padding: 8px 16px 4px 16px;\n}\n\n.date-nav-option.jump-to:hover {\n background: none;\n}\n"] }]
569
566
  }], () => [{ type: i0.ChangeDetectorRef }], { messages: [{
570
567
  type: Input
571
568
  }], conversation: [{
@@ -1 +1 @@
1
- {"version":3,"file":"message-list.component.js","sourceRoot":"","sources":["../../../../src/lib/components/message/message-list.component.ts","../../../../src/lib/components/message/message-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ViewChild,\n ViewContainerRef,\n OnInit,\n OnDestroy,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n ElementRef,\n AfterViewInit,\n AfterViewChecked,\n ComponentRef,\n EmbeddedViewRef,\n TemplateRef\n} from '@angular/core';\nimport { MJConversationDetailEntity, MJConversationEntity, RatingJSON } from '@memberjunction/core-entities';\nimport { UserInfo, CompositeKey } from '@memberjunction/core';\nimport { NormalizeUUID } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MessageItemComponent, MessageAttachment } from './message-item.component';\nimport {\n BeforeResponseFormSubmittedEventArgs,\n AfterResponseFormSubmittedEventArgs,\n} from '../../events/chat-events';\nimport { RealtimeSessionTimelineCardComponent } from '../realtime/realtime-session-timeline-card.component';\nimport { LazyArtifactInfo } from '../../models/lazy-artifact-info';\nimport { selectDistinctLatestArtifacts } from '../../utils/distinct-artifacts';\nimport {\n BuildConversationTimeline,\n ConversationTimelineItem,\n RealtimeSessionTimelineGroup,\n RealtimeSessionTimelineMeta\n} from '../../utils/realtime-session-timeline';\nimport { MJAIAgentRunEntityExtended } from '@memberjunction/ai-core-plus';\n\n/** Context handed to the `messageRenderer` slot template per message. */\ninterface MessageRendererContext {\n $implicit: MJConversationDetailEntity;\n message: MJConversationDetailEntity;\n}\n\n/**\n * One per rendered message in the list. Three paths can produce an entry:\n * - `component` — the default `MessageItemComponent` (single message).\n * - `embedded` — an `EmbeddedViewRef` from the consumer's\n * `messageRenderer` slot template (full per-message\n * replacement, PR 2c slot system).\n * - `realtime-session` — a `RealtimeSessionTimelineCardComponent` collapsing\n * an entire past realtime session into one timeline\n * card (PR #2787 co-agent timeline). The grouping pass\n * (`BuildConversationTimeline`) emits these alongside\n * normal messages — see the timeline utility for the\n * rules.\n *\n * Discriminated by the `kind` tag for ergonomic narrowing.\n */\ntype RenderedMessageEntry =\n | { kind: 'component'; ref: ComponentRef<MessageItemComponent> }\n | { kind: 'embedded'; ref: EmbeddedViewRef<MessageRendererContext> }\n | { kind: 'realtime-session'; ref: ComponentRef<RealtimeSessionTimelineCardComponent> };\n\n/**\n * Container component for displaying a list of messages\n * Uses dynamic component creation (like skip-chat) to avoid Angular binding overhead\n * This dramatically improves performance when messages are added/removed\n */\n@Component({\n standalone: false,\n selector: 'mj-conversation-message-list',\n templateUrl: './message-list.component.html',\n styleUrls: ['./message-list.component.css']\n})\nexport class MessageListComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit, AfterViewChecked {\n @Input() public messages: MJConversationDetailEntity[] = [];\n @Input() public conversation!: MJConversationEntity | null;\n @Input() public currentUser!: UserInfo;\n @Input() public isProcessing: boolean = false;\n @Input() public artifactMap: Map<string, LazyArtifactInfo[]> = new Map();\n @Input() public agentRunMap: Map<string, MJAIAgentRunEntityExtended> = new Map();\n @Input() public ratingsMap: Map<string, RatingJSON[]> = new Map();\n @Input() public userAvatarMap: Map<string, {imageUrl: string | null; iconClass: string | null}> = new Map();\n @Input() public attachmentsMap: Map<string, MessageAttachment[]> = new Map();\n /**\n * Optional session-row enrichment for realtime SESSION BLOCKS, keyed by\n * `NormalizeUUID(sessionId)` (agent name / status / close reason). Details stamped\n * with an `AgentSessionID` collapse into one timeline card per session — see\n * `BuildConversationTimeline` — and this map dresses those cards up when present.\n */\n @Input() public sessionMetaMap: Map<string, RealtimeSessionTimelineMeta> = new Map();\n\n /**\n * Optional per-iteration custom message renderer. When set, the list renders each\n * message via this template (full replacement) instead of the default\n * `MessageItemComponent`. Forwarded by chat-area when a consumer projects\n * `mjChatSlot=\"messageRenderer\"`. The template receives the message as\n * `$implicit` and as a named `message` context binding.\n *\n * Consumers opting into a custom renderer take full responsibility for displaying\n * the message — edit/delete/retry affordances, artifacts, ratings, attachments,\n * etc. The minimal `MJChatMessageBubbleDefaultComponent` ships as a ready-to-use\n * bubble renderer.\n */\n @Input() public messageRendererTemplate: TemplateRef<unknown> | null = null;\n\n /**\n * Optional per-message additive decoration template, projected INSIDE the default\n * `MessageItemComponent` (after the message text). Forwarded by chat-area when a\n * consumer projects `mjChatSlot=\"messageExtra\"`. Ignored when\n * `messageRendererTemplate` is set (custom renderers own all per-message content).\n */\n @Input() public messageExtraTemplate: TemplateRef<unknown> | null = null;\n\n @Output() public editMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public deleteMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public retryMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public testFeedbackMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public artifactClicked = new EventEmitter<{artifactId: string; versionId?: string}>();\n @Output() public replyInThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public viewThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public messageEdited = new EventEmitter<MJConversationDetailEntity>();\n @Output() public openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n @Output() public suggestedResponseSelected = new EventEmitter<{text: string; customInput?: string}>();\n @Output() public attachmentClicked = new EventEmitter<MessageAttachment>();\n @Output() public diagnosticRequested = new EventEmitter<string>(); // emits messageId\n @Output() public messagePinToggled = new EventEmitter<MJConversationDetailEntity>();\n /** Emitted with the `MJ: AI Agent Sessions.ID` when a realtime session block's Open affordance is clicked. */\n @Output() public realtimeSessionOpenRequested = new EventEmitter<string>();\n\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public beforeResponseFormSubmitted = new EventEmitter<BeforeResponseFormSubmittedEventArgs>();\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public afterResponseFormSubmitted = new EventEmitter<AfterResponseFormSubmittedEventArgs>();\n\n @ViewChild('messageContainer', { read: ViewContainerRef }) messageContainerRef!: ViewContainerRef;\n @ViewChild('scrollContainer') scrollContainer!: ElementRef;\n\n /**\n * Per-message rendered entries — see `RenderedMessageEntry` for the 3-way\n * union (default MessageItemComponent / consumer messageRenderer slot\n * embedded view / collapsed realtime session timeline card).\n */\n private _renderedMessages = new Map<string, RenderedMessageEntry>();\n private _shouldScrollToBottom = false;\n private _previousMessageCount = 0; // Track previous count to detect new messages\n\n public currentDateDisplay: string = 'Today';\n public showDateNav: boolean = false;\n public shouldShowDateFilter: boolean = false;\n\n constructor(private cdRef: ChangeDetectorRef) {\n super();\n }\n\n public toggleDateNav(): void {\n this.showDateNav = !this.showDateNav;\n }\n\n public jumpToDate(period: string): void {\n // TODO: Implement date jumping logic\n console.log('Jump to date:', period);\n this.showDateNav = false;\n\n // Update display based on period\n switch(period) {\n case 'today':\n this.currentDateDisplay = 'Today';\n break;\n case 'yesterday':\n this.currentDateDisplay = 'Yesterday';\n break;\n case 'last-week':\n this.currentDateDisplay = 'Last week';\n break;\n case 'last-month':\n this.currentDateDisplay = 'Last month';\n break;\n }\n }\n\n // Track whether initial render has happened\n private _initialRenderComplete = false;\n\n ngOnInit() {\n // Initial render will happen in ngAfterViewInit when ViewContainerRef is available\n }\n\n ngAfterViewInit() {\n // ViewContainerRef is now available - perform initial render if we have messages\n if (this.messages && this.messages.length > 0 && this.messageContainerRef && !this._initialRenderComplete) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // React to messages array changes\n // Note: On initial load, messageContainerRef may not be available yet (ngOnChanges runs before ngAfterViewInit)\n // In that case, ngAfterViewInit will handle the initial render\n if (changes['messages'] && this.messages && this.messageContainerRef) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n\n // Watch for artifactMap changes to handle newly created artifacts\n // While artifacts are pre-loaded during initial peripheral data load,\n // new artifacts can be created mid-conversation (e.g., by agent runs)\n // This ensures artifact cards appear in messages immediately without requiring a refresh\n if (changes['artifactMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for attachmentsMap changes to handle newly created attachments\n // This ensures media attachments (e.g., images generated by agents) appear\n // immediately without requiring a page refresh\n if (changes['attachmentsMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for session-meta changes so realtime session blocks pick up their\n // agent name / status chip once the (async, batched) session lookup lands\n if (changes['sessionMetaMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n }\n\n ngAfterViewChecked() {\n if (this._shouldScrollToBottom) {\n this.scrollToBottom();\n this._shouldScrollToBottom = false;\n }\n }\n\n ngOnDestroy() {\n // Clean up all dynamically created components AND embedded views (both have destroy()).\n this._renderedMessages.forEach((entry) => {\n if (entry) {\n entry.ref.destroy();\n }\n });\n this._renderedMessages.clear();\n\n if (this.messageContainerRef) {\n this.messageContainerRef.clear();\n }\n }\n\n /**\n * Called when messages array changes\n * Efficiently updates the DOM without re-rendering everything\n */\n @Input()\n set messagesUpdate(messages: MJConversationDetailEntity[]) {\n if (messages && this.messageContainerRef) {\n this.updateMessages(messages);\n }\n }\n\n /**\n * Updates the message list using dynamic component creation\n * Only adds/removes changed messages for optimal performance\n *\n * REALTIME SESSIONS: details stamped with an `AgentSessionID` (turns persisted during\n * a live realtime session) do NOT render as normal chat bubbles. The timeline pass\n * (`BuildConversationTimeline`) collapses each session's stamped rows into ONE session\n * block, rendered as a `RealtimeSessionTimelineCardComponent` at the session's\n * chronological position. Everything else renders exactly as before.\n */\n private updateMessages(messages: MJConversationDetailEntity[]): void {\n // Temporarily detach change detection for performance\n this.cdRef.detach();\n\n try {\n // Build the timeline first — collapses contiguous realtime-session rows\n // into ONE session block per session, leaving normal messages in place.\n // See `BuildConversationTimeline` in `utils/realtime-session-timeline`.\n const timeline = BuildConversationTimeline(messages);\n\n // Remove rendered items (messages AND session blocks) that no longer exist\n const currentKeys = new Set(timeline.map(item => this.getTimelineKey(item)));\n this._renderedMessages.forEach((entry, key) => {\n if (!currentKeys.has(key)) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n });\n\n // Add or update timeline items in chronological order. `renderMessageItem`\n // internally branches on the slot template (messageRenderer) vs the\n // default MessageItemComponent; `renderSessionBlock` always creates a\n // RealtimeSessionTimelineCardComponent.\n const lastMessageKey = this.findLastMessageKey(timeline);\n for (const item of timeline) {\n if (item.Kind === 'session') {\n this.renderSessionBlock(item.Group);\n } else {\n this.renderMessageItem(item.Detail, messages, this.getMessageKey(item.Detail) === lastMessageKey);\n }\n }\n\n // Only scroll to bottom if new messages were added (not just updates)\n // This prevents scrolling when the message list is merely refreshed (e.g., during agent run timer)\n const previousCount = this._previousMessageCount;\n this._previousMessageCount = messages.length;\n\n if (messages.length > previousCount) {\n this._shouldScrollToBottom = true;\n }\n } finally {\n // Re-attach change detection\n this.cdRef.reattach();\n this.cdRef.detectChanges();\n }\n }\n\n /** Stable render key for a timeline item — message ID, or a prefixed session key for session blocks. */\n private getTimelineKey(item: ConversationTimelineItem<MJConversationDetailEntity>): string {\n return item.Kind === 'session' ? this.getSessionKey(item.Group.SessionID) : this.getMessageKey(item.Detail);\n }\n\n /** Render key for a session block (case-insensitive on the session id; prefixed so it can't collide with message IDs). */\n private getSessionKey(sessionId: string): string {\n return `session:${NormalizeUUID(sessionId)}`;\n }\n\n /** The render key of the LAST normal message item in the timeline (drives `isLastMessage`), or null when none. */\n private findLastMessageKey(timeline: ConversationTimelineItem<MJConversationDetailEntity>[]): string | null {\n for (let i = timeline.length - 1; i >= 0; i--) {\n const item = timeline[i];\n if (item.Kind === 'message') {\n return this.getMessageKey(item.Detail);\n }\n }\n return null;\n }\n\n /**\n * Creates or updates the ONE timeline card a realtime session collapses to.\n * Click/Open on the card bubbles up via {@link realtimeSessionOpenRequested} so the\n * chat area can host the SESSION REVIEW overlay for it.\n */\n private renderSessionBlock(group: RealtimeSessionTimelineGroup): void {\n const key = this.getSessionKey(group.SessionID);\n const meta = this.sessionMetaMap.get(NormalizeUUID(group.SessionID)) ?? null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'realtime-session') {\n // Update existing card in place.\n const instance = existing.ref.instance;\n instance.Group = group;\n instance.Meta = meta;\n existing.ref.changeDetectorRef.markForCheck();\n return;\n }\n\n // Different kind at this key (e.g. mode changed) — drop the old entry, fall through to create.\n if (existing) {\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n const componentRef = this.messageContainerRef.createComponent(RealtimeSessionTimelineCardComponent);\n componentRef.instance.Group = group;\n componentRef.instance.Meta = meta;\n componentRef.instance.UserName = this.currentUser?.Name || 'You';\n componentRef.instance.OpenRequested.subscribe((sessionId: string) => this.realtimeSessionOpenRequested.emit(sessionId));\n this._renderedMessages.set(key, { kind: 'realtime-session', ref: componentRef });\n }\n\n /**\n * Creates or updates one normal chat message item. Routes to the\n * consumer-projected `messageRenderer` slot template (EmbeddedViewRef path)\n * when present, otherwise falls back to the default `MessageItemComponent`\n * dynamic-component path. Both paths flow through the shared\n * `createRenderedEntry` / `updateMessageItemInstance` helpers.\n */\n private renderMessageItem(message: MJConversationDetailEntity, messages: MJConversationDetailEntity[], isLastMessage: boolean): void {\n const key = this.getMessageKey(message);\n // `index` is only used for the `isLastMessage` heuristic inside\n // updateMessageItemInstance — synthesize a value that produces the right\n // boolean (last index when `isLastMessage` is true, else 0 — any non-last\n // index works since it just affects that one comparison).\n const index = isLastMessage ? messages.length - 1 : 0;\n const useCustomRenderer = this.messageRendererTemplate !== null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'embedded' && useCustomRenderer) {\n // Update existing embedded view from messageRenderer slot\n existing.ref.context.$implicit = message;\n existing.ref.context.message = message;\n existing.ref.markForCheck();\n return;\n }\n if (existing && existing.kind === 'component' && !useCustomRenderer) {\n // Update existing MessageItemComponent in place\n this.updateMessageItemInstance(existing.ref, message, messages, index);\n return;\n }\n if (existing) {\n // Rendering kind changed (e.g. component↔embedded, or a session block was\n // overwritten with a message). Destroy + recreate.\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n this.createRenderedEntry(message, messages, index, key, useCustomRenderer);\n }\n\n /**\n * Updates an existing `MessageItemComponent` in place — used on the default\n * (non-custom-renderer) path when a message's status / artifacts / agent-run /\n * etc. changes mid-stream.\n */\n private updateMessageItemInstance(\n ref: ComponentRef<MessageItemComponent>,\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number\n ): void {\n const instance = ref.instance;\n const previousMessage = instance.message;\n\n instance.message = message;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.messageExtraTemplate;\n\n this.applyArtifactsToInstance(instance, message.ID, ref.changeDetectorRef);\n\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n instance.ratings = this.ratingsMap.get(message.ID);\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n // Status change requires explicit markForCheck on the OnPush dynamic child.\n if (previousMessage && previousMessage.Status !== message.Status) {\n ref.changeDetectorRef.markForCheck();\n }\n }\n\n /**\n * Creates a new rendered entry — either a `MessageItemComponent` (default path)\n * or an `EmbeddedViewRef` from the consumer's `messageRenderer` slot template.\n * Stores the entry in `_renderedMessages` and stamps a back-reference on the\n * message entity.\n */\n private createRenderedEntry(\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number,\n key: string,\n useCustomRenderer: boolean\n ): void {\n if (useCustomRenderer && this.messageRendererTemplate) {\n // The slot directive carries TemplateRef<unknown>; assert the contract here\n // (consumers' `let-message` bindings consume the message context shape below).\n const template = this.messageRendererTemplate as TemplateRef<MessageRendererContext>;\n const viewRef = this.messageContainerRef.createEmbeddedView<MessageRendererContext>(\n template,\n { $implicit: message, message }\n );\n this._renderedMessages.set(key, { kind: 'embedded', ref: viewRef });\n // Stamp back-ref for parity with the component path.\n (message as unknown as { _viewRef?: EmbeddedViewRef<MessageRendererContext> })._viewRef = viewRef;\n return;\n }\n\n const componentRef = this.messageContainerRef.createComponent(MessageItemComponent);\n const instance = componentRef.instance;\n\n instance.message = message;\n instance.conversation = this.conversation;\n instance.currentUser = this.currentUser;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.messageExtraTemplate;\n\n this.applyArtifactsToInstance(instance, message.ID, componentRef.changeDetectorRef);\n\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n instance.ratings = this.ratingsMap.get(message.ID);\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n instance.editClicked.subscribe((msg: MJConversationDetailEntity) => this.editMessage.emit(msg));\n instance.deleteClicked.subscribe((msg: MJConversationDetailEntity) => this.deleteMessage.emit(msg));\n instance.retryClicked.subscribe((msg: MJConversationDetailEntity) => this.retryMessage.emit(msg));\n instance.testFeedbackClicked.subscribe((msg: MJConversationDetailEntity) => this.testFeedbackMessage.emit(msg));\n instance.artifactClicked.subscribe((data: {artifactId: string; versionId?: string}) => this.artifactClicked.emit(data));\n instance.messageEdited.subscribe((msg: MJConversationDetailEntity) => this.messageEdited.emit(msg));\n instance.openEntityRecord.subscribe((data: {entityName: string; compositeKey: CompositeKey}) => this.openEntityRecord.emit(data));\n instance.suggestedResponseSelected.subscribe((data: {text: string; customInput?: string}) => this.suggestedResponseSelected.emit(data));\n instance.attachmentClicked.subscribe((attachment: MessageAttachment) => this.attachmentClicked.emit(attachment));\n instance.diagnosticRequested.subscribe((messageId: string) => this.diagnosticRequested.emit(messageId));\n instance.messagePinToggled.subscribe((msg: MJConversationDetailEntity) => this.messagePinToggled.emit(msg));\n instance.beforeResponseFormSubmitted.subscribe((e: BeforeResponseFormSubmittedEventArgs) => this.beforeResponseFormSubmitted.emit(e));\n instance.afterResponseFormSubmitted.subscribe((e: AfterResponseFormSubmittedEventArgs) => this.afterResponseFormSubmitted.emit(e));\n\n if (instance.artifactActionPerformed) {\n instance.artifactActionPerformed.subscribe((data: {action: string; artifactId: string}) => {\n // Parent can handle artifact actions (save, fork, history, share)\n console.log('Artifact action:', data);\n });\n }\n\n this._renderedMessages.set(key, { kind: 'component', ref: componentRef });\n // Preserve the existing back-ref pattern from the skip-chat performance design.\n (message as unknown as { _componentRef?: ComponentRef<MessageItemComponent> })._componentRef = componentRef;\n }\n\n /**\n * Resolves the DISTINCT artifacts for a message (one entry per artifactId at its\n * latest version), lazy-loads them all, and applies them to the rendered\n * message-item. Loads in the background so the UI never blocks.\n *\n * WHY WE SURFACE THEM ALL (design rationale — see PR discussion w/ Pranav & Ethan):\n * A single message can legitimately carry more than one DISTINCT artifact — e.g. a\n * research report PLUS a *standalone* generated infographic. This is deliberately\n * NOT in conflict with the server-side consolidation in AgentRunner\n * (Pranav, 5664b86: \"keep the report's embedded image in the report, not as a\n * duplicate artifact\"): that logic only suppresses media that is *embedded inline*\n * (base64) in another artifact's payload — a true duplicate. Genuinely standalone\n * sibling artifacts (the report uses SVG charts; the infographic is a separate JPEG)\n * are correctly kept as separate artifacts, and the UI must show every one of them.\n *\n * The earlier `artifactList[length - 1]` (\"show only the most recent\") approach\n * (EL-BC, 95492622) assumed consolidation always left exactly one artifact per\n * message; when it legitimately leaves two, that silently hid the report behind the\n * image. Grouping by artifactId (latest version each) shows all distinct artifacts\n * while still collapsing multiple *versions* of the same artifact to one card.\n */\n private applyArtifactsToInstance(\n instance: MessageItemComponent,\n messageId: string,\n childCdRef: ChangeDetectorRef\n ): void {\n const infos = this.resolveDistinctArtifacts(messageId);\n if (infos.length === 0) {\n instance.artifacts = [];\n instance.artifact = undefined;\n instance.artifactVersion = undefined;\n return;\n }\n\n Promise.all(\n infos.map(info =>\n Promise.all([info.getArtifact(), info.getVersion()]).then(([artifact, version]) => ({ artifact, version }))\n )\n )\n .then(refs => {\n instance.artifacts = refs;\n // Keep the legacy single inputs pointed at the first entry for back-compat.\n instance.artifact = refs[0]?.artifact;\n instance.artifactVersion = refs[0]?.version;\n // zone.js 0.15: parent detectChanges doesn't propagate to dynamically created children\n childCdRef.detectChanges();\n this.cdRef.detectChanges();\n })\n .catch(err => {\n console.error('Failed to lazy-load artifacts:', err);\n });\n }\n\n /**\n * Groups a message's artifact list by artifactId, keeping the highest version of\n * each. Multiple versions of the SAME artifact collapse to one card (latest wins),\n * while genuinely distinct artifacts are all retained.\n */\n private resolveDistinctArtifacts(messageId: string): LazyArtifactInfo[] {\n const list = this.artifactMap.get(messageId);\n if (!list || list.length === 0) {\n return [];\n }\n return selectDistinctLatestArtifacts(list);\n }\n\n /**\n * Generates a unique key for a message\n * Uses ID if available, otherwise uses a temporary key\n */\n private getMessageKey(message: MJConversationDetailEntity): string {\n return message.ID && message.ID.length > 0\n ? message.ID\n : `temp_${message.__mj_CreatedAt?.getTime() || Date.now()}`;\n }\n\n /**\n * Determines whether to show the date filter dropdown\n * Only show if conversation is long and spans multiple days\n */\n private updateDateFilterVisibility(): void {\n if (!this.messages || this.messages.length < 20) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n // Check if messages span more than 2 days\n const dates = this.messages\n .map(m => m.__mj_CreatedAt)\n .filter(d => d != null)\n .map(d => new Date(d!).setHours(0, 0, 0, 0));\n\n if (dates.length === 0) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n const uniqueDates = new Set(dates);\n const daySpan = uniqueDates.size;\n\n // Show filter if conversation has 20+ messages and spans 3+ days\n this.shouldShowDateFilter = daySpan >= 3;\n }\n\n /**\n * Scrolls the message list to the bottom\n */\n private scrollToBottom(): void {\n if (this.scrollContainer && this.scrollContainer.nativeElement) {\n Promise.resolve().then(() => {\n const element = this.scrollContainer.nativeElement;\n element.scrollTop = element.scrollHeight;\n });\n }\n }\n\n /**\n * Removes a message from the rendered list\n * Called externally when a message is deleted\n */\n public removeMessage(message: MJConversationDetailEntity): void {\n const key = this.getMessageKey(message);\n const entry = this._renderedMessages.get(key);\n if (entry) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n }\n}","<div class=\"message-list-container\" #scrollContainer>\n <!-- Sticky Date Header (only show for long conversations spanning multiple days) -->\n @if (shouldShowDateFilter && messages.length > 0) {\n <div class=\"sticky-date-header\">\n <div class=\"sticky-date-wrapper\">\n <button class=\"sticky-date-button\" (click)=\"toggleDateNav()\">\n <span>{{ currentDateDisplay }}</span>\n <i class=\"fas fa-chevron-down\"></i>\n </button>\n <div class=\"date-nav-dropdown\" [class.show]=\"showDateNav\">\n <div class=\"date-nav-option jump-to\">Jump to...</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('today')\">Today</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('yesterday')\">Yesterday</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-week')\">Last week</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-month')\">Last month</div>\n </div>\n </div>\n </div>\n }\n\n <ng-container #messageContainer></ng-container>\n\n @if (messages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fas fa-comments\"></i>\n <p>No messages yet. Start a conversation!</p>\n </div>\n }\n</div>"]}
1
+ {"version":3,"file":"message-list.component.js","sourceRoot":"","sources":["../../../../src/lib/components/message/message-list.component.ts","../../../../src/lib/components/message/message-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ViewChild,\n ViewContainerRef,\n OnInit,\n OnDestroy,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n ElementRef,\n AfterViewInit,\n AfterViewChecked,\n ComponentRef,\n EmbeddedViewRef,\n TemplateRef\n} from '@angular/core';\nimport { MJConversationDetailEntity, MJConversationEntity, RatingJSON } from '@memberjunction/core-entities';\nimport { UserInfo, CompositeKey } from '@memberjunction/core';\nimport { NormalizeUUID } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MessageItemComponent, MessageAttachment } from './message-item.component';\nimport {\n BeforeResponseFormSubmittedEventArgs,\n AfterResponseFormSubmittedEventArgs,\n} from '../../events/chat-events';\nimport { RealtimeSessionTimelineCardComponent } from '../realtime/realtime-session-timeline-card.component';\nimport { LazyArtifactInfo } from '../../models/lazy-artifact-info';\nimport { selectDistinctLatestArtifacts } from '../../utils/distinct-artifacts';\nimport {\n BuildConversationTimeline,\n ConversationTimelineItem,\n RealtimeSessionTimelineGroup,\n RealtimeSessionTimelineMeta\n} from '../../utils/realtime-session-timeline';\nimport { MJAIAgentRunEntityExtended } from '@memberjunction/ai-core-plus';\n\n/** Context handed to the `messageRenderer` slot template per message. */\ninterface MessageRendererContext {\n $implicit: MJConversationDetailEntity;\n message: MJConversationDetailEntity;\n}\n\n/**\n * One per rendered message in the list. Three paths can produce an entry:\n * - `component` — the default `MessageItemComponent` (single message).\n * - `embedded` — an `EmbeddedViewRef` from the consumer's\n * `messageRenderer` slot template (full per-message\n * replacement, PR 2c slot system).\n * - `realtime-session` — a `RealtimeSessionTimelineCardComponent` collapsing\n * an entire past realtime session into one timeline\n * card (PR #2787 co-agent timeline). The grouping pass\n * (`BuildConversationTimeline`) emits these alongside\n * normal messages — see the timeline utility for the\n * rules.\n *\n * Discriminated by the `kind` tag for ergonomic narrowing.\n */\ntype RenderedMessageEntry =\n | { kind: 'component'; ref: ComponentRef<MessageItemComponent> }\n | { kind: 'embedded'; ref: EmbeddedViewRef<MessageRendererContext> }\n | { kind: 'realtime-session'; ref: ComponentRef<RealtimeSessionTimelineCardComponent> };\n\n/**\n * Container component for displaying a list of messages\n * Uses dynamic component creation (like skip-chat) to avoid Angular binding overhead\n * This dramatically improves performance when messages are added/removed\n */\n@Component({\n standalone: false,\n selector: 'mj-conversation-message-list',\n templateUrl: './message-list.component.html',\n styleUrls: ['./message-list.component.css']\n})\nexport class MessageListComponent extends BaseAngularComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit, AfterViewChecked {\n @Input() public messages: MJConversationDetailEntity[] = [];\n @Input() public conversation!: MJConversationEntity | null;\n @Input() public currentUser!: UserInfo;\n @Input() public isProcessing: boolean = false;\n @Input() public artifactMap: Map<string, LazyArtifactInfo[]> = new Map();\n @Input() public agentRunMap: Map<string, MJAIAgentRunEntityExtended> = new Map();\n @Input() public ratingsMap: Map<string, RatingJSON[]> = new Map();\n @Input() public userAvatarMap: Map<string, {imageUrl: string | null; iconClass: string | null}> = new Map();\n @Input() public attachmentsMap: Map<string, MessageAttachment[]> = new Map();\n /**\n * Optional session-row enrichment for realtime SESSION BLOCKS, keyed by\n * `NormalizeUUID(sessionId)` (agent name / status / close reason). Details stamped\n * with an `AgentSessionID` collapse into one timeline card per session — see\n * `BuildConversationTimeline` — and this map dresses those cards up when present.\n */\n @Input() public sessionMetaMap: Map<string, RealtimeSessionTimelineMeta> = new Map();\n\n /**\n * Optional per-iteration custom message renderer. When set, the list renders each\n * message via this template (full replacement) instead of the default\n * `MessageItemComponent`. Forwarded by chat-area when a consumer projects\n * `mjChatSlot=\"messageRenderer\"`. The template receives the message as\n * `$implicit` and as a named `message` context binding.\n *\n * Consumers opting into a custom renderer take full responsibility for displaying\n * the message — edit/delete/retry affordances, artifacts, ratings, attachments,\n * etc. The minimal `MJChatMessageBubbleDefaultComponent` ships as a ready-to-use\n * bubble renderer.\n */\n @Input() public messageRendererTemplate: TemplateRef<unknown> | null = null;\n\n /**\n * Optional per-message additive decoration template, projected INSIDE the default\n * `MessageItemComponent` (after the message text). Forwarded by chat-area when a\n * consumer projects `mjChatSlot=\"messageExtra\"`. Ignored when\n * `messageRendererTemplate` is set (custom renderers own all per-message content).\n */\n @Input() public messageExtraTemplate: TemplateRef<unknown> | null = null;\n\n @Output() public editMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public deleteMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public retryMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public testFeedbackMessage = new EventEmitter<MJConversationDetailEntity>();\n @Output() public artifactClicked = new EventEmitter<{artifactId: string; versionId?: string}>();\n @Output() public replyInThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public viewThread = new EventEmitter<MJConversationDetailEntity>();\n @Output() public messageEdited = new EventEmitter<MJConversationDetailEntity>();\n @Output() public openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n @Output() public suggestedResponseSelected = new EventEmitter<{text: string; customInput?: string}>();\n @Output() public attachmentClicked = new EventEmitter<MessageAttachment>();\n @Output() public diagnosticRequested = new EventEmitter<string>(); // emits messageId\n @Output() public messagePinToggled = new EventEmitter<MJConversationDetailEntity>();\n /** Emitted with the `MJ: AI Agent Sessions.ID` when a realtime session block's Open affordance is clicked. */\n @Output() public realtimeSessionOpenRequested = new EventEmitter<string>();\n\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public beforeResponseFormSubmitted = new EventEmitter<BeforeResponseFormSubmittedEventArgs>();\n /** Forwarded from MessageItemComponent — see its docs. */\n @Output() public afterResponseFormSubmitted = new EventEmitter<AfterResponseFormSubmittedEventArgs>();\n\n @ViewChild('messageContainer', { read: ViewContainerRef }) messageContainerRef!: ViewContainerRef;\n @ViewChild('scrollContainer') scrollContainer!: ElementRef;\n\n /**\n * Per-message rendered entries — see `RenderedMessageEntry` for the 3-way\n * union (default MessageItemComponent / consumer messageRenderer slot\n * embedded view / collapsed realtime session timeline card).\n */\n private _renderedMessages = new Map<string, RenderedMessageEntry>();\n private _shouldScrollToBottom = false;\n private _previousMessageCount = 0; // Track previous count to detect new messages\n\n public currentDateDisplay: string = 'Today';\n public showDateNav: boolean = false;\n public shouldShowDateFilter: boolean = false;\n\n constructor(private cdRef: ChangeDetectorRef) {\n super();\n }\n\n public toggleDateNav(): void {\n this.showDateNav = !this.showDateNav;\n }\n\n public jumpToDate(period: string): void {\n // TODO: Implement date jumping logic\n console.log('Jump to date:', period);\n this.showDateNav = false;\n\n // Update display based on period\n switch(period) {\n case 'today':\n this.currentDateDisplay = 'Today';\n break;\n case 'yesterday':\n this.currentDateDisplay = 'Yesterday';\n break;\n case 'last-week':\n this.currentDateDisplay = 'Last week';\n break;\n case 'last-month':\n this.currentDateDisplay = 'Last month';\n break;\n }\n }\n\n // Track whether initial render has happened\n private _initialRenderComplete = false;\n\n ngOnInit() {\n // Initial render will happen in ngAfterViewInit when ViewContainerRef is available\n }\n\n ngAfterViewInit() {\n // ViewContainerRef is now available - perform initial render if we have messages\n if (this.messages && this.messages.length > 0 && this.messageContainerRef && !this._initialRenderComplete) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // React to messages array changes\n // Note: On initial load, messageContainerRef may not be available yet (ngOnChanges runs before ngAfterViewInit)\n // In that case, ngAfterViewInit will handle the initial render\n if (changes['messages'] && this.messages && this.messageContainerRef) {\n this._initialRenderComplete = true;\n this.updateMessages(this.messages);\n this.updateDateFilterVisibility();\n }\n\n // Watch for artifactMap changes to handle newly created artifacts\n // While artifacts are pre-loaded during initial peripheral data load,\n // new artifacts can be created mid-conversation (e.g., by agent runs)\n // This ensures artifact cards appear in messages immediately without requiring a refresh\n if (changes['artifactMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for attachmentsMap changes to handle newly created attachments\n // This ensures media attachments (e.g., images generated by agents) appear\n // immediately without requiring a page refresh\n if (changes['attachmentsMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n\n // Watch for session-meta changes so realtime session blocks pick up their\n // agent name / status chip once the (async, batched) session lookup lands\n if (changes['sessionMetaMap'] && this.messages && this.messageContainerRef) {\n this.updateMessages(this.messages);\n }\n }\n\n ngAfterViewChecked() {\n if (this._shouldScrollToBottom) {\n this.scrollToBottom();\n this._shouldScrollToBottom = false;\n }\n }\n\n ngOnDestroy() {\n // Clean up all dynamically created components AND embedded views (both have destroy()).\n this._renderedMessages.forEach((entry) => {\n if (entry) {\n entry.ref.destroy();\n }\n });\n this._renderedMessages.clear();\n\n if (this.messageContainerRef) {\n this.messageContainerRef.clear();\n }\n }\n\n /**\n * Called when messages array changes\n * Efficiently updates the DOM without re-rendering everything\n */\n @Input()\n set messagesUpdate(messages: MJConversationDetailEntity[]) {\n if (messages && this.messageContainerRef) {\n this.updateMessages(messages);\n }\n }\n\n /**\n * Updates the message list using dynamic component creation\n * Only adds/removes changed messages for optimal performance\n *\n * REALTIME SESSIONS: details stamped with an `AgentSessionID` (turns persisted during\n * a live realtime session) do NOT render as normal chat bubbles. The timeline pass\n * (`BuildConversationTimeline`) collapses each session's stamped rows into ONE session\n * block, rendered as a `RealtimeSessionTimelineCardComponent` at the session's\n * chronological position. Everything else renders exactly as before.\n */\n private updateMessages(messages: MJConversationDetailEntity[]): void {\n // Temporarily detach change detection for performance\n this.cdRef.detach();\n\n try {\n // Build the timeline first — collapses contiguous realtime-session rows\n // into ONE session block per session, leaving normal messages in place.\n // See `BuildConversationTimeline` in `utils/realtime-session-timeline`.\n const timeline = BuildConversationTimeline(messages);\n\n // Remove rendered items (messages AND session blocks) that no longer exist\n const currentKeys = new Set(timeline.map(item => this.getTimelineKey(item)));\n this._renderedMessages.forEach((entry, key) => {\n if (!currentKeys.has(key)) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n });\n\n // Add or update timeline items in chronological order. `renderMessageItem`\n // internally branches on the slot template (messageRenderer) vs the\n // default MessageItemComponent; `renderSessionBlock` always creates a\n // RealtimeSessionTimelineCardComponent.\n const lastMessageKey = this.findLastMessageKey(timeline);\n for (const item of timeline) {\n if (item.Kind === 'session') {\n this.renderSessionBlock(item.Group);\n } else {\n this.renderMessageItem(item.Detail, messages, this.getMessageKey(item.Detail) === lastMessageKey);\n }\n }\n\n // Only scroll to bottom if new messages were added (not just updates)\n // This prevents scrolling when the message list is merely refreshed (e.g., during agent run timer)\n const previousCount = this._previousMessageCount;\n this._previousMessageCount = messages.length;\n\n if (messages.length > previousCount) {\n this._shouldScrollToBottom = true;\n }\n } finally {\n // Re-attach change detection\n this.cdRef.reattach();\n this.cdRef.detectChanges();\n }\n }\n\n /** Stable render key for a timeline item — message ID, or a prefixed session key for session blocks. */\n private getTimelineKey(item: ConversationTimelineItem<MJConversationDetailEntity>): string {\n return item.Kind === 'session' ? this.getSessionKey(item.Group.SessionID) : this.getMessageKey(item.Detail);\n }\n\n /** Render key for a session block (case-insensitive on the session id; prefixed so it can't collide with message IDs). */\n private getSessionKey(sessionId: string): string {\n return `session:${NormalizeUUID(sessionId)}`;\n }\n\n /** The render key of the LAST normal message item in the timeline (drives `isLastMessage`), or null when none. */\n private findLastMessageKey(timeline: ConversationTimelineItem<MJConversationDetailEntity>[]): string | null {\n for (let i = timeline.length - 1; i >= 0; i--) {\n const item = timeline[i];\n if (item.Kind === 'message') {\n return this.getMessageKey(item.Detail);\n }\n }\n return null;\n }\n\n /**\n * Creates or updates the ONE timeline card a realtime session collapses to.\n * Click/Open on the card bubbles up via {@link realtimeSessionOpenRequested} so the\n * chat area can host the SESSION REVIEW overlay for it.\n */\n private renderSessionBlock(group: RealtimeSessionTimelineGroup): void {\n const key = this.getSessionKey(group.SessionID);\n const meta = this.sessionMetaMap.get(NormalizeUUID(group.SessionID)) ?? null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'realtime-session') {\n // Update existing card in place.\n const instance = existing.ref.instance;\n instance.Group = group;\n instance.Meta = meta;\n existing.ref.changeDetectorRef.markForCheck();\n return;\n }\n\n // Different kind at this key (e.g. mode changed) — drop the old entry, fall through to create.\n if (existing) {\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n const componentRef = this.messageContainerRef.createComponent(RealtimeSessionTimelineCardComponent);\n componentRef.instance.Group = group;\n componentRef.instance.Meta = meta;\n componentRef.instance.UserName = this.currentUser?.Name || 'You';\n componentRef.instance.OpenRequested.subscribe((sessionId: string) => this.realtimeSessionOpenRequested.emit(sessionId));\n this._renderedMessages.set(key, { kind: 'realtime-session', ref: componentRef });\n }\n\n /**\n * Creates or updates one normal chat message item. Routes to the\n * consumer-projected `messageRenderer` slot template (EmbeddedViewRef path)\n * when present, otherwise falls back to the default `MessageItemComponent`\n * dynamic-component path. Both paths flow through the shared\n * `createRenderedEntry` / `updateMessageItemInstance` helpers.\n */\n private renderMessageItem(message: MJConversationDetailEntity, messages: MJConversationDetailEntity[], isLastMessage: boolean): void {\n const key = this.getMessageKey(message);\n // `index` is only used for the `isLastMessage` heuristic inside\n // updateMessageItemInstance — synthesize a value that produces the right\n // boolean (last index when `isLastMessage` is true, else 0 — any non-last\n // index works since it just affects that one comparison).\n const index = isLastMessage ? messages.length - 1 : 0;\n const useCustomRenderer = this.messageRendererTemplate !== null;\n const existing = this._renderedMessages.get(key);\n\n if (existing && existing.kind === 'embedded' && useCustomRenderer) {\n // Update existing embedded view from messageRenderer slot\n existing.ref.context.$implicit = message;\n existing.ref.context.message = message;\n existing.ref.markForCheck();\n return;\n }\n if (existing && existing.kind === 'component' && !useCustomRenderer) {\n // Update existing MessageItemComponent in place\n this.updateMessageItemInstance(existing.ref, message, messages, index);\n return;\n }\n if (existing) {\n // Rendering kind changed (e.g. component↔embedded, or a session block was\n // overwritten with a message). Destroy + recreate.\n existing.ref.destroy();\n this._renderedMessages.delete(key);\n }\n\n this.createRenderedEntry(message, messages, index, key, useCustomRenderer);\n }\n\n /**\n * Updates an existing `MessageItemComponent` in place — used on the default\n * (non-custom-renderer) path when a message's status / artifacts / agent-run /\n * etc. changes mid-stream.\n */\n private updateMessageItemInstance(\n ref: ComponentRef<MessageItemComponent>,\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number\n ): void {\n const instance = ref.instance;\n const previousMessage = instance.message;\n\n instance.message = message;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.messageExtraTemplate;\n\n this.applyArtifactsToInstance(instance, message.ID, ref.changeDetectorRef);\n\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n instance.ratings = this.ratingsMap.get(message.ID);\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n // Status change requires explicit markForCheck on the OnPush dynamic child.\n if (previousMessage && previousMessage.Status !== message.Status) {\n ref.changeDetectorRef.markForCheck();\n }\n }\n\n /**\n * Creates a new rendered entry — either a `MessageItemComponent` (default path)\n * or an `EmbeddedViewRef` from the consumer's `messageRenderer` slot template.\n * Stores the entry in `_renderedMessages` and stamps a back-reference on the\n * message entity.\n */\n private createRenderedEntry(\n message: MJConversationDetailEntity,\n messages: MJConversationDetailEntity[],\n index: number,\n key: string,\n useCustomRenderer: boolean\n ): void {\n if (useCustomRenderer && this.messageRendererTemplate) {\n // The slot directive carries TemplateRef<unknown>; assert the contract here\n // (consumers' `let-message` bindings consume the message context shape below).\n const template = this.messageRendererTemplate as TemplateRef<MessageRendererContext>;\n const viewRef = this.messageContainerRef.createEmbeddedView<MessageRendererContext>(\n template,\n { $implicit: message, message }\n );\n this._renderedMessages.set(key, { kind: 'embedded', ref: viewRef });\n // Stamp back-ref for parity with the component path.\n (message as unknown as { _viewRef?: EmbeddedViewRef<MessageRendererContext> })._viewRef = viewRef;\n return;\n }\n\n const componentRef = this.messageContainerRef.createComponent(MessageItemComponent);\n const instance = componentRef.instance;\n\n instance.message = message;\n instance.conversation = this.conversation;\n instance.currentUser = this.currentUser;\n instance.allMessages = messages;\n instance.isProcessing = this.isProcessing;\n instance.userAvatarMap = this.userAvatarMap;\n instance.isLastMessage = (index === messages.length - 1);\n instance.messageExtraTemplate = this.messageExtraTemplate;\n\n this.applyArtifactsToInstance(instance, message.ID, componentRef.changeDetectorRef);\n\n instance.agentRun = this.agentRunMap.get(message.ID) || null;\n instance.ratings = this.ratingsMap.get(message.ID);\n instance.attachments = this.attachmentsMap.get(message.ID) || [];\n\n instance.editClicked.subscribe((msg: MJConversationDetailEntity) => this.editMessage.emit(msg));\n instance.deleteClicked.subscribe((msg: MJConversationDetailEntity) => this.deleteMessage.emit(msg));\n instance.retryClicked.subscribe((msg: MJConversationDetailEntity) => this.retryMessage.emit(msg));\n instance.testFeedbackClicked.subscribe((msg: MJConversationDetailEntity) => this.testFeedbackMessage.emit(msg));\n instance.artifactClicked.subscribe((data: {artifactId: string; versionId?: string}) => this.artifactClicked.emit(data));\n instance.messageEdited.subscribe((msg: MJConversationDetailEntity) => this.messageEdited.emit(msg));\n instance.openEntityRecord.subscribe((data: {entityName: string; compositeKey: CompositeKey}) => this.openEntityRecord.emit(data));\n instance.suggestedResponseSelected.subscribe((data: {text: string; customInput?: string}) => this.suggestedResponseSelected.emit(data));\n instance.attachmentClicked.subscribe((attachment: MessageAttachment) => this.attachmentClicked.emit(attachment));\n instance.diagnosticRequested.subscribe((messageId: string) => this.diagnosticRequested.emit(messageId));\n instance.messagePinToggled.subscribe((msg: MJConversationDetailEntity) => this.messagePinToggled.emit(msg));\n instance.beforeResponseFormSubmitted.subscribe((e: BeforeResponseFormSubmittedEventArgs) => this.beforeResponseFormSubmitted.emit(e));\n instance.afterResponseFormSubmitted.subscribe((e: AfterResponseFormSubmittedEventArgs) => this.afterResponseFormSubmitted.emit(e));\n\n if (instance.artifactActionPerformed) {\n instance.artifactActionPerformed.subscribe((data: {action: string; artifactId: string}) => {\n // Parent can handle artifact actions (save, fork, history, share)\n console.log('Artifact action:', data);\n });\n }\n\n this._renderedMessages.set(key, { kind: 'component', ref: componentRef });\n // Preserve the existing back-ref pattern from the skip-chat performance design.\n (message as unknown as { _componentRef?: ComponentRef<MessageItemComponent> })._componentRef = componentRef;\n }\n\n /**\n * Resolves the DISTINCT artifacts for a message (one entry per artifactId at its\n * latest version), lazy-loads them all, and applies them to the rendered\n * message-item. Loads in the background so the UI never blocks.\n *\n * WHY WE SURFACE THEM ALL (design rationale — see PR discussion w/ Pranav & Ethan):\n * A single message can legitimately carry more than one DISTINCT artifact — e.g. a\n * research report PLUS a *standalone* generated infographic. This is deliberately\n * NOT in conflict with the server-side consolidation in AgentRunner\n * (Pranav, 5664b86: \"keep the report's embedded image in the report, not as a\n * duplicate artifact\"): that logic only suppresses media that is *embedded inline*\n * (base64) in another artifact's payload — a true duplicate. Genuinely standalone\n * sibling artifacts (the report uses SVG charts; the infographic is a separate JPEG)\n * are correctly kept as separate artifacts, and the UI must show every one of them.\n *\n * The earlier `artifactList[length - 1]` (\"show only the most recent\") approach\n * (EL-BC, 95492622) assumed consolidation always left exactly one artifact per\n * message; when it legitimately leaves two, that silently hid the report behind the\n * image. Grouping by artifactId (latest version each) shows all distinct artifacts\n * while still collapsing multiple *versions* of the same artifact to one card.\n */\n private applyArtifactsToInstance(\n instance: MessageItemComponent,\n messageId: string,\n childCdRef: ChangeDetectorRef\n ): void {\n const infos = this.resolveDistinctArtifacts(messageId);\n if (infos.length === 0) {\n instance.artifacts = [];\n instance.artifact = undefined;\n instance.artifactVersion = undefined;\n return;\n }\n\n Promise.all(\n infos.map(info =>\n Promise.all([info.getArtifact(), info.getVersion()]).then(([artifact, version]) => ({ artifact, version }))\n )\n )\n .then(refs => {\n instance.artifacts = refs;\n // Keep the legacy single inputs pointed at the first entry for back-compat.\n instance.artifact = refs[0]?.artifact;\n instance.artifactVersion = refs[0]?.version;\n // zone.js 0.15: parent detectChanges doesn't propagate to dynamically created children\n childCdRef.detectChanges();\n this.cdRef.detectChanges();\n })\n .catch(err => {\n console.error('Failed to lazy-load artifacts:', err);\n });\n }\n\n /**\n * Groups a message's artifact list by artifactId, keeping the highest version of\n * each. Multiple versions of the SAME artifact collapse to one card (latest wins),\n * while genuinely distinct artifacts are all retained.\n */\n private resolveDistinctArtifacts(messageId: string): LazyArtifactInfo[] {\n const list = this.artifactMap.get(messageId);\n if (!list || list.length === 0) {\n return [];\n }\n return selectDistinctLatestArtifacts(list);\n }\n\n /**\n * Generates a unique key for a message\n * Uses ID if available, otherwise uses a temporary key\n */\n private getMessageKey(message: MJConversationDetailEntity): string {\n return message.ID && message.ID.length > 0\n ? message.ID\n : `temp_${message.__mj_CreatedAt?.getTime() || Date.now()}`;\n }\n\n /**\n * Determines whether to show the date filter dropdown\n * Only show if conversation is long and spans multiple days\n */\n private updateDateFilterVisibility(): void {\n if (!this.messages || this.messages.length < 20) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n // Check if messages span more than 2 days\n const dates = this.messages\n .map(m => m.__mj_CreatedAt)\n .filter(d => d != null)\n .map(d => new Date(d!).setHours(0, 0, 0, 0));\n\n if (dates.length === 0) {\n this.shouldShowDateFilter = false;\n return;\n }\n\n const uniqueDates = new Set(dates);\n const daySpan = uniqueDates.size;\n\n // Show filter if conversation has 20+ messages and spans 3+ days\n this.shouldShowDateFilter = daySpan >= 3;\n }\n\n /**\n * Scrolls the message list to the bottom\n */\n private scrollToBottom(): void {\n if (this.scrollContainer && this.scrollContainer.nativeElement) {\n Promise.resolve().then(() => {\n const element = this.scrollContainer.nativeElement;\n element.scrollTop = element.scrollHeight;\n });\n }\n }\n\n /**\n * Removes a message from the rendered list\n * Called externally when a message is deleted\n */\n public removeMessage(message: MJConversationDetailEntity): void {\n const key = this.getMessageKey(message);\n const entry = this._renderedMessages.get(key);\n if (entry) {\n entry.ref.destroy();\n this._renderedMessages.delete(key);\n }\n }\n}","<div class=\"message-list-container\" #scrollContainer>\n <!-- Sticky Date Header (only show for long conversations spanning multiple days) -->\n @if (shouldShowDateFilter && messages.length > 0) {\n <div class=\"sticky-date-header\">\n <div class=\"sticky-date-wrapper\">\n <button class=\"sticky-date-button\" (click)=\"toggleDateNav()\">\n <span>{{ currentDateDisplay }}</span>\n <i class=\"fas fa-chevron-down\"></i>\n </button>\n <div class=\"date-nav-dropdown\" [class.show]=\"showDateNav\">\n <div class=\"date-nav-option jump-to\">Jump to...</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('today')\">Today</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('yesterday')\">Yesterday</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-week')\">Last week</div>\n <div class=\"date-nav-option\" (click)=\"jumpToDate('last-month')\">Last month</div>\n </div>\n </div>\n </div>\n }\n\n <ng-container #messageContainer></ng-container>\n\n @if (messages.length === 0) {\n <mj-empty-state\n class=\"messages-empty-fill\"\n Icon=\"fa-solid fa-comments\"\n Title=\"No messages yet. Start a conversation!\" />\n }\n</div>"]}
@@ -19,7 +19,7 @@ import { UserInfo, CompositeKey } from '@memberjunction/core';
19
19
  import { MJConversationEntity, MJTaskEntity } from '@memberjunction/core-entities';
20
20
  import { ClientToolResultEvent } from '@memberjunction/ai-agent-client';
21
21
  import { NavigationRequest } from '@memberjunction/ng-artifacts';
22
- import { PendingAttachment } from '../mention/mention-editor.component';
22
+ import { PendingAttachment } from '@memberjunction/ng-composer';
23
23
  import * as i0 from "@angular/core";
24
24
  /** Visual state of the overlay panel */
25
25
  export type ChatOverlayState = 'collapsed' | 'expanded' | 'maximized';
@@ -118,6 +118,9 @@ export declare class ChatAgentsOverlayComponent extends BaseAngularComponent imp
118
118
  IsNewConversation: boolean;
119
119
  /** Pending message to send after conversation creation */
120
120
  PendingMessage: string | null;
121
+ /** The conversation {@link PendingMessage} is destined for — pins the auto-send to that
122
+ * conversation's input so a fast conversation-swap can't redirect it elsewhere. */
123
+ PendingMessageConversationId: string | null;
121
124
  /** Pending attachments to send after conversation creation */
122
125
  PendingAttachments: PendingAttachment[] | null;
123
126
  /** Resize drag state */
@@ -1 +1 @@
1
- {"version":3,"file":"chat-overlay.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/overlay/chat-overlay.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-overlay.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/overlay/chat-overlay.component.ts"],"names":[],"mappings":"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"}
@@ -127,12 +127,12 @@ function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template(rf, ctx
127
127
  i0.ɵɵadvance();
128
128
  i0.ɵɵclassProp("fa-expand", ctx_r1.State !== "maximized")("fa-compress", ctx_r1.State === "maximized");
129
129
  i0.ɵɵadvance(4);
130
- i0.ɵɵproperty("environmentId", ctx_r1.EnvironmentId)("currentUser", ctx_r1.CurrentUser)("conversationId", ctx_r1.ConversationId)("conversation", ctx_r1.Conversation)("isNewConversation", ctx_r1.IsNewConversation)("pendingMessage", ctx_r1.PendingMessage)("pendingAttachments", ctx_r1.PendingAttachments)("overlayMode", true)("showExportButton", false)("showShareButton", false)("showArtifactIndicator", false)("appContext", ctx_r1.AppContext)("emptyStateGreeting", ctx_r1.EmptyStateGreeting);
130
+ i0.ɵɵproperty("environmentId", ctx_r1.EnvironmentId)("currentUser", ctx_r1.CurrentUser)("conversationId", ctx_r1.ConversationId)("conversation", ctx_r1.Conversation)("isNewConversation", ctx_r1.IsNewConversation)("pendingMessage", ctx_r1.PendingMessage)("pendingAttachments", ctx_r1.PendingAttachments)("pendingMessageConversationId", ctx_r1.PendingMessageConversationId)("overlayMode", true)("showExportButton", false)("showShareButton", false)("showArtifactIndicator", false)("appContext", ctx_r1.AppContext)("emptyStateGreeting", ctx_r1.EmptyStateGreeting);
131
131
  } }
132
132
  function ChatAgentsOverlayComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
133
133
  i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template, 7, 7, "div", 0);
134
134
  i0.ɵɵconditionalCreate(1, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template, 3, 3, "button", 1);
135
- i0.ɵɵconditionalCreate(2, ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template, 17, 28, "div", 2);
135
+ i0.ɵɵconditionalCreate(2, ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template, 17, 29, "div", 2);
136
136
  } if (rf & 2) {
137
137
  const ctx_r1 = i0.ɵɵnextContext();
138
138
  i0.ɵɵconditional(ctx_r1.State === "collapsed" && !ctx_r1.IsHidden ? 0 : -1);
@@ -244,6 +244,9 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
244
244
  IsNewConversation = true;
245
245
  /** Pending message to send after conversation creation */
246
246
  PendingMessage = null;
247
+ /** The conversation {@link PendingMessage} is destined for — pins the auto-send to that
248
+ * conversation's input so a fast conversation-swap can't redirect it elsewhere. */
249
+ PendingMessageConversationId = null;
247
250
  /** Pending attachments to send after conversation creation */
248
251
  PendingAttachments = null;
249
252
  /** Resize drag state */
@@ -329,6 +332,7 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
329
332
  // Set ALL state atomically before Angular change detection runs
330
333
  this.PendingMessage = event.pendingMessage || null;
331
334
  this.PendingAttachments = event.pendingAttachments || null;
335
+ this.PendingMessageConversationId = event.conversation.ID;
332
336
  const prevId = this._conversationId;
333
337
  this._conversationId = event.conversation.ID;
334
338
  this.Conversation = event.conversation;
@@ -340,6 +344,7 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
340
344
  OnPendingMessageConsumed() {
341
345
  this.PendingMessage = null;
342
346
  this.PendingAttachments = null;
347
+ this.PendingMessageConversationId = null;
343
348
  }
344
349
  /** Handle conversation rename from chat area */
345
350
  OnConversationRenamed(_event) {
@@ -664,7 +669,7 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
664
669
  });
665
670
  }
666
671
  static ɵfac = /*@__PURE__*/ (() => { let ɵChatAgentsOverlayComponent_BaseFactory; return function ChatAgentsOverlayComponent_Factory(__ngFactoryType__) { return (ɵChatAgentsOverlayComponent_BaseFactory || (ɵChatAgentsOverlayComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ChatAgentsOverlayComponent)))(__ngFactoryType__ || ChatAgentsOverlayComponent); }; })();
667
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ChatAgentsOverlayComponent, selectors: [["mj-chat-agents-overlay"]], inputs: { IsVisible: "IsVisible", CurrentUser: "CurrentUser", EnvironmentId: "EnvironmentId", AppContext: "AppContext", EmptyStateGreeting: "EmptyStateGreeting", TopBoundaryPx: "TopBoundaryPx" }, outputs: { VisibilityChanged: "VisibilityChanged", ToolExecuted: "ToolExecuted", ConversationSwitched: "ConversationSwitched", OpenFullChatWorkspace: "OpenFullChatWorkspace", NavigationRequested: "NavigationRequested", OpenEntityRecord: "OpenEntityRecord", TaskClicked: "TaskClicked" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[1, "chat-overlay-bubble", 3, "is-pressed", "is-dragging", "bottom"], ["type", "button", "title", "Open chat", "aria-label", "Open chat", 1, "chat-overlay-sliver", 3, "bottom"], [1, "chat-overlay-panel", 3, "maximized", "width", "height", "bottom"], [1, "chat-overlay-bubble", 3, "pointerdown"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-up", "chat-overlay-bubble-arrow", "chat-overlay-bubble-arrow-up"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down", "chat-overlay-bubble-arrow", "chat-overlay-bubble-arrow-down"], [1, "fa-solid", "fa-comments", "chat-overlay-bubble-icon"], [1, "chat-overlay-badge"], ["type", "button", "title", "Hide chat \u2014 a thin sliver will remain on the right edge", "aria-label", "Hide chat overlay", 1, "chat-overlay-bubble-close", 3, "pointerdown", "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], ["type", "button", "title", "Open chat", "aria-label", "Open chat", 1, "chat-overlay-sliver", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-comments", "chat-overlay-sliver-icon"], [1, "chat-overlay-badge", "chat-overlay-sliver-badge"], [1, "chat-overlay-panel"], [1, "chat-overlay-header"], [1, "chat-overlay-title"], [1, "fa-solid", "fa-robot"], [1, "chat-overlay-header-actions"], ["title", "New conversation", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-plus"], ["title", "Open in full chat workspace", 1, "chat-overlay-header-btn"], [1, "chat-overlay-header-btn", 3, "click", "title"], [1, "fa-solid"], ["title", "Minimize", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-minus"], [1, "chat-overlay-body"], [3, "conversationCreated", "conversationRenamed", "pendingMessageConsumed", "openEntityRecord", "navigationRequest", "taskClicked", "environmentId", "currentUser", "conversationId", "conversation", "isNewConversation", "pendingMessage", "pendingAttachments", "overlayMode", "showExportButton", "showShareButton", "showArtifactIndicator", "appContext", "emptyStateGreeting"], [1, "resize-handle", "resize-left", 3, "mousedown"], [1, "resize-handle", "resize-top", 3, "mousedown"], [1, "resize-handle", "resize-top-left", 3, "mousedown"], ["title", "Open in full chat workspace", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-up-right-from-square"]], template: function ChatAgentsOverlayComponent_Template(rf, ctx) { if (rf & 1) {
672
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ChatAgentsOverlayComponent, selectors: [["mj-chat-agents-overlay"]], inputs: { IsVisible: "IsVisible", CurrentUser: "CurrentUser", EnvironmentId: "EnvironmentId", AppContext: "AppContext", EmptyStateGreeting: "EmptyStateGreeting", TopBoundaryPx: "TopBoundaryPx" }, outputs: { VisibilityChanged: "VisibilityChanged", ToolExecuted: "ToolExecuted", ConversationSwitched: "ConversationSwitched", OpenFullChatWorkspace: "OpenFullChatWorkspace", NavigationRequested: "NavigationRequested", OpenEntityRecord: "OpenEntityRecord", TaskClicked: "TaskClicked" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[1, "chat-overlay-bubble", 3, "is-pressed", "is-dragging", "bottom"], ["type", "button", "title", "Open chat", "aria-label", "Open chat", 1, "chat-overlay-sliver", 3, "bottom"], [1, "chat-overlay-panel", 3, "maximized", "width", "height", "bottom"], [1, "chat-overlay-bubble", 3, "pointerdown"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-up", "chat-overlay-bubble-arrow", "chat-overlay-bubble-arrow-up"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down", "chat-overlay-bubble-arrow", "chat-overlay-bubble-arrow-down"], [1, "fa-solid", "fa-comments", "chat-overlay-bubble-icon"], [1, "chat-overlay-badge"], ["type", "button", "title", "Hide chat \u2014 a thin sliver will remain on the right edge", "aria-label", "Hide chat overlay", 1, "chat-overlay-bubble-close", 3, "pointerdown", "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], ["type", "button", "title", "Open chat", "aria-label", "Open chat", 1, "chat-overlay-sliver", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-comments", "chat-overlay-sliver-icon"], [1, "chat-overlay-badge", "chat-overlay-sliver-badge"], [1, "chat-overlay-panel"], [1, "chat-overlay-header"], [1, "chat-overlay-title"], [1, "fa-solid", "fa-robot"], [1, "chat-overlay-header-actions"], ["title", "New conversation", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-plus"], ["title", "Open in full chat workspace", 1, "chat-overlay-header-btn"], [1, "chat-overlay-header-btn", 3, "click", "title"], [1, "fa-solid"], ["title", "Minimize", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-minus"], [1, "chat-overlay-body"], [3, "conversationCreated", "conversationRenamed", "pendingMessageConsumed", "openEntityRecord", "navigationRequest", "taskClicked", "environmentId", "currentUser", "conversationId", "conversation", "isNewConversation", "pendingMessage", "pendingAttachments", "pendingMessageConversationId", "overlayMode", "showExportButton", "showShareButton", "showArtifactIndicator", "appContext", "emptyStateGreeting"], [1, "resize-handle", "resize-left", 3, "mousedown"], [1, "resize-handle", "resize-top", 3, "mousedown"], [1, "resize-handle", "resize-top-left", 3, "mousedown"], ["title", "Open in full chat workspace", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-up-right-from-square"]], template: function ChatAgentsOverlayComponent_Template(rf, ctx) { if (rf & 1) {
668
673
  i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Template, 3, 3);
669
674
  } if (rf & 2) {
670
675
  i0.ɵɵconditional(ctx.IsVisible ? 0 : -1);
@@ -672,7 +677,7 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
672
677
  }
673
678
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ChatAgentsOverlayComponent, [{
674
679
  type: Component,
675
- args: [{ standalone: false, selector: 'mj-chat-agents-overlay', template: "@if (IsVisible) {\n <!-- Floating Button (collapsed state, not hidden) -->\n @if (State === 'collapsed' && !IsHidden) {\n <div class=\"chat-overlay-bubble\"\n [class.is-pressed]=\"IsBubblePressed\"\n [class.is-dragging]=\"IsBubbleDragging\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (pointerdown)=\"OnBubblePointerDown($event)\">\n <i class=\"fa-solid fa-chevron-up chat-overlay-bubble-arrow chat-overlay-bubble-arrow-up\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-chevron-down chat-overlay-bubble-arrow chat-overlay-bubble-arrow-down\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-comments chat-overlay-bubble-icon\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n <!-- Hide affordance: revealed on hover. pointerdown stops drag from starting; click hides the bubble. -->\n <button type=\"button\"\n class=\"chat-overlay-bubble-close\"\n title=\"Hide chat \u2014 a thin sliver will remain on the right edge\"\n aria-label=\"Hide chat overlay\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"Hide($event)\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <!-- Collapsed sliver \u2014 flush with the right edge when the bubble is hidden.\n Click opens the chat directly; closing returns to the bubble (not the\n sliver). To re-enter hidden mode the user clicks the \u00D7 pill again. -->\n @if (State === 'collapsed' && IsHidden) {\n <button type=\"button\"\n class=\"chat-overlay-sliver\"\n title=\"Open chat\"\n aria-label=\"Open chat\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (click)=\"Expand()\">\n <i class=\"fa-solid fa-comments chat-overlay-sliver-icon\" aria-hidden=\"true\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge chat-overlay-sliver-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n </button>\n }\n\n <!-- Expanded / Maximized Chat Panel -->\n @if (State === 'expanded' || State === 'maximized') {\n <div class=\"chat-overlay-panel\"\n [class.maximized]=\"State === 'maximized'\"\n [style.width.px]=\"State === 'maximized' ? null : PanelWidth\"\n [style.height.px]=\"State === 'maximized' ? null : PanelHeight\"\n [style.bottom.px]=\"State === 'maximized' ? null : PanelBottomPx\">\n\n <!-- Resize handles (only in expanded, not maximized) -->\n @if (State === 'expanded') {\n <div class=\"resize-handle resize-left\"\n (mousedown)=\"OnResizeStart($event, 'left')\"></div>\n <div class=\"resize-handle resize-top\"\n (mousedown)=\"OnResizeStart($event, 'top')\"></div>\n <div class=\"resize-handle resize-top-left\"\n (mousedown)=\"OnResizeStart($event, 'top-left')\"></div>\n }\n\n <!-- Panel Header -->\n <div class=\"chat-overlay-header\">\n <div class=\"chat-overlay-title\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>AI Assistant</span>\n </div>\n <div class=\"chat-overlay-header-actions\">\n <button\n class=\"chat-overlay-header-btn\"\n title=\"New conversation\"\n (click)=\"StartNewConversation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n @if (ConversationId) {\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Open in full chat workspace\"\n (click)=\"OnOpenFullChatWorkspace()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n }\n <button\n class=\"chat-overlay-header-btn\"\n [title]=\"State === 'maximized' ? 'Restore size' : 'Maximize'\"\n (click)=\"ToggleMaximize()\">\n <i class=\"fa-solid\" [class.fa-expand]=\"State !== 'maximized'\" [class.fa-compress]=\"State === 'maximized'\"></i>\n </button>\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Minimize\"\n (click)=\"Collapse()\">\n <i class=\"fa-solid fa-minus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Chat Content \u2014 wraps conversation-chat-area -->\n <div class=\"chat-overlay-body\">\n <mj-conversation-chat-area\n [environmentId]=\"EnvironmentId\"\n [currentUser]=\"CurrentUser\"\n [conversationId]=\"ConversationId\"\n [conversation]=\"Conversation\"\n [isNewConversation]=\"IsNewConversation\"\n [pendingMessage]=\"PendingMessage\"\n [pendingAttachments]=\"PendingAttachments\"\n [overlayMode]=\"true\"\n [showExportButton]=\"false\"\n [showShareButton]=\"false\"\n [showArtifactIndicator]=\"false\"\n [appContext]=\"AppContext\"\n [emptyStateGreeting]=\"EmptyStateGreeting\"\n (conversationCreated)=\"OnConversationCreated($event)\"\n (conversationRenamed)=\"OnConversationRenamed($event)\"\n (pendingMessageConsumed)=\"OnPendingMessageConsumed()\"\n (openEntityRecord)=\"OnOpenEntityRecord($event)\"\n (navigationRequest)=\"OnNavigationRequest($event)\"\n (taskClicked)=\"OnTaskClicked($event)\"\n ></mj-conversation-chat-area>\n </div>\n </div>\n }\n}\n", styles: ["/* ============================================================\n Chat Overlay \u2014 Floating Bubble + Expanding Panel\n All colors use MJ design tokens (--mj-* CSS variables).\n ============================================================ */\n\n/* --- Floating Bubble (collapsed state) --- */\n\n.chat-overlay-bubble {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n width: 3.5rem;\n height: 3.5rem;\n border-radius: 50%;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n z-index: 2147483647;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: overlayBubbleIn 0.3s ease;\n /* Required for touch drag: blocks browser pan/zoom so pointermove fires\n continuously instead of being swallowed by scroll-handling. */\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n/* Subtle up/down chevrons just outside the bubble, hinting that it can be\n dragged vertically. On hover-capable devices (mouse/pen) they stay hidden\n in the resting state and reveal on hover/press/drag \u2014 keeps the corner\n visually clean. On touch-only devices (no hover) they're always visible at\n low opacity so the affordance is discoverable without needing a hover. */\n.chat-overlay-bubble-arrow {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n color: var(--mj-text-muted);\n font-size: 0.65rem;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.18s ease;\n}\n\n.chat-overlay-bubble-arrow-up {\n top: -0.85rem;\n}\n\n.chat-overlay-bubble-arrow-down {\n bottom: -0.85rem;\n}\n\n/* Hover-capable devices: reveal on hover, press, or active drag. */\n.chat-overlay-bubble:hover .chat-overlay-bubble-arrow,\n.chat-overlay-bubble.is-pressed .chat-overlay-bubble-arrow,\n.chat-overlay-bubble.is-dragging .chat-overlay-bubble-arrow {\n opacity: 0.85;\n}\n\n/* Touch-only devices (no hover): always show at subtle opacity. The\n :hover/.is-pressed/.is-dragging rules above still apply via higher\n specificity, so touching the bubble briefly bumps them to 0.85. */\n@media (hover: none) {\n .chat-overlay-bubble-arrow {\n opacity: 0.5;\n }\n}\n\n.chat-overlay-bubble:hover {\n transform: scale(1.08);\n box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);\n}\n\n/* Immediate press feedback \u2014 fires on mousedown before the drag threshold is crossed,\n so the user sees \"I'm being held\" right away and learns the bubble is draggable. */\n.chat-overlay-bubble.is-pressed {\n cursor: grabbing;\n transform: scale(0.94);\n transition: transform 0.08s ease;\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.25),\n 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n/* Active drag \u2014 overrides the press state once movement passes the threshold. */\n.chat-overlay-bubble.is-dragging {\n cursor: grabbing;\n transform: scale(1.04);\n transition: none;\n box-shadow:\n 0 8px 28px rgba(0, 0, 0, 0.35),\n 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n@keyframes overlayBubbleIn {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.chat-overlay-bubble-icon {\n font-size: 1.3rem;\n}\n\n.chat-overlay-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 1.2rem;\n height: 1.2rem;\n border-radius: 9999px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 0.65rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 0.25rem;\n border: 2px solid var(--mj-bg-page);\n}\n\n/* --- Hide-bubble affordance (\"\u00D7\" pill on the outer-left edge of the bubble) ---\n Revealed on hover. Touch-only devices (no hover) get a permanent low-opacity\n render so the affordance is reachable without a hover gesture. */\n.chat-overlay-bubble-close {\n position: absolute;\n top: 50%;\n /* Sits flush with the bubble's left bounding-box edge \u2014 no dead-zone gap that\n would drop the :hover state mid-reach. The bubble's circular shape means the\n visible space between the circle and the pill still reads as a gap. */\n right: 100%;\n transform: translateY(-50%);\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border-radius: 9999px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-strong);\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.65rem;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;\n}\n\n.chat-overlay-bubble:hover .chat-overlay-bubble-close {\n opacity: 1;\n pointer-events: auto;\n}\n\n.chat-overlay-bubble-close:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-brand-primary);\n transform: translateY(-50%) scale(1.08);\n}\n\n/* Touch devices: keep the pill reachable without a hover gesture. */\n@media (hover: none) {\n .chat-overlay-bubble-close {\n opacity: 0.7;\n pointer-events: auto;\n }\n}\n\n/* While actively dragging, suppress the close pill \u2014 it shouldn't compete with the drag affordance. */\n.chat-overlay-bubble.is-dragging .chat-overlay-bubble-close,\n.chat-overlay-bubble.is-pressed .chat-overlay-bubble-close {\n opacity: 0;\n pointer-events: none;\n}\n\n/* --- Collapsed sliver (right edge, replaces bubble when hidden) --- */\n\n.chat-overlay-sliver {\n position: fixed;\n right: 0;\n width: 0.875rem; /* 14px sliver */\n height: 5rem; /* 80px tall */\n padding: 0;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px 0 0 8px;\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n z-index: 2147483647;\n transition: width 0.18s ease, background 0.15s ease;\n animation: overlayBubbleIn 0.25s ease;\n}\n\n.chat-overlay-sliver:hover {\n width: 1.5rem; /* widens slightly to invite the click */\n background: color-mix(in srgb, var(--mj-brand-primary) 85%, white);\n}\n\n.chat-overlay-sliver-icon {\n font-size: 0.55rem;\n opacity: 0.95;\n}\n\n.chat-overlay-sliver:hover .chat-overlay-sliver-icon {\n font-size: 0.7rem;\n}\n\n.chat-overlay-sliver-badge {\n /* Pull the badge a hair outside the sliver so it isn't clipped by the narrow width. */\n top: -6px;\n right: -6px;\n}\n\n/* --- Expanded Panel --- */\n\n.chat-overlay-panel {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n border-radius: 12px;\n background: var(--mj-bg-surface);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-border-strong));\n box-shadow:\n 0 8px 32px rgba(0, 0, 0, 0.3),\n 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 2147483647;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: overlayPanelIn 0.25s ease;\n max-height: calc(100vh - 3rem);\n max-width: calc(100vw - 3rem);\n}\n\n.chat-overlay-panel.maximized {\n bottom: 1rem;\n right: 1rem;\n width: calc(100vw - 2rem) !important;\n height: calc(100vh - 2rem) !important;\n max-height: none;\n max-width: none;\n border-radius: 12px;\n}\n\n@keyframes overlayPanelIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(10px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* --- Resize Handles --- */\n\n.resize-handle {\n position: absolute;\n z-index: 2;\n}\n\n.resize-left {\n left: -3px;\n top: 20px;\n bottom: 20px;\n width: 6px;\n cursor: ew-resize;\n}\n\n.resize-top {\n top: -3px;\n left: 20px;\n right: 20px;\n height: 6px;\n cursor: ns-resize;\n}\n\n.resize-top-left {\n top: -4px;\n left: -4px;\n width: 16px;\n height: 16px;\n cursor: nwse-resize;\n}\n\n.resize-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 3px;\n}\n\n/* --- Panel Header --- */\n\n.chat-overlay-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.6rem 0.75rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.chat-overlay-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.chat-overlay-title i {\n color: var(--mj-brand-primary);\n}\n\n.chat-overlay-header-actions {\n display: flex;\n gap: 0.25rem;\n}\n\n.chat-overlay-header-btn {\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 6px;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n transition: all 0.15s ease;\n}\n\n.chat-overlay-header-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* --- Panel Body --- */\n\n.chat-overlay-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.chat-overlay-body mj-conversation-chat-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* --- Mobile / Small-Screen Responsive ---\n 640px = small-screen cutoff (covers all phones in both orientations). Tablets\n in portrait (\u2265768px) keep the floating-panel treatment because they have the\n real estate for it. */\n\n@media (max-width: 640px) {\n .chat-overlay-panel {\n bottom: 0 !important;\n right: 0;\n width: 100% !important;\n height: 100vh !important;\n max-height: 100vh;\n border-radius: 0;\n }\n\n .chat-overlay-bubble {\n /* No !important on `bottom` \u2014 the inline [style.bottom.px] binding owns it\n so users can drag the bubble out of the way of underlying app buttons.\n Smaller diameter on small screens: 2.75rem (44px) hits the WCAG minimum\n touch target while ~38% less occluding than the desktop 3.5rem. */\n width: 2.75rem;\n height: 2.75rem;\n right: 1rem;\n }\n\n .chat-overlay-bubble-icon {\n font-size: 1.1rem;\n }\n\n .chat-overlay-badge {\n min-width: 1rem;\n height: 1rem;\n font-size: 0.6rem;\n top: -3px;\n right: -3px;\n }\n\n .resize-handle {\n display: none;\n }\n\n /* Slightly wider sliver on touch so it meets the WCAG minimum touch target. */\n .chat-overlay-sliver {\n width: 1.25rem;\n height: 4.5rem;\n }\n}\n"] }]
680
+ args: [{ standalone: false, selector: 'mj-chat-agents-overlay', template: "@if (IsVisible) {\n <!-- Floating Button (collapsed state, not hidden) -->\n @if (State === 'collapsed' && !IsHidden) {\n <div class=\"chat-overlay-bubble\"\n [class.is-pressed]=\"IsBubblePressed\"\n [class.is-dragging]=\"IsBubbleDragging\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (pointerdown)=\"OnBubblePointerDown($event)\">\n <i class=\"fa-solid fa-chevron-up chat-overlay-bubble-arrow chat-overlay-bubble-arrow-up\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-chevron-down chat-overlay-bubble-arrow chat-overlay-bubble-arrow-down\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-comments chat-overlay-bubble-icon\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n <!-- Hide affordance: revealed on hover. pointerdown stops drag from starting; click hides the bubble. -->\n <button type=\"button\"\n class=\"chat-overlay-bubble-close\"\n title=\"Hide chat \u2014 a thin sliver will remain on the right edge\"\n aria-label=\"Hide chat overlay\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"Hide($event)\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <!-- Collapsed sliver \u2014 flush with the right edge when the bubble is hidden.\n Click opens the chat directly; closing returns to the bubble (not the\n sliver). To re-enter hidden mode the user clicks the \u00D7 pill again. -->\n @if (State === 'collapsed' && IsHidden) {\n <button type=\"button\"\n class=\"chat-overlay-sliver\"\n title=\"Open chat\"\n aria-label=\"Open chat\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (click)=\"Expand()\">\n <i class=\"fa-solid fa-comments chat-overlay-sliver-icon\" aria-hidden=\"true\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge chat-overlay-sliver-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n </button>\n }\n\n <!-- Expanded / Maximized Chat Panel -->\n @if (State === 'expanded' || State === 'maximized') {\n <div class=\"chat-overlay-panel\"\n [class.maximized]=\"State === 'maximized'\"\n [style.width.px]=\"State === 'maximized' ? null : PanelWidth\"\n [style.height.px]=\"State === 'maximized' ? null : PanelHeight\"\n [style.bottom.px]=\"State === 'maximized' ? null : PanelBottomPx\">\n\n <!-- Resize handles (only in expanded, not maximized) -->\n @if (State === 'expanded') {\n <div class=\"resize-handle resize-left\"\n (mousedown)=\"OnResizeStart($event, 'left')\"></div>\n <div class=\"resize-handle resize-top\"\n (mousedown)=\"OnResizeStart($event, 'top')\"></div>\n <div class=\"resize-handle resize-top-left\"\n (mousedown)=\"OnResizeStart($event, 'top-left')\"></div>\n }\n\n <!-- Panel Header -->\n <div class=\"chat-overlay-header\">\n <div class=\"chat-overlay-title\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>AI Assistant</span>\n </div>\n <div class=\"chat-overlay-header-actions\">\n <button\n class=\"chat-overlay-header-btn\"\n title=\"New conversation\"\n (click)=\"StartNewConversation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n @if (ConversationId) {\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Open in full chat workspace\"\n (click)=\"OnOpenFullChatWorkspace()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n }\n <button\n class=\"chat-overlay-header-btn\"\n [title]=\"State === 'maximized' ? 'Restore size' : 'Maximize'\"\n (click)=\"ToggleMaximize()\">\n <i class=\"fa-solid\" [class.fa-expand]=\"State !== 'maximized'\" [class.fa-compress]=\"State === 'maximized'\"></i>\n </button>\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Minimize\"\n (click)=\"Collapse()\">\n <i class=\"fa-solid fa-minus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Chat Content \u2014 wraps conversation-chat-area -->\n <div class=\"chat-overlay-body\">\n <mj-conversation-chat-area\n [environmentId]=\"EnvironmentId\"\n [currentUser]=\"CurrentUser\"\n [conversationId]=\"ConversationId\"\n [conversation]=\"Conversation\"\n [isNewConversation]=\"IsNewConversation\"\n [pendingMessage]=\"PendingMessage\"\n [pendingAttachments]=\"PendingAttachments\"\n [pendingMessageConversationId]=\"PendingMessageConversationId\"\n [overlayMode]=\"true\"\n [showExportButton]=\"false\"\n [showShareButton]=\"false\"\n [showArtifactIndicator]=\"false\"\n [appContext]=\"AppContext\"\n [emptyStateGreeting]=\"EmptyStateGreeting\"\n (conversationCreated)=\"OnConversationCreated($event)\"\n (conversationRenamed)=\"OnConversationRenamed($event)\"\n (pendingMessageConsumed)=\"OnPendingMessageConsumed()\"\n (openEntityRecord)=\"OnOpenEntityRecord($event)\"\n (navigationRequest)=\"OnNavigationRequest($event)\"\n (taskClicked)=\"OnTaskClicked($event)\"\n ></mj-conversation-chat-area>\n </div>\n </div>\n }\n}\n", styles: ["/* ============================================================\n Chat Overlay \u2014 Floating Bubble + Expanding Panel\n All colors use MJ design tokens (--mj-* CSS variables).\n ============================================================ */\n\n/* --- Floating Bubble (collapsed state) --- */\n\n.chat-overlay-bubble {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n width: 3.5rem;\n height: 3.5rem;\n border-radius: 50%;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n z-index: 2147483647;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: overlayBubbleIn 0.3s ease;\n /* Required for touch drag: blocks browser pan/zoom so pointermove fires\n continuously instead of being swallowed by scroll-handling. */\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n/* Subtle up/down chevrons just outside the bubble, hinting that it can be\n dragged vertically. On hover-capable devices (mouse/pen) they stay hidden\n in the resting state and reveal on hover/press/drag \u2014 keeps the corner\n visually clean. On touch-only devices (no hover) they're always visible at\n low opacity so the affordance is discoverable without needing a hover. */\n.chat-overlay-bubble-arrow {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n color: var(--mj-text-muted);\n font-size: 0.65rem;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.18s ease;\n}\n\n.chat-overlay-bubble-arrow-up {\n top: -0.85rem;\n}\n\n.chat-overlay-bubble-arrow-down {\n bottom: -0.85rem;\n}\n\n/* Hover-capable devices: reveal on hover, press, or active drag. */\n.chat-overlay-bubble:hover .chat-overlay-bubble-arrow,\n.chat-overlay-bubble.is-pressed .chat-overlay-bubble-arrow,\n.chat-overlay-bubble.is-dragging .chat-overlay-bubble-arrow {\n opacity: 0.85;\n}\n\n/* Touch-only devices (no hover): always show at subtle opacity. The\n :hover/.is-pressed/.is-dragging rules above still apply via higher\n specificity, so touching the bubble briefly bumps them to 0.85. */\n@media (hover: none) {\n .chat-overlay-bubble-arrow {\n opacity: 0.5;\n }\n}\n\n.chat-overlay-bubble:hover {\n transform: scale(1.08);\n box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);\n}\n\n/* Immediate press feedback \u2014 fires on mousedown before the drag threshold is crossed,\n so the user sees \"I'm being held\" right away and learns the bubble is draggable. */\n.chat-overlay-bubble.is-pressed {\n cursor: grabbing;\n transform: scale(0.94);\n transition: transform 0.08s ease;\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.25),\n 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n/* Active drag \u2014 overrides the press state once movement passes the threshold. */\n.chat-overlay-bubble.is-dragging {\n cursor: grabbing;\n transform: scale(1.04);\n transition: none;\n box-shadow:\n 0 8px 28px rgba(0, 0, 0, 0.35),\n 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n@keyframes overlayBubbleIn {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.chat-overlay-bubble-icon {\n font-size: 1.3rem;\n}\n\n.chat-overlay-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 1.2rem;\n height: 1.2rem;\n border-radius: 9999px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 0.65rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 0.25rem;\n border: 2px solid var(--mj-bg-page);\n}\n\n/* --- Hide-bubble affordance (\"\u00D7\" pill on the outer-left edge of the bubble) ---\n Revealed on hover. Touch-only devices (no hover) get a permanent low-opacity\n render so the affordance is reachable without a hover gesture. */\n.chat-overlay-bubble-close {\n position: absolute;\n top: 50%;\n /* Sits flush with the bubble's left bounding-box edge \u2014 no dead-zone gap that\n would drop the :hover state mid-reach. The bubble's circular shape means the\n visible space between the circle and the pill still reads as a gap. */\n right: 100%;\n transform: translateY(-50%);\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border-radius: 9999px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-strong);\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.65rem;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;\n}\n\n.chat-overlay-bubble:hover .chat-overlay-bubble-close {\n opacity: 1;\n pointer-events: auto;\n}\n\n.chat-overlay-bubble-close:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-brand-primary);\n transform: translateY(-50%) scale(1.08);\n}\n\n/* Touch devices: keep the pill reachable without a hover gesture. */\n@media (hover: none) {\n .chat-overlay-bubble-close {\n opacity: 0.7;\n pointer-events: auto;\n }\n}\n\n/* While actively dragging, suppress the close pill \u2014 it shouldn't compete with the drag affordance. */\n.chat-overlay-bubble.is-dragging .chat-overlay-bubble-close,\n.chat-overlay-bubble.is-pressed .chat-overlay-bubble-close {\n opacity: 0;\n pointer-events: none;\n}\n\n/* --- Collapsed sliver (right edge, replaces bubble when hidden) --- */\n\n.chat-overlay-sliver {\n position: fixed;\n right: 0;\n width: 0.875rem; /* 14px sliver */\n height: 5rem; /* 80px tall */\n padding: 0;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px 0 0 8px;\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n z-index: 2147483647;\n transition: width 0.18s ease, background 0.15s ease;\n animation: overlayBubbleIn 0.25s ease;\n}\n\n.chat-overlay-sliver:hover {\n width: 1.5rem; /* widens slightly to invite the click */\n background: color-mix(in srgb, var(--mj-brand-primary) 85%, white);\n}\n\n.chat-overlay-sliver-icon {\n font-size: 0.55rem;\n opacity: 0.95;\n}\n\n.chat-overlay-sliver:hover .chat-overlay-sliver-icon {\n font-size: 0.7rem;\n}\n\n.chat-overlay-sliver-badge {\n /* Pull the badge a hair outside the sliver so it isn't clipped by the narrow width. */\n top: -6px;\n right: -6px;\n}\n\n/* --- Expanded Panel --- */\n\n.chat-overlay-panel {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n border-radius: 12px;\n background: var(--mj-bg-surface);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-border-strong));\n box-shadow:\n 0 8px 32px rgba(0, 0, 0, 0.3),\n 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 2147483647;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: overlayPanelIn 0.25s ease;\n max-height: calc(100vh - 3rem);\n max-width: calc(100vw - 3rem);\n}\n\n.chat-overlay-panel.maximized {\n bottom: 1rem;\n right: 1rem;\n width: calc(100vw - 2rem) !important;\n height: calc(100vh - 2rem) !important;\n max-height: none;\n max-width: none;\n border-radius: 12px;\n}\n\n@keyframes overlayPanelIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(10px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* --- Resize Handles --- */\n\n.resize-handle {\n position: absolute;\n z-index: 2;\n}\n\n.resize-left {\n left: -3px;\n top: 20px;\n bottom: 20px;\n width: 6px;\n cursor: ew-resize;\n}\n\n.resize-top {\n top: -3px;\n left: 20px;\n right: 20px;\n height: 6px;\n cursor: ns-resize;\n}\n\n.resize-top-left {\n top: -4px;\n left: -4px;\n width: 16px;\n height: 16px;\n cursor: nwse-resize;\n}\n\n.resize-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 3px;\n}\n\n/* --- Panel Header --- */\n\n.chat-overlay-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.6rem 0.75rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.chat-overlay-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.chat-overlay-title i {\n color: var(--mj-brand-primary);\n}\n\n.chat-overlay-header-actions {\n display: flex;\n gap: 0.25rem;\n}\n\n.chat-overlay-header-btn {\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 6px;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n transition: all 0.15s ease;\n}\n\n.chat-overlay-header-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* --- Panel Body --- */\n\n.chat-overlay-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.chat-overlay-body mj-conversation-chat-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* --- Mobile / Small-Screen Responsive ---\n 640px = small-screen cutoff (covers all phones in both orientations). Tablets\n in portrait (\u2265768px) keep the floating-panel treatment because they have the\n real estate for it. */\n\n@media (max-width: 640px) {\n .chat-overlay-panel {\n bottom: 0 !important;\n right: 0;\n width: 100% !important;\n height: 100vh !important;\n max-height: 100vh;\n border-radius: 0;\n }\n\n .chat-overlay-bubble {\n /* No !important on `bottom` \u2014 the inline [style.bottom.px] binding owns it\n so users can drag the bubble out of the way of underlying app buttons.\n Smaller diameter on small screens: 2.75rem (44px) hits the WCAG minimum\n touch target while ~38% less occluding than the desktop 3.5rem. */\n width: 2.75rem;\n height: 2.75rem;\n right: 1rem;\n }\n\n .chat-overlay-bubble-icon {\n font-size: 1.1rem;\n }\n\n .chat-overlay-badge {\n min-width: 1rem;\n height: 1rem;\n font-size: 0.6rem;\n top: -3px;\n right: -3px;\n }\n\n .resize-handle {\n display: none;\n }\n\n /* Slightly wider sliver on touch so it meets the WCAG minimum touch target. */\n .chat-overlay-sliver {\n width: 1.25rem;\n height: 4.5rem;\n }\n}\n"] }]
676
681
  }], null, { IsVisible: [{
677
682
  type: Input
678
683
  }], CurrentUser: [{