@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
@@ -1,1233 +0,0 @@
1
- import { Component, Input, Output, EventEmitter, ViewChild, forwardRef } from '@angular/core';
2
- import { NG_VALUE_ACCESSOR } from '@angular/forms';
3
- import { AIEngineBase } from '@memberjunction/ai-engine-base';
4
- import { UUIDsEqual } from '@memberjunction/global';
5
- import * as i0 from "@angular/core";
6
- import * as i1 from "../../services/mention-autocomplete.service";
7
- import * as i2 from "./mention-dropdown.component";
8
- const _c0 = ["editor"];
9
- function MentionEditorComponent_Conditional_1_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
10
- i0.ɵɵelement(0, "img", 8);
11
- } if (rf & 2) {
12
- const attachment_r3 = i0.ɵɵnextContext().$implicit;
13
- i0.ɵɵproperty("src", attachment_r3.thumbnailUrl, i0.ɵɵsanitizeUrl)("alt", attachment_r3.fileName);
14
- } }
15
- function MentionEditorComponent_Conditional_1_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
16
- i0.ɵɵelementStart(0, "div", 9);
17
- i0.ɵɵelement(1, "i", 12);
18
- i0.ɵɵelementStart(2, "span", 13);
19
- i0.ɵɵtext(3);
20
- i0.ɵɵelementEnd()();
21
- } if (rf & 2) {
22
- const attachment_r3 = i0.ɵɵnextContext().$implicit;
23
- i0.ɵɵadvance(3);
24
- i0.ɵɵtextInterpolate(attachment_r3.fileName);
25
- } }
26
- function MentionEditorComponent_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
27
- const _r2 = i0.ɵɵgetCurrentView();
28
- i0.ɵɵelementStart(0, "div", 7);
29
- i0.ɵɵlistener("click", function MentionEditorComponent_Conditional_1_For_2_Template_div_click_0_listener() { const attachment_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onAttachmentClick(attachment_r3)); });
30
- i0.ɵɵconditionalCreate(1, MentionEditorComponent_Conditional_1_For_2_Conditional_1_Template, 1, 2, "img", 8);
31
- i0.ɵɵconditionalCreate(2, MentionEditorComponent_Conditional_1_For_2_Conditional_2_Template, 4, 1, "div", 9);
32
- i0.ɵɵelementStart(3, "button", 10);
33
- i0.ɵɵlistener("click", function MentionEditorComponent_Conditional_1_For_2_Template_button_click_3_listener($event) { const attachment_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); ctx_r3.removeAttachment(attachment_r3.id); return i0.ɵɵresetView($event.stopPropagation()); });
34
- i0.ɵɵelement(4, "i", 11);
35
- i0.ɵɵelementEnd()();
36
- } if (rf & 2) {
37
- const attachment_r3 = ctx.$implicit;
38
- i0.ɵɵadvance();
39
- i0.ɵɵconditional(attachment_r3.thumbnailUrl ? 1 : -1);
40
- i0.ɵɵadvance();
41
- i0.ɵɵconditional(!attachment_r3.thumbnailUrl ? 2 : -1);
42
- } }
43
- function MentionEditorComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
44
- i0.ɵɵelementStart(0, "div", 2);
45
- i0.ɵɵrepeaterCreate(1, MentionEditorComponent_Conditional_1_For_2_Template, 5, 2, "div", 6, i0.ɵɵrepeaterTrackByIdentity);
46
- i0.ɵɵelementEnd();
47
- } if (rf & 2) {
48
- const ctx_r3 = i0.ɵɵnextContext();
49
- i0.ɵɵadvance();
50
- i0.ɵɵrepeater(ctx_r3.pendingAttachments);
51
- } }
52
- function MentionEditorComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
53
- i0.ɵɵelementStart(0, "div", 4)(1, "div", 14);
54
- i0.ɵɵelement(2, "i", 15);
55
- i0.ɵɵelementStart(3, "span");
56
- i0.ɵɵtext(4, "Drop files here");
57
- i0.ɵɵelementEnd()()();
58
- } }
59
- function MentionEditorComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
60
- const _r5 = i0.ɵɵgetCurrentView();
61
- i0.ɵɵelementStart(0, "mj-mention-dropdown", 16);
62
- i0.ɵɵlistener("suggestionSelected", function MentionEditorComponent_Conditional_5_Template_mj_mention_dropdown_suggestionSelected_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onMentionSelected($event)); })("closed", function MentionEditorComponent_Conditional_5_Template_mj_mention_dropdown_closed_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeMentionDropdown()); });
63
- i0.ɵɵelementEnd();
64
- } if (rf & 2) {
65
- const ctx_r3 = i0.ɵɵnextContext();
66
- i0.ɵɵproperty("suggestions", ctx_r3.mentionSuggestions)("position", ctx_r3.mentionDropdownPosition)("showAbove", ctx_r3.mentionDropdownShowAbove)("useFixedPositioning", true)("visible", true);
67
- } }
68
- /**
69
- * ContentEditable-based mention editor with visual chips/pills
70
- * Provides Slack/Teams-style mention UX with immutable mention tokens
71
- */
72
- export class MentionEditorComponent {
73
- mentionAutocomplete;
74
- cdr;
75
- editorRef;
76
- placeholder = 'Type @ to mention agents or users, # for entities...';
77
- disabled = false;
78
- currentUser;
79
- enableMentions = true;
80
- // Attachment settings
81
- enableAttachments = true;
82
- maxAttachments = 10;
83
- maxAttachmentSizeBytes = 20 * 1024 * 1024; // 20MB default
84
- acceptedFileTypes = 'image/*'; // MIME types to accept
85
- valueChange = new EventEmitter();
86
- mentionSelected = new EventEmitter();
87
- enterPressed = new EventEmitter();
88
- attachmentsChanged = new EventEmitter();
89
- attachmentError = new EventEmitter();
90
- attachmentClicked = new EventEmitter();
91
- // Pending attachments state
92
- pendingAttachments = [];
93
- isDragOver = false;
94
- // Mention dropdown state
95
- showMentionDropdown = false;
96
- mentionSuggestions = [];
97
- mentionDropdownPosition = { top: 0, left: 0 };
98
- mentionDropdownShowAbove = false;
99
- mentionStartIndex = -1;
100
- mentionQuery = '';
101
- /** Mention trigger characters: '@' for agents/users, '#' for entities */
102
- static MENTION_TRIGGERS = ['@', '#'];
103
- /** The trigger char that opened the current mention dropdown */
104
- activeTrigger = '@';
105
- onChange = () => { };
106
- onTouched = () => { };
107
- constructor(mentionAutocomplete, cdr) {
108
- this.mentionAutocomplete = mentionAutocomplete;
109
- this.cdr = cdr;
110
- }
111
- async ngOnInit() {
112
- if (this.enableMentions && this.currentUser) {
113
- await this.mentionAutocomplete.initialize(this.currentUser);
114
- }
115
- }
116
- ngAfterViewInit() {
117
- // Auto-focus the editor
118
- setTimeout(() => {
119
- this.editorRef?.nativeElement?.focus();
120
- }, 100);
121
- }
122
- /**
123
- * Handle clicks on the container - focus the editor if clicking outside the contentEditable
124
- */
125
- onContainerClick(event) {
126
- const target = event.target;
127
- const editor = this.editorRef?.nativeElement;
128
- // Don't handle clicks on the dropdown or its children
129
- if (target.closest('mj-mention-dropdown')) {
130
- return;
131
- }
132
- // If clicking on container or any element that's not the editor itself, focus the editor
133
- if (target !== editor && !editor?.contains(target)) {
134
- editor?.focus();
135
- // Move cursor to end of content
136
- const selection = window.getSelection();
137
- const range = document.createRange();
138
- if (editor && selection) {
139
- range.selectNodeContents(editor);
140
- range.collapse(false); // Collapse to end
141
- selection.removeAllRanges();
142
- selection.addRange(range);
143
- }
144
- }
145
- }
146
- /**
147
- * Handle input changes in contentEditable
148
- */
149
- onInput() {
150
- const plainText = this.getPlainText();
151
- this.onChange(plainText);
152
- this.valueChange.emit(plainText);
153
- // Handle @mention autocomplete
154
- if (this.enableMentions && this.currentUser) {
155
- this.handleMentionInput();
156
- }
157
- }
158
- /**
159
- * Handle blur event - close dropdown when editor loses focus
160
- */
161
- onBlur() {
162
- // Call form control touched callback
163
- this.onTouched();
164
- // Close dropdown when editor loses focus
165
- // Use setTimeout to allow mousedown events on dropdown to fire first
166
- setTimeout(() => {
167
- if (this.showMentionDropdown) {
168
- this.closeMentionDropdown();
169
- }
170
- }, 200);
171
- }
172
- /**
173
- * Handle paste event - images or plain text
174
- */
175
- onPaste(event) {
176
- // Check for image data in clipboard
177
- if (this.enableAttachments && event.clipboardData?.items) {
178
- const items = Array.from(event.clipboardData.items);
179
- const imageItems = items.filter(item => item.type.startsWith('image/'));
180
- if (imageItems.length > 0) {
181
- event.preventDefault();
182
- // Process each image
183
- for (const item of imageItems) {
184
- const file = item.getAsFile();
185
- if (file) {
186
- this.processFile(file);
187
- }
188
- }
189
- return;
190
- }
191
- }
192
- // No images - handle as plain text
193
- event.preventDefault();
194
- // Get plain text from clipboard
195
- const text = event.clipboardData?.getData('text/plain') || '';
196
- if (!text)
197
- return;
198
- // Insert plain text at cursor position
199
- const selection = window.getSelection();
200
- if (!selection || selection.rangeCount === 0)
201
- return;
202
- const range = selection.getRangeAt(0);
203
- range.deleteContents();
204
- // Insert text as text node (not HTML)
205
- const textNode = document.createTextNode(text);
206
- range.insertNode(textNode);
207
- // Move cursor to end of inserted text
208
- range.setStartAfter(textNode);
209
- range.collapse(true);
210
- selection.removeAllRanges();
211
- selection.addRange(range);
212
- // Trigger input event to update model
213
- this.onInput();
214
- }
215
- /**
216
- * Handle keydown events
217
- */
218
- onKeyDown(event) {
219
- // Enter alone: Send message (if dropdown not showing)
220
- if (event.key === 'Enter' && !event.shiftKey && !this.showMentionDropdown) {
221
- event.preventDefault();
222
- const plainText = this.getPlainText();
223
- this.enterPressed.emit(plainText);
224
- return;
225
- }
226
- // Backspace: Check if deleting a mention chip
227
- if (event.key === 'Backspace') {
228
- this.handleBackspace(event);
229
- }
230
- // Handle mention dropdown navigation
231
- if (this.showMentionDropdown) {
232
- // Let the dropdown handle arrow keys, enter, escape
233
- // (We'll pass these through to mention-dropdown component)
234
- }
235
- }
236
- /**
237
- * Handle @mention input detection
238
- */
239
- handleMentionInput() {
240
- const selection = window.getSelection();
241
- if (!selection || selection.rangeCount === 0)
242
- return;
243
- const range = selection.getRangeAt(0);
244
- const textBeforeCursor = this.getTextBeforeCursor(range);
245
- // Find the nearest mention trigger before the cursor
246
- // ('@' for agents/users, '#' for entities) — whichever is closest wins
247
- let triggerIndex = -1;
248
- let triggerChar = '@';
249
- for (const t of MentionEditorComponent.MENTION_TRIGGERS) {
250
- const idx = textBeforeCursor.lastIndexOf(t);
251
- if (idx > triggerIndex) {
252
- triggerIndex = idx;
253
- triggerChar = t;
254
- }
255
- }
256
- if (triggerIndex === -1) {
257
- this.closeMentionDropdown();
258
- return;
259
- }
260
- // Check if there's a space between the trigger and cursor (means mention was completed)
261
- const textAfterTrigger = textBeforeCursor.substring(triggerIndex + 1);
262
- if (textAfterTrigger.includes(' ')) {
263
- this.closeMentionDropdown();
264
- return;
265
- }
266
- // Extract query
267
- this.mentionQuery = textAfterTrigger;
268
- this.mentionStartIndex = triggerIndex;
269
- this.activeTrigger = triggerChar;
270
- // Get suggestions for the active trigger
271
- this.mentionSuggestions = this.mentionAutocomplete.getSuggestions(this.mentionQuery, !!this.currentUser, triggerChar);
272
- if (this.mentionSuggestions.length > 0) {
273
- this.showMentionDropdown = true;
274
- this.positionMentionDropdown();
275
- }
276
- else {
277
- this.closeMentionDropdown();
278
- }
279
- }
280
- /**
281
- * Get text before cursor position
282
- */
283
- getTextBeforeCursor(range) {
284
- const tempRange = range.cloneRange();
285
- tempRange.selectNodeContents(this.editorRef.nativeElement);
286
- tempRange.setEnd(range.startContainer, range.startOffset);
287
- return tempRange.toString();
288
- }
289
- /**
290
- * Position the mention dropdown
291
- */
292
- positionMentionDropdown() {
293
- const editor = this.editorRef?.nativeElement;
294
- if (!editor)
295
- return;
296
- // Get the parent container (message-input-box-container) for alignment
297
- const container = editor.closest('.message-input-box-container');
298
- const containerRect = container?.getBoundingClientRect();
299
- const selection = window.getSelection();
300
- if (!selection || selection.rangeCount === 0)
301
- return;
302
- const range = selection.getRangeAt(0);
303
- const cursorRect = range.getBoundingClientRect();
304
- // Check space below vs above
305
- const spaceBelow = window.innerHeight - cursorRect.bottom;
306
- const spaceAbove = cursorRect.top;
307
- const dropdownHeight = Math.min(this.mentionSuggestions.length * 56, 300);
308
- this.mentionDropdownShowAbove = spaceBelow < dropdownHeight && spaceAbove > spaceBelow;
309
- if (this.mentionDropdownShowAbove) {
310
- // Position above, aligning with container top if possible
311
- this.mentionDropdownPosition = {
312
- top: containerRect ? containerRect.top + window.scrollY : cursorRect.top + window.scrollY - 4,
313
- left: cursorRect.left + window.scrollX
314
- };
315
- }
316
- else {
317
- // Position below cursor, but align bottom edge with container top
318
- this.mentionDropdownPosition = {
319
- top: containerRect ? containerRect.top + window.scrollY : cursorRect.bottom + window.scrollY + 4,
320
- left: cursorRect.left + window.scrollX
321
- };
322
- }
323
- }
324
- /**
325
- * Handle mention selection from dropdown
326
- */
327
- onMentionSelected(suggestion) {
328
- this.insertMentionChip(suggestion);
329
- this.closeMentionDropdown();
330
- this.mentionSelected.emit(suggestion);
331
- // Refocus the editor after selection
332
- setTimeout(() => {
333
- this.editorRef?.nativeElement?.focus();
334
- }, 50);
335
- }
336
- /**
337
- * Insert a mention chip at the current cursor position
338
- */
339
- insertMentionChip(suggestion) {
340
- const selection = window.getSelection();
341
- if (!selection || selection.rangeCount === 0)
342
- return;
343
- const range = selection.getRangeAt(0);
344
- // Delete the trigger + query text (use the active trigger char)
345
- const textBeforeCursor = this.getTextBeforeCursor(range);
346
- const lastAtIndex = textBeforeCursor.lastIndexOf(this.activeTrigger);
347
- const deleteLength = textBeforeCursor.length - lastAtIndex;
348
- range.setStart(range.startContainer, range.startOffset - deleteLength);
349
- range.deleteContents();
350
- // Create mention chip element
351
- const chip = this.createMentionChip(suggestion);
352
- // Insert chip
353
- range.insertNode(chip);
354
- // Add space after chip
355
- const space = document.createTextNode(' ');
356
- range.collapse(false);
357
- range.insertNode(space);
358
- // Move cursor after the space
359
- range.setStartAfter(space);
360
- range.collapse(true);
361
- selection.removeAllRanges();
362
- selection.addRange(range);
363
- // Trigger change detection
364
- this.onInput();
365
- }
366
- /**
367
- * Create a mention chip DOM element
368
- */
369
- createMentionChip(suggestion) {
370
- const chip = document.createElement('span');
371
- chip.className = 'mention-chip';
372
- chip.contentEditable = 'false'; // Make chip non-editable
373
- chip.setAttribute('data-mention-id', suggestion.id);
374
- chip.setAttribute('data-mention-type', suggestion.type);
375
- chip.setAttribute('data-mention-name', suggestion.name);
376
- // For agents, get configuration presets (AIEngine.Config() already called during app init)
377
- let presets = [];
378
- if (suggestion.type === 'agent') {
379
- presets = AIEngineBase.Instance.GetAgentConfigurationPresets(suggestion.id, true);
380
- // Store default preset
381
- // IMPORTANT: Store the AIAgentConfiguration.ID (preset ID), not AIConfigurationID
382
- // The backend mapping will convert preset ID -> AIConfigurationID
383
- const defaultPreset = presets.find(p => p.IsDefault) || presets[0];
384
- if (defaultPreset) {
385
- chip.setAttribute('data-preset-id', defaultPreset.ID || '');
386
- chip.setAttribute('data-preset-name', defaultPreset.Name || '');
387
- }
388
- }
389
- // Apply inline styles directly — color by mention type
390
- const palette = suggestion.type === 'user'
391
- ? { bg: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)', border: 'rgba(240, 147, 251, 0.4)' }
392
- : suggestion.type === 'entity'
393
- ? { bg: 'linear-gradient(135deg, #11998e 0%, #38ef7d 100%)', border: 'rgba(17, 153, 142, 0.4)' }
394
- : suggestion.type === 'query'
395
- ? { bg: 'linear-gradient(135deg, #FF6A00 0%, #FF9E2C 100%)', border: 'rgba(255, 106, 0, 0.4)' }
396
- : { bg: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', border: 'rgba(102, 126, 234, 0.4)' };
397
- chip.style.cssText = `
398
- display: inline-flex;
399
- align-items: center;
400
- gap: 5px;
401
- padding: 4px 12px;
402
- margin: 0 3px;
403
- border-radius: 16px;
404
- font-size: 13px;
405
- font-weight: 600;
406
- cursor: default;
407
- user-select: none;
408
- vertical-align: middle;
409
- white-space: nowrap;
410
- pointer-events: all;
411
- background: ${palette.bg};
412
- color: white;
413
- border: 2px solid ${palette.border};
414
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2), 0 1px 2px rgba(0, 0, 0, 0.1);
415
- `;
416
- // Add icon or image
417
- if (suggestion.type === 'agent' && suggestion.imageUrl) {
418
- // Use image if available (LogoURL from agent)
419
- const img = document.createElement('img');
420
- img.src = suggestion.imageUrl;
421
- img.alt = suggestion.displayName;
422
- img.style.cssText = 'width: 16px; height: 16px; border-radius: 50%; object-fit: cover;';
423
- chip.appendChild(img);
424
- }
425
- else if (suggestion.type === 'agent' && suggestion.icon === 'mj-icon-skip') {
426
- // Special handling for mj-icon-skip: use the SVG data URI as an image
427
- const img = document.createElement('img');
428
- img.src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.89918457031249 96.83947368421053'%3E%3Cg transform='translate(-0.1288232421875,-0.0)'%3E%3Cpath d='M93.85,41.56c-.84,0-1.62.2-2.37.55-3-4.35-7.49-8.12-13.04-11.04l.04-7.18v-14.44h-10.24v17.6c-1.52-.43-3.07-.8-4.67-1.11V0h-10.24v24.72s-.09,0-.14,0h-4.38s-.1,0-.14,0V7.3h-10.24v18.62c-1.6.32-3.15.69-4.67,1.11v-11.67h-10.24v6.09l.04,9.6c-5.55,2.92-10.04,6.7-13.04,11.04-.75-.35-1.53-.55-2.37-.55-4.5,0-8.14,5.61-8.14,12.51s3.64,12.53,8.14,12.53c.58,0,1.14-.12,1.67-.29,4.1,6.62,11.54,12.06,20.98,15.28l.79.13v7.05c0,2.97,1.45,5.58,3.87,6.99,1.18.69,2.5,1.04,3.85,1.03,1.4,0,2.83-.37,4.15-1.12l7.54-4.29,7.56,4.3c1.31.74,2.73,1.12,4.13,1.12s2.67-.35,3.85-1.04c2.42-1.41,3.86-4.02,3.86-6.98v-7.05l.79-.13c9.44-3.22,16.89-8.66,20.98-15.28.54.17,1.09.29,1.68.29,4.5,0,8.14-5.61,8.14-12.53s-3.63-12.51-8.14-12.51' fill='%23AAAAAA'/%3E%3Cpath d='M86.69,50.87c0-12.22-13.6-19.1-28.94-20.66-4.48-.47-9.19-.54-13.52,0-15.34,1.53-28.93,8.41-28.93,20.66,0,8.55,5.7,15.55,12.68,15.55h7.94c3.05,2.5,6.93,4.1,11.08,4.71,2.65.4,5.44.46,8.01,0,4.15-.6,8.05-2.2,11.1-4.71h7.92c6.97,0,12.68-7,12.68-15.55' fill='white' opacity='0.9'/%3E%3Cpath d='M57.83,55.82c-1.19,2.58-3.8,4.35-6.84,4.35s-5.65-1.77-6.84-4.35h13.68Z' fill='%23AAAAAA'/%3E%3Cpath d='M32.52,41.14c1.74,0,3.18,2.13,3.18,4.76s-1.44,4.74-3.18,4.74-3.16-2.13-3.16-4.74,1.41-4.76,3.16-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M69.46,41.14c1.74,0,3.16,2.13,3.16,4.76s-1.41,4.74-3.16,4.74-3.18-2.13-3.18-4.74,1.41-4.76,3.18-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M63.91,76.15c-.82-.48-1.84-.43-2.8.12l-10.13,5.75-10.11-5.75c-.96-.55-1.98-.59-2.8-.12-.82.47-1.29,1.38-1.29,2.49v10.12c0,1.11.47,2.02,1.28,2.49.38.22.8.33,1.24.33.51,0,1.05-.15,1.57-.44l10.12-5.75,10.11,5.75c.52.29,1.05.44,1.56.44.44,0,.86-.11,1.24-.33.81-.48,1.28-1.38,1.28-2.49v-10.12c0-1.11-.47-2.02-1.28-2.49' fill='white' opacity='0.9'/%3E%3C/g%3E%3C/svg%3E";
429
- img.alt = suggestion.displayName;
430
- img.style.cssText = 'width: 16px; height: 16px; border-radius: 50%; object-fit: cover;';
431
- chip.appendChild(img);
432
- }
433
- else {
434
- // Use icon for users or agents without images
435
- const icon = document.createElement('i');
436
- icon.style.cssText = 'font-size: 12px; opacity: 0.95;';
437
- if (suggestion.type === 'agent' && suggestion.icon) {
438
- icon.className = this.getIconClasses(suggestion.icon);
439
- }
440
- else if (suggestion.type === 'user') {
441
- icon.className = 'fa-solid fa-user';
442
- }
443
- else if (suggestion.type === 'entity') {
444
- icon.className = this.getIconClasses(suggestion.icon || 'fa-solid fa-table');
445
- }
446
- else if (suggestion.type === 'query') {
447
- icon.className = this.getIconClasses(suggestion.icon || 'fa-solid fa-database');
448
- }
449
- else {
450
- icon.className = 'fa-solid fa-robot';
451
- }
452
- chip.appendChild(icon);
453
- }
454
- // Add space between icon/image and text
455
- const space = document.createTextNode(' ');
456
- chip.appendChild(space);
457
- // Add text
458
- const text = document.createTextNode(suggestion.displayName);
459
- chip.appendChild(text);
460
- // Add dropdown if 2+ presets for agents
461
- if (suggestion.type === 'agent' && presets.length >= 2) {
462
- this.addConfigurationDropdown(chip, presets);
463
- }
464
- return chip;
465
- }
466
- /**
467
- * Add configuration preset dropdown to agent chip
468
- */
469
- addConfigurationDropdown(chip, presets) {
470
- // Store default preset for comparison
471
- const defaultPreset = presets.find(p => p.IsDefault) || presets[0];
472
- // Add preset indicator text (only shown when non-default selected)
473
- const presetIndicator = document.createElement('span');
474
- presetIndicator.className = 'preset-indicator';
475
- presetIndicator.style.cssText = `
476
- display: none;
477
- font-size: 10px;
478
- font-weight: 600;
479
- font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Courier New', monospace;
480
- background: rgba(255, 255, 255, 0.25);
481
- padding: 2px 6px;
482
- border-radius: 4px;
483
- margin-left: 4px;
484
- letter-spacing: 0.3px;
485
- text-transform: uppercase;
486
- border: 1px solid rgba(255, 255, 255, 0.15);
487
- `;
488
- chip.appendChild(presetIndicator);
489
- // Add dropdown chevron button
490
- const chevron = document.createElement('i');
491
- chevron.className = 'fa-solid fa-chevron-down';
492
- chevron.style.cssText = `
493
- font-size: 10px;
494
- opacity: 0.9;
495
- cursor: pointer;
496
- padding: 2px;
497
- `;
498
- chip.appendChild(chevron);
499
- // Create dropdown menu (initially hidden) - append to body for global positioning
500
- const dropdown = document.createElement('div');
501
- dropdown.className = 'preset-dropdown';
502
- dropdown.style.cssText = `
503
- display: none;
504
- position: fixed;
505
- background: white;
506
- border: 1px solid #ddd;
507
- border-radius: 8px;
508
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
509
- min-width: 200px;
510
- max-width: 300px;
511
- z-index: 10000;
512
- overflow: hidden;
513
- `;
514
- // Add preset options to dropdown
515
- presets.forEach(preset => {
516
- const option = document.createElement('div');
517
- option.className = 'preset-option';
518
- option.style.cssText = `
519
- padding: 10px 12px;
520
- cursor: pointer;
521
- display: flex;
522
- align-items: center;
523
- gap: 8px;
524
- transition: background 0.2s;
525
- `;
526
- // Check if this is the selected preset
527
- const currentPresetId = chip.getAttribute('data-preset-id');
528
- const isSelected = UUIDsEqual(preset.ID, currentPresetId);
529
- // Add checkmark for selected option
530
- const checkmark = document.createElement('i');
531
- checkmark.className = 'fa-solid fa-check';
532
- checkmark.style.cssText = `
533
- font-size: 12px;
534
- color: #667eea;
535
- opacity: ${isSelected ? '1' : '0'};
536
- width: 14px;
537
- `;
538
- option.appendChild(checkmark);
539
- // Add preset text content
540
- const textContainer = document.createElement('div');
541
- textContainer.style.cssText = 'flex: 1;';
542
- const displayName = document.createElement('div');
543
- displayName.textContent = preset.DisplayName || preset.Name;
544
- displayName.style.cssText = `
545
- font-weight: 600;
546
- color: #333;
547
- font-size: 13px;
548
- `;
549
- textContainer.appendChild(displayName);
550
- if (preset.Description) {
551
- const description = document.createElement('div');
552
- description.textContent = preset.Description;
553
- description.style.cssText = `
554
- font-size: 11px;
555
- color: #666;
556
- margin-top: 2px;
557
- `;
558
- textContainer.appendChild(description);
559
- }
560
- option.appendChild(textContainer);
561
- // Hover effects
562
- option.addEventListener('mouseenter', () => {
563
- option.style.background = '#f5f5f5';
564
- });
565
- option.addEventListener('mouseleave', () => {
566
- option.style.background = 'white';
567
- });
568
- // Click handler to select preset
569
- option.addEventListener('click', (e) => {
570
- e.stopPropagation();
571
- // Update chip data attributes
572
- // IMPORTANT: Store preset.ID (AIAgentConfiguration.ID), not AIConfigurationID
573
- chip.setAttribute('data-preset-id', preset.ID || '');
574
- chip.setAttribute('data-preset-name', preset.Name || '');
575
- // Update preset indicator visibility and text
576
- const isDefault = UUIDsEqual(preset.ID, defaultPreset.ID);
577
- if (isDefault) {
578
- presetIndicator.style.display = 'none';
579
- }
580
- else {
581
- presetIndicator.style.display = 'inline';
582
- presetIndicator.textContent = preset.DisplayName || preset.Name;
583
- }
584
- // Update checkmarks
585
- dropdown.querySelectorAll('.preset-option').forEach((opt, idx) => {
586
- const check = opt.querySelector('i.fa-check');
587
- if (check) {
588
- check.style.opacity = idx === presets.indexOf(preset) ? '1' : '0';
589
- }
590
- });
591
- // Close dropdown
592
- dropdown.style.display = 'none';
593
- });
594
- dropdown.appendChild(option);
595
- });
596
- // Append dropdown to document body for global positioning
597
- document.body.appendChild(dropdown);
598
- // Helper function to position dropdown relative to chip
599
- const positionDropdown = () => {
600
- const chipRect = chip.getBoundingClientRect();
601
- const viewportHeight = window.innerHeight;
602
- const spaceBelow = viewportHeight - chipRect.bottom;
603
- // Set left position (same for both above/below)
604
- dropdown.style.left = `${chipRect.left}px`;
605
- // First, show dropdown to measure its actual height
606
- const wasHidden = dropdown.style.display === 'none';
607
- if (wasHidden) {
608
- dropdown.style.visibility = 'hidden';
609
- dropdown.style.display = 'block';
610
- }
611
- const dropdownHeight = dropdown.offsetHeight;
612
- const spaceAbove = chipRect.top;
613
- // Position dropdown above chip if not enough space below
614
- if (spaceBelow < dropdownHeight && spaceAbove > spaceBelow) {
615
- // Show above - position so bottom of dropdown is 4px above top of chip
616
- dropdown.style.top = `${chipRect.top - dropdownHeight - 4}px`;
617
- }
618
- else {
619
- // Show below (default) - position 4px below bottom of chip
620
- dropdown.style.top = `${chipRect.bottom + 4}px`;
621
- }
622
- // Restore visibility
623
- if (wasHidden) {
624
- dropdown.style.visibility = 'visible';
625
- }
626
- };
627
- // Toggle dropdown on chevron click
628
- chevron.addEventListener('click', (e) => {
629
- e.stopPropagation();
630
- const isVisible = dropdown.style.display === 'block';
631
- if (isVisible) {
632
- dropdown.style.display = 'none';
633
- }
634
- else {
635
- positionDropdown();
636
- dropdown.style.display = 'block';
637
- }
638
- });
639
- // Close dropdown when clicking outside
640
- const closeDropdown = (e) => {
641
- if (!dropdown.contains(e.target) && !chip.contains(e.target)) {
642
- dropdown.style.display = 'none';
643
- }
644
- };
645
- document.addEventListener('click', closeDropdown);
646
- // Cleanup: remove dropdown from body and event listeners when chip is removed
647
- const observer = new MutationObserver((mutations) => {
648
- mutations.forEach((mutation) => {
649
- mutation.removedNodes.forEach((node) => {
650
- if (node === chip) {
651
- document.removeEventListener('click', closeDropdown);
652
- if (dropdown.parentNode) {
653
- dropdown.parentNode.removeChild(dropdown);
654
- }
655
- observer.disconnect();
656
- }
657
- });
658
- });
659
- });
660
- if (chip.parentNode) {
661
- observer.observe(chip.parentNode, { childList: true });
662
- }
663
- }
664
- /**
665
- * Get icon classes with proper FA prefix
666
- */
667
- getIconClasses(iconClass) {
668
- if (!iconClass)
669
- return 'fa-solid fa-robot';
670
- if (iconClass.includes('fa-')) {
671
- if (iconClass.match(/\b(fa-solid|fa-regular|fa-light|fa-brands)\b/)) {
672
- return iconClass;
673
- }
674
- return `fa-solid ${iconClass}`;
675
- }
676
- return iconClass;
677
- }
678
- /**
679
- * Handle backspace key - delete entire chip if cursor is right after one
680
- */
681
- handleBackspace(event) {
682
- const selection = window.getSelection();
683
- if (!selection || selection.rangeCount === 0)
684
- return;
685
- const range = selection.getRangeAt(0);
686
- // Check if cursor is right after a mention chip
687
- if (range.collapsed && range.startOffset > 0) {
688
- const prevNode = range.startContainer.childNodes[range.startOffset - 1];
689
- if (prevNode && prevNode.classList?.contains('mention-chip')) {
690
- event.preventDefault();
691
- prevNode.remove();
692
- this.onInput();
693
- }
694
- }
695
- }
696
- /**
697
- * Close mention dropdown
698
- */
699
- closeMentionDropdown() {
700
- this.showMentionDropdown = false;
701
- this.mentionSuggestions = [];
702
- this.mentionStartIndex = -1;
703
- this.mentionQuery = '';
704
- this.activeTrigger = '@';
705
- }
706
- /**
707
- * Convert editor HTML to plain text with @mentions
708
- */
709
- getPlainText() {
710
- const editor = this.editorRef?.nativeElement;
711
- if (!editor)
712
- return '';
713
- let text = '';
714
- const nodes = editor.childNodes;
715
- for (let i = 0; i < nodes.length; i++) {
716
- const node = nodes[i];
717
- if (node.nodeType === Node.TEXT_NODE) {
718
- text += node.textContent || '';
719
- }
720
- else if (node.nodeType === Node.ELEMENT_NODE) {
721
- const element = node;
722
- if (element.classList.contains('mention-chip')) {
723
- const name = element.getAttribute('data-mention-name') || '';
724
- const mentionType = element.getAttribute('data-mention-type');
725
- const prefix = mentionType === 'entity' || mentionType === 'query' ? '#' : '@';
726
- // Use quoted format if name has spaces
727
- text += name.includes(' ') ? `${prefix}"${name}"` : `${prefix}${name}`;
728
- }
729
- else if (element.tagName === 'BR') {
730
- text += '\n';
731
- }
732
- else if (element.tagName === 'DIV') {
733
- // Handle line breaks from contentEditable
734
- if (i > 0)
735
- text += '\n';
736
- text += this.getNodeText(element);
737
- }
738
- else {
739
- text += element.textContent || '';
740
- }
741
- }
742
- }
743
- return text;
744
- }
745
- /**
746
- * Get text from a node recursively
747
- */
748
- getNodeText(node) {
749
- let text = '';
750
- const children = node.childNodes;
751
- for (let i = 0; i < children.length; i++) {
752
- const child = children[i];
753
- if (child.nodeType === Node.TEXT_NODE) {
754
- text += child.textContent || '';
755
- }
756
- else if (child.nodeType === Node.ELEMENT_NODE) {
757
- const element = child;
758
- if (element.classList.contains('mention-chip')) {
759
- const name = element.getAttribute('data-mention-name') || '';
760
- const mentionType = element.getAttribute('data-mention-type');
761
- const prefix = mentionType === 'entity' || mentionType === 'query' ? '#' : '@';
762
- text += name.includes(' ') ? `${prefix}"${name}"` : `${prefix}${name}`;
763
- }
764
- else {
765
- text += this.getNodeText(element);
766
- }
767
- }
768
- }
769
- return text;
770
- }
771
- /**
772
- * Set editor content from plain text (for programmatic updates)
773
- */
774
- setEditorContent(text) {
775
- const editor = this.editorRef?.nativeElement;
776
- if (!editor)
777
- return;
778
- // For now, just set as plain text
779
- // TODO: Parse @mentions and render as chips
780
- editor.textContent = text;
781
- }
782
- // ControlValueAccessor implementation
783
- writeValue(value) {
784
- if (value) {
785
- this.setEditorContent(value);
786
- }
787
- else if (this.editorRef?.nativeElement) {
788
- this.editorRef.nativeElement.textContent = '';
789
- }
790
- }
791
- registerOnChange(fn) {
792
- this.onChange = fn;
793
- }
794
- registerOnTouched(fn) {
795
- this.onTouched = fn;
796
- }
797
- setDisabledState(isDisabled) {
798
- this.disabled = isDisabled;
799
- if (this.editorRef?.nativeElement) {
800
- this.editorRef.nativeElement.contentEditable = (!isDisabled).toString();
801
- }
802
- }
803
- /**
804
- * Focus the editor
805
- */
806
- focus() {
807
- this.editorRef?.nativeElement?.focus();
808
- }
809
- /**
810
- * Clear the editor content and pending attachments
811
- */
812
- clear() {
813
- if (this.editorRef?.nativeElement) {
814
- this.editorRef.nativeElement.textContent = '';
815
- this.onInput();
816
- }
817
- this.clearPendingAttachments();
818
- }
819
- /**
820
- * Extract mention chips with their configuration data
821
- * Returns array of objects containing mention info and preset configuration
822
- */
823
- getMentionChipsData() {
824
- const editor = this.editorRef?.nativeElement;
825
- if (!editor)
826
- return [];
827
- const chips = [];
828
- const mentionElements = editor.querySelectorAll('.mention-chip');
829
- mentionElements.forEach(chip => {
830
- const element = chip;
831
- const id = element.getAttribute('data-mention-id') || '';
832
- const type = element.getAttribute('data-mention-type') || '';
833
- const name = element.getAttribute('data-mention-name') || '';
834
- const presetId = element.getAttribute('data-preset-id') || undefined;
835
- const presetName = element.getAttribute('data-preset-name') || undefined;
836
- chips.push({
837
- id,
838
- type,
839
- name,
840
- ...(presetId ? { presetId } : {}),
841
- ...(presetName ? { presetName } : {})
842
- });
843
- });
844
- return chips;
845
- }
846
- /**
847
- * Get the plain text value with mentions encoded as JSON
848
- * This format preserves configuration information when messages are saved
849
- * Format: @{type:"agent",id:"uuid",name:"Agent Name",configId:"uuid",config:"High"}
850
- */
851
- getPlainTextWithJsonMentions() {
852
- const editor = this.editorRef?.nativeElement;
853
- if (!editor)
854
- return '';
855
- let plainText = '';
856
- const childNodes = Array.from(editor.childNodes);
857
- for (const node of childNodes) {
858
- if (node.nodeType === Node.TEXT_NODE) {
859
- // Regular text node
860
- plainText += node.textContent || '';
861
- }
862
- else if (node.nodeType === Node.ELEMENT_NODE) {
863
- const element = node;
864
- if (element.classList.contains('mention-chip')) {
865
- // Extract mention data attributes
866
- const type = element.getAttribute('data-mention-type') || '';
867
- const id = element.getAttribute('data-mention-id') || '';
868
- const name = element.getAttribute('data-mention-name') || '';
869
- const presetId = element.getAttribute('data-preset-id');
870
- const presetName = element.getAttribute('data-preset-name');
871
- // Build JSON mention object (compact format - no spaces)
872
- const mentionObj = {
873
- type,
874
- id,
875
- name
876
- };
877
- // Add configuration fields if present (for agents with non-default presets)
878
- if (presetId) {
879
- mentionObj.configId = presetId;
880
- }
881
- if (presetName) {
882
- mentionObj.config = presetName;
883
- }
884
- // Encode as JSON mention
885
- // Don't remove spaces from the JSON string - spaces in values (like agent names) need to be preserved
886
- plainText += `@${JSON.stringify(mentionObj)}`;
887
- }
888
- else {
889
- // Other HTML element (e.g., <br>)
890
- if (element.tagName === 'BR') {
891
- plainText += '\n';
892
- }
893
- else {
894
- plainText += element.textContent || '';
895
- }
896
- }
897
- }
898
- }
899
- return plainText;
900
- }
901
- // ==================== Attachment Handling Methods ====================
902
- /**
903
- * Handle drag over event
904
- */
905
- onDragOver(event) {
906
- if (!this.enableAttachments)
907
- return;
908
- event.preventDefault();
909
- event.stopPropagation();
910
- this.isDragOver = true;
911
- }
912
- /**
913
- * Handle drag leave event
914
- */
915
- onDragLeave(event) {
916
- event.preventDefault();
917
- event.stopPropagation();
918
- this.isDragOver = false;
919
- }
920
- /**
921
- * Handle drop event
922
- */
923
- onDrop(event) {
924
- if (!this.enableAttachments)
925
- return;
926
- event.preventDefault();
927
- event.stopPropagation();
928
- this.isDragOver = false;
929
- if (event.dataTransfer?.files) {
930
- const files = Array.from(event.dataTransfer.files);
931
- for (const file of files) {
932
- if (this.isAcceptedFile(file)) {
933
- this.processFile(file);
934
- }
935
- }
936
- }
937
- }
938
- /**
939
- * Handle file input change (from file picker)
940
- */
941
- onFileSelected(event) {
942
- const input = event.target;
943
- if (input.files) {
944
- const files = Array.from(input.files);
945
- for (const file of files) {
946
- this.processFile(file);
947
- }
948
- // Reset input so same file can be selected again
949
- input.value = '';
950
- }
951
- }
952
- /**
953
- * Process a file for attachment
954
- */
955
- async processFile(file) {
956
- // Validate file
957
- const validation = this.validateFile(file);
958
- if (!validation.valid) {
959
- this.attachmentError.emit(validation.error);
960
- return;
961
- }
962
- // Read file as data URL
963
- const dataUrl = await this.readFileAsDataUrl(file);
964
- if (!dataUrl) {
965
- this.attachmentError.emit('Failed to read file');
966
- return;
967
- }
968
- // Get image dimensions if applicable
969
- let width;
970
- let height;
971
- if (file.type.startsWith('image/')) {
972
- const dimensions = await this.getImageDimensions(dataUrl);
973
- width = dimensions.width;
974
- height = dimensions.height;
975
- }
976
- // Create pending attachment
977
- const attachment = {
978
- id: this.generateAttachmentId(),
979
- file,
980
- dataUrl,
981
- mimeType: file.type,
982
- fileName: file.name,
983
- sizeBytes: file.size,
984
- width,
985
- height,
986
- thumbnailUrl: file.type.startsWith('image/') ? dataUrl : undefined
987
- };
988
- // Add to pending attachments
989
- this.pendingAttachments.push(attachment);
990
- this.attachmentsChanged.emit([...this.pendingAttachments]);
991
- this.cdr.detectChanges();
992
- }
993
- /**
994
- * Validate a file against settings
995
- */
996
- validateFile(file) {
997
- // Check count limit
998
- if (this.pendingAttachments.length >= this.maxAttachments) {
999
- return {
1000
- valid: false,
1001
- error: `Maximum ${this.maxAttachments} attachments allowed`
1002
- };
1003
- }
1004
- // Check size limit
1005
- if (file.size > this.maxAttachmentSizeBytes) {
1006
- const maxMB = (this.maxAttachmentSizeBytes / (1024 * 1024)).toFixed(1);
1007
- const fileMB = (file.size / (1024 * 1024)).toFixed(1);
1008
- return {
1009
- valid: false,
1010
- error: `File size (${fileMB}MB) exceeds maximum (${maxMB}MB)`
1011
- };
1012
- }
1013
- // Check file type
1014
- if (!this.isAcceptedFile(file)) {
1015
- return {
1016
- valid: false,
1017
- error: `File type ${file.type || 'unknown'} not accepted`
1018
- };
1019
- }
1020
- return { valid: true };
1021
- }
1022
- /**
1023
- * Check if file type is accepted
1024
- */
1025
- isAcceptedFile(file) {
1026
- if (this.acceptedFileTypes === '*' || this.acceptedFileTypes === '*/*') {
1027
- return true;
1028
- }
1029
- const acceptedTypes = this.acceptedFileTypes.split(',').map(t => t.trim());
1030
- for (const accepted of acceptedTypes) {
1031
- // Handle universal wildcard */* anywhere in the list
1032
- if (accepted === '*/*') {
1033
- return true;
1034
- }
1035
- // Handle wildcard MIME types like "image/*"
1036
- if (accepted.endsWith('/*')) {
1037
- const category = accepted.slice(0, -2);
1038
- if (file.type.startsWith(category + '/')) {
1039
- return true;
1040
- }
1041
- }
1042
- else if (accepted.startsWith('.')) {
1043
- // Handle file extensions like ".png"
1044
- if (file.name.toLowerCase().endsWith(accepted.toLowerCase())) {
1045
- return true;
1046
- }
1047
- }
1048
- else if (file.type === accepted) {
1049
- // Exact MIME type match
1050
- return true;
1051
- }
1052
- }
1053
- return false;
1054
- }
1055
- /**
1056
- * Read file as data URL
1057
- */
1058
- readFileAsDataUrl(file) {
1059
- return new Promise((resolve) => {
1060
- const reader = new FileReader();
1061
- reader.onload = () => resolve(reader.result);
1062
- reader.onerror = () => resolve(null);
1063
- reader.readAsDataURL(file);
1064
- });
1065
- }
1066
- /**
1067
- * Get image dimensions
1068
- */
1069
- getImageDimensions(dataUrl) {
1070
- return new Promise((resolve) => {
1071
- const img = new Image();
1072
- img.onload = () => {
1073
- resolve({ width: img.naturalWidth, height: img.naturalHeight });
1074
- };
1075
- img.onerror = () => {
1076
- resolve({ width: 0, height: 0 });
1077
- };
1078
- img.src = dataUrl;
1079
- });
1080
- }
1081
- /**
1082
- * Generate unique attachment ID
1083
- */
1084
- generateAttachmentId() {
1085
- return `att_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1086
- }
1087
- /**
1088
- * Remove a pending attachment by ID
1089
- */
1090
- removeAttachment(id) {
1091
- const index = this.pendingAttachments.findIndex(a => a.id === id);
1092
- if (index !== -1) {
1093
- this.pendingAttachments.splice(index, 1);
1094
- this.attachmentsChanged.emit([...this.pendingAttachments]);
1095
- this.cdr.detectChanges();
1096
- }
1097
- }
1098
- /**
1099
- * Get all pending attachments
1100
- */
1101
- getPendingAttachments() {
1102
- return [...this.pendingAttachments];
1103
- }
1104
- /**
1105
- * Add an artifact as a pending attachment programmatically.
1106
- * Used by the artifact picker to attach artifacts as conversation inputs.
1107
- */
1108
- AddArtifactAttachment(artifact) {
1109
- const attachment = {
1110
- id: crypto.randomUUID(),
1111
- file: null,
1112
- dataUrl: '',
1113
- mimeType: artifact.mimeType,
1114
- fileName: artifact.fileName,
1115
- sizeBytes: artifact.sizeBytes,
1116
- fileID: artifact.fileID,
1117
- source: 'artifact',
1118
- artifactVersionId: artifact.artifactVersionId
1119
- };
1120
- this.pendingAttachments.push(attachment);
1121
- this.attachmentsChanged.emit([...this.pendingAttachments]);
1122
- return attachment;
1123
- }
1124
- /**
1125
- * Clear all pending attachments
1126
- */
1127
- clearPendingAttachments() {
1128
- this.pendingAttachments = [];
1129
- this.attachmentsChanged.emit([]);
1130
- this.cdr.detectChanges();
1131
- }
1132
- /**
1133
- * Handle click on an attachment thumbnail
1134
- */
1135
- onAttachmentClick(attachment) {
1136
- this.attachmentClicked.emit(attachment);
1137
- }
1138
- /**
1139
- * Check if there are any pending attachments
1140
- */
1141
- hasAttachments() {
1142
- return this.pendingAttachments.length > 0;
1143
- }
1144
- /**
1145
- * Trigger file picker programmatically
1146
- */
1147
- openFilePicker() {
1148
- const input = document.createElement('input');
1149
- input.type = 'file';
1150
- // If */* is in the list, accept all files (some browsers don't handle */* correctly)
1151
- input.accept = this.acceptedFileTypes.includes('*/*') ? '' : this.acceptedFileTypes;
1152
- input.multiple = true;
1153
- input.onchange = (e) => this.onFileSelected(e);
1154
- input.click();
1155
- }
1156
- static ɵfac = function MentionEditorComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MentionEditorComponent)(i0.ɵɵdirectiveInject(i1.MentionAutocompleteService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
1157
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MentionEditorComponent, selectors: [["mj-mention-editor"]], viewQuery: function MentionEditorComponent_Query(rf, ctx) { if (rf & 1) {
1158
- i0.ɵɵviewQuery(_c0, 5);
1159
- } if (rf & 2) {
1160
- let _t;
1161
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.editorRef = _t.first);
1162
- } }, inputs: { placeholder: "placeholder", disabled: "disabled", currentUser: "currentUser", enableMentions: "enableMentions", enableAttachments: "enableAttachments", maxAttachments: "maxAttachments", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", acceptedFileTypes: "acceptedFileTypes" }, outputs: { valueChange: "valueChange", mentionSelected: "mentionSelected", enterPressed: "enterPressed", attachmentsChanged: "attachmentsChanged", attachmentError: "attachmentError", attachmentClicked: "attachmentClicked" }, standalone: false, features: [i0.ɵɵProvidersFeature([
1163
- {
1164
- provide: NG_VALUE_ACCESSOR,
1165
- useExisting: forwardRef(() => MentionEditorComponent),
1166
- multi: true
1167
- }
1168
- ])], decls: 6, vars: 7, consts: [["editor", ""], [1, "mention-editor-container", 3, "click", "dragover", "dragleave", "drop"], [1, "pending-attachments"], ["contenteditable", "true", 1, "mention-editor", 3, "input", "keydown", "blur", "paste"], [1, "drop-overlay"], [3, "suggestions", "position", "showAbove", "useFixedPositioning", "visible"], [1, "attachment-thumbnail"], [1, "attachment-thumbnail", 3, "click"], [1, "thumbnail-image", 3, "src", "alt"], [1, "thumbnail-placeholder"], ["title", "Remove attachment", 1, "remove-attachment", 3, "click"], [1, "fa-solid", "fa-times"], [1, "fa-solid", "fa-file"], [1, "file-name"], [1, "drop-message"], [1, "fa-solid", "fa-cloud-arrow-up"], [3, "suggestionSelected", "closed", "suggestions", "position", "showAbove", "useFixedPositioning", "visible"]], template: function MentionEditorComponent_Template(rf, ctx) { if (rf & 1) {
1169
- const _r1 = i0.ɵɵgetCurrentView();
1170
- i0.ɵɵelementStart(0, "div", 1);
1171
- i0.ɵɵlistener("click", function MentionEditorComponent_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onContainerClick($event)); })("dragover", function MentionEditorComponent_Template_div_dragover_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onDragOver($event)); })("dragleave", function MentionEditorComponent_Template_div_dragleave_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onDragLeave($event)); })("drop", function MentionEditorComponent_Template_div_drop_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onDrop($event)); });
1172
- i0.ɵɵconditionalCreate(1, MentionEditorComponent_Conditional_1_Template, 3, 0, "div", 2);
1173
- i0.ɵɵelementStart(2, "div", 3, 0);
1174
- i0.ɵɵlistener("input", function MentionEditorComponent_Template_div_input_2_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onInput()); })("keydown", function MentionEditorComponent_Template_div_keydown_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onKeyDown($event)); })("blur", function MentionEditorComponent_Template_div_blur_2_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onBlur()); })("paste", function MentionEditorComponent_Template_div_paste_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onPaste($event)); });
1175
- i0.ɵɵelementEnd();
1176
- i0.ɵɵconditionalCreate(4, MentionEditorComponent_Conditional_4_Template, 5, 0, "div", 4);
1177
- i0.ɵɵconditionalCreate(5, MentionEditorComponent_Conditional_5_Template, 1, 5, "mj-mention-dropdown", 5);
1178
- i0.ɵɵelementEnd();
1179
- } if (rf & 2) {
1180
- i0.ɵɵclassProp("drag-over", ctx.isDragOver);
1181
- i0.ɵɵadvance();
1182
- i0.ɵɵconditional(ctx.pendingAttachments.length > 0 ? 1 : -1);
1183
- i0.ɵɵadvance();
1184
- i0.ɵɵattribute("contenteditable", !ctx.disabled)("data-placeholder", ctx.placeholder);
1185
- i0.ɵɵadvance(2);
1186
- i0.ɵɵconditional(ctx.isDragOver ? 4 : -1);
1187
- i0.ɵɵadvance();
1188
- i0.ɵɵconditional(ctx.showMentionDropdown && ctx.enableMentions ? 5 : -1);
1189
- } }, dependencies: [i2.MentionDropdownComponent], styles: [".mention-editor-container[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n display: block;\n}\n\n.mention-editor-container.drag-over[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--mj-brand-primary);\n}\n\n.mention-editor[_ngcontent-%COMP%] {\n display: block;\n width: 100%;\n min-height: 100px;\n max-height: 300px;\n padding: 7px 3.5rem 7px 12px;\n outline: none;\n border: none;\n background: transparent;\n font-family: inherit;\n font-size: 1rem;\n line-height: 1.5;\n overflow-y: auto;\n overflow-x: hidden;\n word-wrap: break-word;\n white-space: pre-wrap;\n cursor: text;\n user-select: text;\n box-sizing: border-box;\n}\n.mention-editor[_ngcontent-%COMP%]:empty:before {\n content: attr(data-placeholder);\n color: var(--mj-text-muted);\n pointer-events: none;\n position: absolute;\n}\n.mention-editor[_ngcontent-%COMP%]:focus {\n outline: none;\n}\n.mention-editor[contenteditable=false][_ngcontent-%COMP%] {\n cursor: not-allowed;\n opacity: 0.6;\n background: var(--mj-bg-surface-sunken);\n}\n@media (max-width: 768px) {\n .mention-editor[_ngcontent-%COMP%] {\n font-size: 16px;\n padding: 5px;\n padding-right: 3rem;\n }\n}\n\n .mention-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 12px;\n margin: 0 3px;\n border-radius: 16px;\n font-size: 13px;\n font-weight: 600;\n cursor: default;\n user-select: none;\n vertical-align: middle;\n white-space: nowrap;\n pointer-events: all;\n -webkit-user-modify: read-only;\n -moz-user-modify: read-only;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n box-shadow: var(--mj-shadow-md);\n animation: _ngcontent-%COMP%_chipInsert 0.15s ease-out;\n}\n .mention-chip i {\n font-size: 12px;\n opacity: 0.95;\n}\n .mention-chip[data-mention-type=user] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n .mention-chip:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-lg);\n transition: all 0.2s ease;\n}\n .mention-chip:focus, .mention-chip.selected {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n@keyframes _ngcontent-%COMP%_chipInsert {\n 0% {\n transform: scale(0.8);\n opacity: 0;\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.mention-editor[_ngcontent-%COMP%] .mention-chip[_ngcontent-%COMP%] + .mention-chip[_ngcontent-%COMP%] {\n margin-left: 4px;\n}\n.mention-editor[_ngcontent-%COMP%] br[_ngcontent-%COMP%] {\n display: block;\n content: \"\";\n margin: 0;\n}\n\n.mention-editor[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 6px;\n}\n.mention-editor[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: transparent;\n}\n.mention-editor[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: color-mix(in srgb, var(--mj-text-primary) 20%, transparent);\n border-radius: 3px;\n}\n.mention-editor[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n}\n\n\n\n\n.pending-attachments[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n background: color-mix(in srgb, var(--mj-text-primary) 2%, transparent);\n}\n\n.attachment-thumbnail[_ngcontent-%COMP%] {\n position: relative;\n width: 80px;\n height: 80px;\n border-radius: 8px;\n overflow: hidden;\n cursor: pointer;\n transition: transform 0.2s, box-shadow 0.2s;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n\n.attachment-thumbnail[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.thumbnail-image[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.thumbnail-placeholder[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 8px;\n color: var(--mj-text-secondary);\n}\n\n.thumbnail-placeholder[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n margin-bottom: 4px;\n color: var(--mj-text-muted);\n}\n\n.thumbnail-placeholder[_ngcontent-%COMP%] .file-name[_ngcontent-%COMP%] {\n font-size: 10px;\n text-align: center;\n word-break: break-all;\n line-height: 1.2;\n max-height: 36px;\n overflow: hidden;\n}\n\n.remove-attachment[_ngcontent-%COMP%] {\n position: absolute;\n top: 4px;\n right: 4px;\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-text-primary) 60%, transparent);\n color: var(--mj-text-inverse);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.2s, background 0.2s;\n}\n\n.attachment-thumbnail[_ngcontent-%COMP%]:hover .remove-attachment[_ngcontent-%COMP%] {\n opacity: 1;\n}\n\n.remove-attachment[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 90%, transparent);\n}\n\n.remove-attachment[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.drop-overlay[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n backdrop-filter: blur(2px);\n border: 2px dashed var(--mj-brand-primary);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n pointer-events: none;\n}\n\n.drop-message[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.drop-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n}\n\n.drop-message[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 14px;\n}"] });
1190
- }
1191
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MentionEditorComponent, [{
1192
- type: Component,
1193
- args: [{ standalone: false, selector: 'mj-mention-editor', providers: [
1194
- {
1195
- provide: NG_VALUE_ACCESSOR,
1196
- useExisting: forwardRef(() => MentionEditorComponent),
1197
- multi: true
1198
- }
1199
- ], template: "<div class=\"mention-editor-container\"\n [class.drag-over]=\"isDragOver\"\n (click)=\"onContainerClick($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n\n <!-- Pending Attachments Preview -->\n @if (pendingAttachments.length > 0) {\n <div class=\"pending-attachments\">\n @for (attachment of pendingAttachments; track attachment) {\n <div class=\"attachment-thumbnail\"\n (click)=\"onAttachmentClick(attachment)\">\n @if (attachment.thumbnailUrl) {\n <img\n [src]=\"attachment.thumbnailUrl\"\n [alt]=\"attachment.fileName\"\n class=\"thumbnail-image\">\n }\n @if (!attachment.thumbnailUrl) {\n <div class=\"thumbnail-placeholder\">\n <i class=\"fa-solid fa-file\"></i>\n <span class=\"file-name\">{{ attachment.fileName }}</span>\n </div>\n }\n <button class=\"remove-attachment\"\n (click)=\"removeAttachment(attachment.id); $event.stopPropagation()\"\n title=\"Remove attachment\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n }\n </div>\n }\n\n <div\n #editor\n class=\"mention-editor\"\n contenteditable=\"true\"\n [attr.contenteditable]=\"!disabled\"\n [attr.data-placeholder]=\"placeholder\"\n (input)=\"onInput()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n (paste)=\"onPaste($event)\"\n ></div>\n\n <!-- Drag & Drop Overlay -->\n @if (isDragOver) {\n <div class=\"drop-overlay\">\n <div class=\"drop-message\">\n <i class=\"fa-solid fa-cloud-arrow-up\"></i>\n <span>Drop files here</span>\n </div>\n </div>\n }\n\n <!-- Mention Dropdown -->\n @if (showMentionDropdown && enableMentions) {\n <mj-mention-dropdown\n [suggestions]=\"mentionSuggestions\"\n [position]=\"mentionDropdownPosition\"\n [showAbove]=\"mentionDropdownShowAbove\"\n [useFixedPositioning]=\"true\"\n [visible]=\"true\"\n (suggestionSelected)=\"onMentionSelected($event)\"\n (closed)=\"closeMentionDropdown()\">\n </mj-mention-dropdown>\n }\n</div>\n", styles: [".mention-editor-container {\n position: relative;\n width: 100%;\n display: block;\n}\n\n.mention-editor-container.drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, transparent);\n border-color: var(--mj-brand-primary);\n}\n\n.mention-editor {\n display: block;\n width: 100%;\n min-height: 100px;\n max-height: 300px;\n padding: 7px 3.5rem 7px 12px;\n outline: none;\n border: none;\n background: transparent;\n font-family: inherit;\n font-size: 1rem;\n line-height: 1.5;\n overflow-y: auto;\n overflow-x: hidden;\n word-wrap: break-word;\n white-space: pre-wrap;\n cursor: text;\n user-select: text;\n box-sizing: border-box;\n}\n.mention-editor:empty:before {\n content: attr(data-placeholder);\n color: var(--mj-text-muted);\n pointer-events: none;\n position: absolute;\n}\n.mention-editor:focus {\n outline: none;\n}\n.mention-editor[contenteditable=false] {\n cursor: not-allowed;\n opacity: 0.6;\n background: var(--mj-bg-surface-sunken);\n}\n@media (max-width: 768px) {\n .mention-editor {\n font-size: 16px;\n padding: 5px;\n padding-right: 3rem;\n }\n}\n\n::ng-deep .mention-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 12px;\n margin: 0 3px;\n border-radius: 16px;\n font-size: 13px;\n font-weight: 600;\n cursor: default;\n user-select: none;\n vertical-align: middle;\n white-space: nowrap;\n pointer-events: all;\n -webkit-user-modify: read-only;\n -moz-user-modify: read-only;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n box-shadow: var(--mj-shadow-md);\n animation: chipInsert 0.15s ease-out;\n}\n::ng-deep .mention-chip i {\n font-size: 12px;\n opacity: 0.95;\n}\n::ng-deep .mention-chip[data-mention-type=user] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n::ng-deep .mention-chip:hover {\n transform: translateY(-1px);\n box-shadow: var(--mj-shadow-lg);\n transition: all 0.2s ease;\n}\n::ng-deep .mention-chip:focus, ::ng-deep .mention-chip.selected {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n@keyframes chipInsert {\n 0% {\n transform: scale(0.8);\n opacity: 0;\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.mention-editor .mention-chip + .mention-chip {\n margin-left: 4px;\n}\n.mention-editor br {\n display: block;\n content: \"\";\n margin: 0;\n}\n\n.mention-editor::-webkit-scrollbar {\n width: 6px;\n}\n.mention-editor::-webkit-scrollbar-track {\n background: transparent;\n}\n.mention-editor::-webkit-scrollbar-thumb {\n background: color-mix(in srgb, var(--mj-text-primary) 20%, transparent);\n border-radius: 3px;\n}\n.mention-editor::-webkit-scrollbar-thumb:hover {\n background: color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n}\n\n/* ==================== Attachment Styles ==================== */\n\n.pending-attachments {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n background: color-mix(in srgb, var(--mj-text-primary) 2%, transparent);\n}\n\n.attachment-thumbnail {\n position: relative;\n width: 80px;\n height: 80px;\n border-radius: 8px;\n overflow: hidden;\n cursor: pointer;\n transition: transform 0.2s, box-shadow 0.2s;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n\n.attachment-thumbnail:hover {\n transform: scale(1.05);\n box-shadow: var(--mj-shadow-lg);\n}\n\n.thumbnail-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.thumbnail-placeholder {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 8px;\n color: var(--mj-text-secondary);\n}\n\n.thumbnail-placeholder i {\n font-size: 24px;\n margin-bottom: 4px;\n color: var(--mj-text-muted);\n}\n\n.thumbnail-placeholder .file-name {\n font-size: 10px;\n text-align: center;\n word-break: break-all;\n line-height: 1.2;\n max-height: 36px;\n overflow: hidden;\n}\n\n.remove-attachment {\n position: absolute;\n top: 4px;\n right: 4px;\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-text-primary) 60%, transparent);\n color: var(--mj-text-inverse);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.2s, background 0.2s;\n}\n\n.attachment-thumbnail:hover .remove-attachment {\n opacity: 1;\n}\n\n.remove-attachment:hover {\n background: color-mix(in srgb, var(--mj-status-error) 90%, transparent);\n}\n\n.remove-attachment i {\n font-size: 10px;\n}\n\n/* Drop Overlay */\n.drop-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n backdrop-filter: blur(2px);\n border: 2px dashed var(--mj-brand-primary);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n pointer-events: none;\n}\n\n.drop-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.drop-message i {\n font-size: 32px;\n}\n\n.drop-message span {\n font-size: 14px;\n}\n"] }]
1200
- }], () => [{ type: i1.MentionAutocompleteService }, { type: i0.ChangeDetectorRef }], { editorRef: [{
1201
- type: ViewChild,
1202
- args: ['editor', { static: false }]
1203
- }], placeholder: [{
1204
- type: Input
1205
- }], disabled: [{
1206
- type: Input
1207
- }], currentUser: [{
1208
- type: Input
1209
- }], enableMentions: [{
1210
- type: Input
1211
- }], enableAttachments: [{
1212
- type: Input
1213
- }], maxAttachments: [{
1214
- type: Input
1215
- }], maxAttachmentSizeBytes: [{
1216
- type: Input
1217
- }], acceptedFileTypes: [{
1218
- type: Input
1219
- }], valueChange: [{
1220
- type: Output
1221
- }], mentionSelected: [{
1222
- type: Output
1223
- }], enterPressed: [{
1224
- type: Output
1225
- }], attachmentsChanged: [{
1226
- type: Output
1227
- }], attachmentError: [{
1228
- type: Output
1229
- }], attachmentClicked: [{
1230
- type: Output
1231
- }] }); })();
1232
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MentionEditorComponent, { className: "MentionEditorComponent", filePath: "src/lib/components/mention/mention-editor.component.ts", lineNumber: 69 }); })();
1233
- //# sourceMappingURL=mention-editor.component.js.map