@memberjunction/ng-conversations 5.44.0 → 5.45.1

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 (109) hide show
  1. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts +3 -1
  2. package/dist/lib/components/artifact/artifact-share-modal.component.d.ts.map +1 -1
  3. package/dist/lib/components/artifact/artifact-share-modal.component.js +16 -12
  4. package/dist/lib/components/artifact/artifact-share-modal.component.js.map +1 -1
  5. package/dist/lib/components/collection/collection-share-modal.component.d.ts +3 -1
  6. package/dist/lib/components/collection/collection-share-modal.component.d.ts.map +1 -1
  7. package/dist/lib/components/collection/collection-share-modal.component.js +16 -12
  8. package/dist/lib/components/collection/collection-share-modal.component.js.map +1 -1
  9. package/dist/lib/components/collection/collection-tree.component.d.ts +3 -1
  10. package/dist/lib/components/collection/collection-tree.component.d.ts.map +1 -1
  11. package/dist/lib/components/collection/collection-tree.component.js +10 -7
  12. package/dist/lib/components/collection/collection-tree.component.js.map +1 -1
  13. package/dist/lib/components/collection/collection-view.component.d.ts +3 -1
  14. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  15. package/dist/lib/components/collection/collection-view.component.js +10 -8
  16. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  17. package/dist/lib/components/composer/ai-composer.component.d.ts +103 -0
  18. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -0
  19. package/dist/lib/components/composer/ai-composer.component.js +263 -0
  20. package/dist/lib/components/composer/ai-composer.component.js.map +1 -0
  21. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +3 -4
  22. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  23. package/dist/lib/components/conversation/conversation-chat-area.component.js +36 -36
  24. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  25. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +1 -1
  26. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  27. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  28. package/dist/lib/components/message/message-input.component.d.ts +5 -6
  29. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  30. package/dist/lib/components/message/message-input.component.js +35 -20
  31. package/dist/lib/components/message/message-input.component.js.map +1 -1
  32. package/dist/lib/components/message/message-item.component.d.ts +2 -3
  33. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  34. package/dist/lib/components/message/message-item.component.js +17 -17
  35. package/dist/lib/components/message/message-item.component.js.map +1 -1
  36. package/dist/lib/components/overlay/chat-overlay.component.d.ts +1 -1
  37. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  38. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  39. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +11 -3
  40. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
  41. package/dist/lib/components/sidebar/conversation-sidebar.component.js +34 -10
  42. package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
  43. package/dist/lib/components/sidebar/routines-section.component.d.ts +73 -0
  44. package/dist/lib/components/sidebar/routines-section.component.d.ts.map +1 -0
  45. package/dist/lib/components/sidebar/routines-section.component.js +211 -0
  46. package/dist/lib/components/sidebar/routines-section.component.js.map +1 -0
  47. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts +12 -0
  48. package/dist/lib/components/tasks/tasks-dropdown.component.d.ts.map +1 -1
  49. package/dist/lib/components/tasks/tasks-dropdown.component.js +37 -1
  50. package/dist/lib/components/tasks/tasks-dropdown.component.js.map +1 -1
  51. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +11 -5
  52. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  53. package/dist/lib/components/workspace/conversation-workspace.component.js +35 -26
  54. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  55. package/dist/lib/composer-plugins/agent-mention.provider.d.ts +16 -0
  56. package/dist/lib/composer-plugins/agent-mention.provider.d.ts.map +1 -0
  57. package/dist/lib/composer-plugins/agent-mention.provider.js +28 -0
  58. package/dist/lib/composer-plugins/agent-mention.provider.js.map +1 -0
  59. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts +20 -0
  60. package/dist/lib/composer-plugins/base-conversation-mention.provider.d.ts.map +1 -0
  61. package/dist/lib/composer-plugins/base-conversation-mention.provider.js +32 -0
  62. package/dist/lib/composer-plugins/base-conversation-mention.provider.js.map +1 -0
  63. package/dist/lib/composer-plugins/load-composer-plugins.d.ts +9 -0
  64. package/dist/lib/composer-plugins/load-composer-plugins.d.ts.map +1 -0
  65. package/dist/lib/composer-plugins/load-composer-plugins.js +17 -0
  66. package/dist/lib/composer-plugins/load-composer-plugins.js.map +1 -0
  67. package/dist/lib/composer-plugins/record-mention.provider.d.ts +14 -0
  68. package/dist/lib/composer-plugins/record-mention.provider.d.ts.map +1 -0
  69. package/dist/lib/composer-plugins/record-mention.provider.js +26 -0
  70. package/dist/lib/composer-plugins/record-mention.provider.js.map +1 -0
  71. package/dist/lib/composer-plugins/skill-command.provider.d.ts +15 -0
  72. package/dist/lib/composer-plugins/skill-command.provider.d.ts.map +1 -0
  73. package/dist/lib/composer-plugins/skill-command.provider.js +27 -0
  74. package/dist/lib/composer-plugins/skill-command.provider.js.map +1 -0
  75. package/dist/lib/conversations.module.d.ts +74 -73
  76. package/dist/lib/conversations.module.d.ts.map +1 -1
  77. package/dist/lib/conversations.module.js +33 -13
  78. package/dist/lib/conversations.module.js.map +1 -1
  79. package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
  80. package/dist/lib/services/active-tasks.service.js +4 -1
  81. package/dist/lib/services/active-tasks.service.js.map +1 -1
  82. package/dist/lib/services/conversation-agent.service.d.ts +7 -0
  83. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  84. package/dist/lib/services/conversation-agent.service.js +20 -0
  85. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  86. package/dist/lib/services/conversation-attachment.service.d.ts +1 -1
  87. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  88. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  89. package/dist/lib/services/mention-autocomplete.service.d.ts +27 -20
  90. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  91. package/dist/lib/services/mention-autocomplete.service.js +55 -16
  92. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  93. package/dist/public-api.d.ts +23 -3
  94. package/dist/public-api.d.ts.map +1 -1
  95. package/dist/public-api.js +38 -3
  96. package/dist/public-api.js.map +1 -1
  97. package/package.json +29 -27
  98. package/dist/lib/components/mention/mention-dropdown.component.d.ts +0 -53
  99. package/dist/lib/components/mention/mention-dropdown.component.d.ts.map +0 -1
  100. package/dist/lib/components/mention/mention-dropdown.component.js +0 -297
  101. package/dist/lib/components/mention/mention-dropdown.component.js.map +0 -1
  102. package/dist/lib/components/mention/mention-editor.component.d.ts +0 -256
  103. package/dist/lib/components/mention/mention-editor.component.d.ts.map +0 -1
  104. package/dist/lib/components/mention/mention-editor.component.js +0 -1247
  105. package/dist/lib/components/mention/mention-editor.component.js.map +0 -1
  106. package/dist/lib/components/message/message-input-box.component.d.ts +0 -132
  107. package/dist/lib/components/message/message-input-box.component.d.ts.map +0 -1
  108. package/dist/lib/components/message/message-input-box.component.js +0 -327
  109. package/dist/lib/components/message/message-input-box.component.js.map +0 -1
@@ -1,327 +0,0 @@
1
- import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
2
- import * as i0 from "@angular/core";
3
- import * as i1 from "@angular/forms";
4
- import * as i2 from "../mention/mention-editor.component";
5
- const _c0 = ["mentionEditor"];
6
- function MessageInputBoxComponent_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
7
- const _r2 = i0.ɵɵgetCurrentView();
8
- i0.ɵɵelementStart(0, "button", 9);
9
- i0.ɵɵlistener("click", function MessageInputBoxComponent_Conditional_4_Conditional_1_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.planModeToggle.emit(); return i0.ɵɵresetView($event.stopPropagation()); });
10
- i0.ɵɵelement(1, "i", 10);
11
- i0.ɵɵelementEnd();
12
- } if (rf & 2) {
13
- const ctx_r2 = i0.ɵɵnextContext(2);
14
- i0.ɵɵclassProp("plan-mode-button-icon--active", ctx_r2.planModeActive);
15
- i0.ɵɵproperty("disabled", ctx_r2.disabled)("title", ctx_r2.planModeActive ? "Plan Mode ON \u2014 the agent presents a plan for your approval before it acts" : "Plan Mode: have the agent present a plan for your approval before it acts");
16
- i0.ɵɵattribute("aria-pressed", ctx_r2.planModeActive);
17
- } }
18
- function MessageInputBoxComponent_Conditional_4_Conditional_2_Template(rf, ctx) { if (rf & 1) {
19
- const _r4 = i0.ɵɵgetCurrentView();
20
- i0.ɵɵelementStart(0, "button", 11);
21
- i0.ɵɵlistener("click", function MessageInputBoxComponent_Conditional_4_Conditional_2_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.openFilePicker(); return i0.ɵɵresetView($event.stopPropagation()); });
22
- i0.ɵɵelement(1, "i", 12);
23
- i0.ɵɵelementEnd();
24
- } if (rf & 2) {
25
- const ctx_r2 = i0.ɵɵnextContext(2);
26
- i0.ɵɵproperty("disabled", ctx_r2.disabled);
27
- } }
28
- function MessageInputBoxComponent_Conditional_4_Conditional_3_Template(rf, ctx) { if (rf & 1) {
29
- const _r5 = i0.ɵɵgetCurrentView();
30
- i0.ɵɵelementStart(0, "button", 13);
31
- i0.ɵɵlistener("click", function MessageInputBoxComponent_Conditional_4_Conditional_3_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.onRealtimeClick(); return i0.ɵɵresetView($event.stopPropagation()); });
32
- i0.ɵɵelement(1, "i", 14);
33
- i0.ɵɵelementEnd();
34
- i0.ɵɵelementStart(2, "button", 15);
35
- i0.ɵɵlistener("click", function MessageInputBoxComponent_Conditional_4_Conditional_3_Template_button_click_2_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.onRealtimeOptionsClick(); return i0.ɵɵresetView($event.stopPropagation()); });
36
- i0.ɵɵelement(3, "i", 16);
37
- i0.ɵɵelementEnd();
38
- } if (rf & 2) {
39
- const ctx_r2 = i0.ɵɵnextContext(2);
40
- i0.ɵɵclassProp("voice-button-icon--active", ctx_r2.voiceActive);
41
- i0.ɵɵproperty("disabled", !ctx_r2.canStartRealtime)("title", ctx_r2.voiceActive ? "Voice call active" : "Start a voice call");
42
- i0.ɵɵadvance(2);
43
- i0.ɵɵproperty("disabled", !ctx_r2.canStartRealtime);
44
- } }
45
- function MessageInputBoxComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
46
- i0.ɵɵelementStart(0, "div", 4);
47
- i0.ɵɵconditionalCreate(1, MessageInputBoxComponent_Conditional_4_Conditional_1_Template, 2, 5, "button", 7);
48
- i0.ɵɵconditionalCreate(2, MessageInputBoxComponent_Conditional_4_Conditional_2_Template, 2, 1, "button", 8);
49
- i0.ɵɵconditionalCreate(3, MessageInputBoxComponent_Conditional_4_Conditional_3_Template, 4, 5);
50
- i0.ɵɵelementEnd();
51
- } if (rf & 2) {
52
- const ctx_r2 = i0.ɵɵnextContext();
53
- i0.ɵɵadvance();
54
- i0.ɵɵconditional(ctx_r2.enablePlanMode ? 1 : -1);
55
- i0.ɵɵadvance();
56
- i0.ɵɵconditional(ctx_r2.enableAttachments ? 2 : -1);
57
- i0.ɵɵadvance();
58
- i0.ɵɵconditional(ctx_r2.enableRealtime ? 3 : -1);
59
- } }
60
- /**
61
- * Reusable message input box component (presentational)
62
- * Now uses MentionEditorComponent for rich @mention functionality with chips
63
- *
64
- * Handles:
65
- * - Text input with keyboard shortcuts via MentionEditorComponent
66
- * - @mention autocomplete with visual chips (contentEditable)
67
- * - Send button
68
- *
69
- * Does NOT handle:
70
- * - Saving messages to database
71
- * - Agent invocation
72
- * - Artifact creation
73
- * - Conversation management
74
- */
75
- export class MessageInputBoxComponent {
76
- mentionEditor;
77
- placeholder = 'Type your message to start a new conversation...';
78
- disabled = false;
79
- value = '';
80
- showCharacterCount = false;
81
- enableMentions = true;
82
- currentUser;
83
- rows = 3;
84
- // Attachment settings
85
- enableAttachments = true;
86
- maxAttachments = 10;
87
- maxAttachmentSizeBytes = 20 * 1024 * 1024; // 20MB
88
- acceptedFileTypes = 'image/*';
89
- /** Shows the in-composer mic button when true. */
90
- enableRealtime = false;
91
- /** Whether a realtime voice session is currently active (mic renders in its active state). */
92
- voiceActive = false;
93
- /** Whether a voice session can be started right now (mic disabled when false). */
94
- canStartRealtime = true;
95
- /** Shows the in-composer Plan Mode toggle button when true. */
96
- enablePlanMode = false;
97
- /** Current Plan Mode toggle state (renders the button in its active state). */
98
- planModeActive = false;
99
- textSubmitted = new EventEmitter();
100
- valueChange = new EventEmitter();
101
- attachmentsChanged = new EventEmitter();
102
- attachmentError = new EventEmitter();
103
- attachmentClicked = new EventEmitter();
104
- /** Emitted when the user clicks the mic button to start/stop a voice session. */
105
- voiceRequested = new EventEmitter();
106
- /**
107
- * Emitted when the user clicks the small caret next to the phone button — the host opens the
108
- * voice agent/model picker so call options (which agent, which voice model) stay reachable
109
- * without adding friction to the plain phone click's instant-start path.
110
- */
111
- voiceOptionsRequested = new EventEmitter();
112
- /** Emitted when the user clicks the in-composer Plan Mode toggle button. */
113
- planModeToggle = new EventEmitter();
114
- onRealtimeClick() {
115
- this.voiceRequested.emit();
116
- }
117
- onRealtimeOptionsClick() {
118
- this.voiceOptionsRequested.emit();
119
- }
120
- get canSend() {
121
- const hasText = this.value.trim().length > 0;
122
- const hasAttachments = this.mentionEditor?.hasAttachments() || false;
123
- return !this.disabled && (hasText || hasAttachments);
124
- }
125
- /**
126
- * Handle value changes from MentionEditorComponent
127
- */
128
- onValueChange(newValue) {
129
- this.value = newValue;
130
- this.valueChange.emit(this.value);
131
- }
132
- /**
133
- * Handle attachment changes from MentionEditorComponent
134
- */
135
- onAttachmentsChanged(attachments) {
136
- this.attachmentsChanged.emit(attachments);
137
- }
138
- /**
139
- * Handle attachment errors from MentionEditorComponent
140
- */
141
- onAttachmentError(error) {
142
- this.attachmentError.emit(error);
143
- }
144
- /**
145
- * Handle attachment click from MentionEditorComponent
146
- */
147
- onAttachmentClicked(attachment) {
148
- this.attachmentClicked.emit(attachment);
149
- }
150
- /**
151
- * Handle Enter key from MentionEditorComponent
152
- * Extracts plain text with JSON-encoded mentions for message submission
153
- */
154
- onEnterPressed(_text) {
155
- this.onSendClick();
156
- }
157
- /**
158
- * Handle mention selection from MentionEditorComponent
159
- */
160
- onMentionSelected(suggestion) {
161
- // MentionEditorComponent already inserts the mention chip
162
- // This is just for additional tracking/analytics if needed
163
- }
164
- /**
165
- * Send the message
166
- * Extracts plain text with JSON-encoded mentions for proper persistence
167
- */
168
- onSendClick() {
169
- if (this.canSend) {
170
- // Get plain text with JSON-encoded mentions (preserves configuration info)
171
- const textToSend = this.mentionEditor?.getPlainTextWithJsonMentions() || this.value.trim();
172
- this.textSubmitted.emit(textToSend);
173
- this.value = ''; // Clear input after sending
174
- // Clear the editor content
175
- if (this.mentionEditor) {
176
- this.mentionEditor.clear();
177
- }
178
- this.valueChange.emit(this.value);
179
- }
180
- }
181
- /**
182
- * Handle clicks on the container - focus the mention editor
183
- * Only moves cursor to end if clicking outside the contentEditable area
184
- */
185
- onContainerClick(event) {
186
- const target = event.target;
187
- // Don't handle clicks on the send button
188
- if (target.closest('.send-button-icon')) {
189
- return;
190
- }
191
- const editor = this.mentionEditor?.editorRef?.nativeElement;
192
- if (!editor)
193
- return;
194
- // If clicking directly on the editor or its children, let the browser handle cursor placement
195
- if (target === editor || editor.contains(target)) {
196
- return;
197
- }
198
- // Only if clicking on the container (empty space), focus and move cursor to end
199
- editor.focus();
200
- const selection = window.getSelection();
201
- const range = document.createRange();
202
- if (selection) {
203
- range.selectNodeContents(editor);
204
- range.collapse(false); // Collapse to end
205
- selection.removeAllRanges();
206
- selection.addRange(range);
207
- }
208
- }
209
- /**
210
- * Public method to focus the input programmatically
211
- */
212
- focus() {
213
- const editor = this.mentionEditor?.editorRef?.nativeElement;
214
- if (editor) {
215
- editor.focus();
216
- }
217
- }
218
- /**
219
- * Get mention chip data including configuration presets
220
- */
221
- getMentionChipsData() {
222
- return this.mentionEditor?.getMentionChipsData() || [];
223
- }
224
- /**
225
- * Get pending attachments from the editor
226
- */
227
- getPendingAttachments() {
228
- return this.mentionEditor?.getPendingAttachments() || [];
229
- }
230
- /**
231
- * Open file picker programmatically
232
- */
233
- openFilePicker() {
234
- this.mentionEditor?.openFilePicker();
235
- }
236
- /**
237
- * Add an artifact as a pending attachment (called by parent after artifact selection)
238
- */
239
- AddArtifactAttachment(artifact) {
240
- return this.mentionEditor?.AddArtifactAttachment(artifact);
241
- }
242
- static ɵfac = function MessageInputBoxComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MessageInputBoxComponent)(); };
243
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MessageInputBoxComponent, selectors: [["mj-message-input-box"]], viewQuery: function MessageInputBoxComponent_Query(rf, ctx) { if (rf & 1) {
244
- i0.ɵɵviewQuery(_c0, 5);
245
- } if (rf & 2) {
246
- let _t;
247
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.mentionEditor = _t.first);
248
- } }, inputs: { placeholder: "placeholder", disabled: "disabled", value: "value", showCharacterCount: "showCharacterCount", enableMentions: "enableMentions", currentUser: "currentUser", rows: "rows", enableAttachments: "enableAttachments", maxAttachments: "maxAttachments", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", acceptedFileTypes: "acceptedFileTypes", enableRealtime: "enableRealtime", voiceActive: "voiceActive", canStartRealtime: "canStartRealtime", enablePlanMode: "enablePlanMode", planModeActive: "planModeActive" }, outputs: { textSubmitted: "textSubmitted", valueChange: "valueChange", attachmentsChanged: "attachmentsChanged", attachmentError: "attachmentError", attachmentClicked: "attachmentClicked", voiceRequested: "voiceRequested", voiceOptionsRequested: "voiceOptionsRequested", planModeToggle: "planModeToggle" }, standalone: false, decls: 7, vars: 11, consts: [["mentionEditor", ""], [1, "message-input-box-container", 3, "click"], [1, "input-wrapper"], [3, "ngModelChange", "valueChange", "enterPressed", "mentionSelected", "attachmentsChanged", "attachmentError", "attachmentClicked", "placeholder", "disabled", "currentUser", "enableMentions", "enableAttachments", "maxAttachments", "maxAttachmentSizeBytes", "acceptedFileTypes", "ngModel"], [1, "attach-buttons"], ["title", "Send message (Enter)", 1, "send-button-icon", 3, "click", "disabled"], [1, "fa-solid", "fa-paper-plane"], ["aria-label", "Toggle Plan Mode", 1, "attach-button-icon", "plan-mode-button-icon", 3, "plan-mode-button-icon--active", "disabled", "title"], ["title", "Attach file", 1, "attach-button-icon", 3, "disabled"], ["aria-label", "Toggle Plan Mode", 1, "attach-button-icon", "plan-mode-button-icon", 3, "click", "disabled", "title"], ["aria-hidden", "true", 1, "fa-solid", "fa-route"], ["title", "Attach file", 1, "attach-button-icon", 3, "click", "disabled"], [1, "fa-solid", "fa-paperclip"], ["aria-label", "Start a voice call", 1, "attach-button-icon", "voice-button-icon", 3, "click", "disabled", "title"], ["aria-hidden", "true", 1, "fa-solid", "fa-phone"], ["title", "Voice call options (choose agent and voice model)", "aria-label", "Voice call options", 1, "attach-button-icon", "voice-options-button-icon", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down"]], template: function MessageInputBoxComponent_Template(rf, ctx) { if (rf & 1) {
249
- const _r1 = i0.ɵɵgetCurrentView();
250
- i0.ɵɵelementStart(0, "div", 1);
251
- i0.ɵɵlistener("click", function MessageInputBoxComponent_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onContainerClick($event)); });
252
- i0.ɵɵelementStart(1, "div", 2)(2, "mj-mention-editor", 3, 0);
253
- i0.ɵɵtwoWayListener("ngModelChange", function MessageInputBoxComponent_Template_mj_mention_editor_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.value, $event) || (ctx.value = $event); return i0.ɵɵresetView($event); });
254
- i0.ɵɵlistener("valueChange", function MessageInputBoxComponent_Template_mj_mention_editor_valueChange_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onValueChange($event)); })("enterPressed", function MessageInputBoxComponent_Template_mj_mention_editor_enterPressed_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onEnterPressed($event)); })("mentionSelected", function MessageInputBoxComponent_Template_mj_mention_editor_mentionSelected_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onMentionSelected($event)); })("attachmentsChanged", function MessageInputBoxComponent_Template_mj_mention_editor_attachmentsChanged_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentsChanged($event)); })("attachmentError", function MessageInputBoxComponent_Template_mj_mention_editor_attachmentError_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentError($event)); })("attachmentClicked", function MessageInputBoxComponent_Template_mj_mention_editor_attachmentClicked_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentClicked($event)); });
255
- i0.ɵɵelementEnd();
256
- i0.ɵɵconditionalCreate(4, MessageInputBoxComponent_Conditional_4_Template, 4, 3, "div", 4);
257
- i0.ɵɵelementStart(5, "button", 5);
258
- i0.ɵɵlistener("click", function MessageInputBoxComponent_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSendClick()); });
259
- i0.ɵɵelement(6, "i", 6);
260
- i0.ɵɵelementEnd()()();
261
- } if (rf & 2) {
262
- i0.ɵɵadvance(2);
263
- i0.ɵɵproperty("placeholder", ctx.placeholder)("disabled", ctx.disabled)("currentUser", ctx.currentUser)("enableMentions", ctx.enableMentions)("enableAttachments", ctx.enableAttachments)("maxAttachments", ctx.maxAttachments)("maxAttachmentSizeBytes", ctx.maxAttachmentSizeBytes)("acceptedFileTypes", ctx.acceptedFileTypes);
264
- i0.ɵɵtwoWayProperty("ngModel", ctx.value);
265
- i0.ɵɵadvance(2);
266
- i0.ɵɵconditional(ctx.enableAttachments || ctx.enableRealtime || ctx.enablePlanMode ? 4 : -1);
267
- i0.ɵɵadvance();
268
- i0.ɵɵproperty("disabled", !ctx.canSend);
269
- } }, dependencies: [i1.NgControlStatus, i1.NgModel, i2.MentionEditorComponent], styles: [".message-input-box-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n transition: all 0.2s ease;\n overflow: visible;\n position: relative;\n cursor: text;\n}\n.message-input-box-container[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 16px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.input-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: flex-end;\n padding: 5px;\n}\n.input-wrapper[_ngcontent-%COMP%] mj-mention-editor[_ngcontent-%COMP%] {\n flex: 1;\n display: block;\n}\n\n.message-input-box-textarea[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 100px;\n padding: 1rem;\n padding-right: 3.5rem;\n border: 0 !important;\n outline: 0 !important;\n box-shadow: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n appearance: none !important;\n font-family: inherit;\n font-size: 1rem;\n line-height: 1.5;\n resize: vertical;\n background: transparent;\n color: var(--mj-text-primary);\n border: 0 !important;\n}\n.message-input-box-textarea[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-muted);\n}\n.message-input-box-textarea[_ngcontent-%COMP%]:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n background: var(--mj-bg-surface-sunken);\n}\n.message-input-box-textarea[_ngcontent-%COMP%]:focus, .message-input-box-textarea[_ngcontent-%COMP%]:active, .message-input-box-textarea[_ngcontent-%COMP%]:focus-visible {\n outline: 0 !important;\n box-shadow: none !important;\n}\n\n.send-button-icon[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 0.75rem;\n right: 0.75rem;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n.send-button-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n.send-button-icon[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n}\n.send-button-icon[_ngcontent-%COMP%]:active:not(:disabled) {\n transform: scale(0.95);\n}\n.send-button-icon[_ngcontent-%COMP%]:disabled {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n\n\n.attach-buttons[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 0.75rem;\n right: 3rem;\n display: flex;\n gap: 2px;\n}\n.attach-button-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n color: var(--mj-text-secondary);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n.attach-button-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n.attach-button-icon[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-text-primary) 5%, transparent);\n color: var(--mj-brand-primary);\n transform: scale(1.05);\n}\n.attach-button-icon[_ngcontent-%COMP%]:active:not(:disabled) {\n transform: scale(0.95);\n}\n.attach-button-icon[_ngcontent-%COMP%]:disabled {\n color: var(--mj-text-muted);\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n\n\n\n.plan-mode-button-icon--active[_ngcontent-%COMP%]:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n.plan-mode-button-icon--active[_ngcontent-%COMP%]:not(:disabled):hover {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n color: var(--mj-text-inverse);\n}\n\n\n\n@media (max-width: 768px) {\n .message-input-box-container[_ngcontent-%COMP%] {\n border-radius: 10px;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-text-primary) 6%, transparent);\n }\n .message-input-box-textarea[_ngcontent-%COMP%] {\n min-height: 80px;\n padding: 0.75rem;\n padding-right: 3rem;\n font-size: 16px;\n line-height: 1.4;\n }\n .send-button-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n bottom: 0.625rem;\n right: 0.625rem;\n border-radius: 6px;\n }\n .send-button-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n }\n .attach-buttons[_ngcontent-%COMP%] {\n bottom: 0.625rem;\n right: 2.75rem;\n }\n .attach-button-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n }\n .attach-button-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n }\n}\n\n\n@media (max-width: 480px) {\n .message-input-box-container[_ngcontent-%COMP%] {\n border-radius: 8px;\n border-width: 1.5px;\n }\n .message-input-box-textarea[_ngcontent-%COMP%] {\n min-height: 60px;\n padding: 0.625rem;\n padding-right: 2.75rem;\n font-size: 16px;\n line-height: 1.3;\n }\n .send-button-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n bottom: 0.5rem;\n right: 0.5rem;\n border-radius: 6px;\n }\n .send-button-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n }\n .attach-buttons[_ngcontent-%COMP%] {\n bottom: 0.5rem;\n right: 2.75rem;\n }\n .attach-button-icon[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n }\n .attach-button-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n }\n}\n\n\n\n\n\n\n.voice-button-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n.voice-button-icon[_ngcontent-%COMP%]:hover:not(:disabled) i[_ngcontent-%COMP%] {\n filter: drop-shadow(0 0 4px color-mix(in srgb, var(--mj-brand-primary) 55%, transparent));\n}\n.voice-button-icon[_ngcontent-%COMP%]:disabled i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}\n.voice-button-icon--active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n.voice-button-icon--active[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n\n\n\n\n\n.voice-options-button-icon[_ngcontent-%COMP%] {\n width: 20px;\n margin-left: -4px;\n}\n.voice-options-button-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n color: var(--mj-text-muted);\n}\n.voice-options-button-icon[_ngcontent-%COMP%]:hover:not(:disabled) i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n.voice-options-button-icon[_ngcontent-%COMP%]:disabled i[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n}"] });
270
- }
271
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageInputBoxComponent, [{
272
- type: Component,
273
- args: [{ standalone: false, selector: 'mj-message-input-box', template: "<div class=\"message-input-box-container\" (click)=\"onContainerClick($event)\">\n <div class=\"input-wrapper\">\n <mj-mention-editor\n #mentionEditor\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [currentUser]=\"currentUser\"\n [enableMentions]=\"enableMentions\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n [(ngModel)]=\"value\"\n (valueChange)=\"onValueChange($event)\"\n (enterPressed)=\"onEnterPressed($event)\"\n (mentionSelected)=\"onMentionSelected($event)\"\n (attachmentsChanged)=\"onAttachmentsChanged($event)\"\n (attachmentError)=\"onAttachmentError($event)\"\n (attachmentClicked)=\"onAttachmentClicked($event)\">\n </mj-mention-editor>\n\n <!-- Attach + voice + plan-mode buttons - Positioned over editor -->\n @if (enableAttachments || enableRealtime || enablePlanMode) {\n <div class=\"attach-buttons\">\n @if (enablePlanMode) {\n <button\n class=\"attach-button-icon plan-mode-button-icon\"\n [class.plan-mode-button-icon--active]=\"planModeActive\"\n [disabled]=\"disabled\"\n [attr.aria-pressed]=\"planModeActive\"\n (click)=\"planModeToggle.emit(); $event.stopPropagation()\"\n [title]=\"planModeActive ? 'Plan Mode ON \u2014 the agent presents a plan for your approval before it acts' : 'Plan Mode: have the agent present a plan for your approval before it acts'\"\n aria-label=\"Toggle Plan Mode\"\n >\n <i class=\"fa-solid fa-route\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (enableAttachments) {\n <button\n class=\"attach-button-icon\"\n [disabled]=\"disabled\"\n (click)=\"openFilePicker(); $event.stopPropagation()\"\n title=\"Attach file\"\n >\n <i class=\"fa-solid fa-paperclip\"></i>\n </button>\n }\n @if (enableRealtime) {\n <button\n class=\"attach-button-icon voice-button-icon\"\n [class.voice-button-icon--active]=\"voiceActive\"\n [disabled]=\"!canStartRealtime\"\n (click)=\"onRealtimeClick(); $event.stopPropagation()\"\n [title]=\"voiceActive ? 'Voice call active' : 'Start a voice call'\"\n aria-label=\"Start a voice call\"\n >\n <i class=\"fa-solid fa-phone\" aria-hidden=\"true\"></i>\n </button>\n <!-- Caret beside the phone: opens the agent/model picker so call OPTIONS stay one\n click away while the plain phone click keeps its instant-start behavior. -->\n <button\n class=\"attach-button-icon voice-options-button-icon\"\n [disabled]=\"!canStartRealtime\"\n (click)=\"onRealtimeOptionsClick(); $event.stopPropagation()\"\n title=\"Voice call options (choose agent and voice model)\"\n aria-label=\"Voice call options\"\n >\n <i class=\"fa-solid fa-chevron-down\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n }\n\n <!-- Send Button (Icon Only) - Positioned over editor -->\n <button\n class=\"send-button-icon\"\n [disabled]=\"!canSend\"\n (click)=\"onSendClick()\"\n title=\"Send message (Enter)\"\n >\n <i class=\"fa-solid fa-paper-plane\"></i>\n </button>\n </div>\n</div>\n", styles: [".message-input-box-container {\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-sm);\n transition: all 0.2s ease;\n overflow: visible;\n position: relative;\n cursor: text;\n}\n.message-input-box-container:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 16px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.input-wrapper {\n position: relative;\n display: flex;\n align-items: flex-end;\n padding: 5px;\n}\n.input-wrapper mj-mention-editor {\n flex: 1;\n display: block;\n}\n\n.message-input-box-textarea {\n flex: 1;\n min-height: 100px;\n padding: 1rem;\n padding-right: 3.5rem;\n border: 0 !important;\n outline: 0 !important;\n box-shadow: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n appearance: none !important;\n font-family: inherit;\n font-size: 1rem;\n line-height: 1.5;\n resize: vertical;\n background: transparent;\n color: var(--mj-text-primary);\n border: 0 !important;\n}\n.message-input-box-textarea::placeholder {\n color: var(--mj-text-muted);\n}\n.message-input-box-textarea:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n background: var(--mj-bg-surface-sunken);\n}\n.message-input-box-textarea:focus, .message-input-box-textarea:active, .message-input-box-textarea:focus-visible {\n outline: 0 !important;\n box-shadow: none !important;\n}\n\n.send-button-icon {\n position: absolute;\n bottom: 0.75rem;\n right: 0.75rem;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n.send-button-icon i {\n font-size: 1rem;\n}\n.send-button-icon:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n transform: scale(1.05);\n}\n.send-button-icon:active:not(:disabled) {\n transform: scale(0.95);\n}\n.send-button-icon:disabled {\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Attach buttons container */\n.attach-buttons {\n position: absolute;\n bottom: 0.75rem;\n right: 3rem;\n display: flex;\n gap: 2px;\n}\n.attach-button-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n color: var(--mj-text-secondary);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n}\n.attach-button-icon i {\n font-size: 1rem;\n}\n.attach-button-icon:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-text-primary) 5%, transparent);\n color: var(--mj-brand-primary);\n transform: scale(1.05);\n}\n.attach-button-icon:active:not(:disabled) {\n transform: scale(0.95);\n}\n.attach-button-icon:disabled {\n color: var(--mj-text-muted);\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n/* Plan Mode toggle \u2014 inherits .attach-button-icon; when active it fills with the brand color\n so the on/off state reads clearly at a glance (parallels the voice button's active state). */\n.plan-mode-button-icon--active:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n.plan-mode-button-icon--active:not(:disabled):hover {\n background: var(--mj-brand-primary-hover, var(--mj-brand-primary));\n color: var(--mj-text-inverse);\n}\n\n/* Mobile adjustments: 481px - 768px */\n@media (max-width: 768px) {\n .message-input-box-container {\n border-radius: 10px;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-text-primary) 6%, transparent);\n }\n .message-input-box-textarea {\n min-height: 80px;\n padding: 0.75rem;\n padding-right: 3rem;\n font-size: 16px;\n line-height: 1.4;\n }\n .send-button-icon {\n width: 32px;\n height: 32px;\n bottom: 0.625rem;\n right: 0.625rem;\n border-radius: 6px;\n }\n .send-button-icon i {\n font-size: 0.875rem;\n }\n .attach-buttons {\n bottom: 0.625rem;\n right: 2.75rem;\n }\n .attach-button-icon {\n width: 32px;\n height: 32px;\n }\n .attach-button-icon i {\n font-size: 0.875rem;\n }\n}\n/* Small Phone adjustments: <= 480px */\n@media (max-width: 480px) {\n .message-input-box-container {\n border-radius: 8px;\n border-width: 1.5px;\n }\n .message-input-box-textarea {\n min-height: 60px;\n padding: 0.625rem;\n padding-right: 2.75rem;\n font-size: 16px;\n line-height: 1.3;\n }\n .send-button-icon {\n width: 36px;\n height: 36px;\n bottom: 0.5rem;\n right: 0.5rem;\n border-radius: 6px;\n }\n .send-button-icon i {\n font-size: 0.875rem;\n }\n .attach-buttons {\n bottom: 0.5rem;\n right: 2.75rem;\n }\n .attach-button-icon {\n width: 32px;\n height: 32px;\n }\n .attach-button-icon i {\n font-size: 0.875rem;\n }\n}\n\n/* Voice call button \u2014 a phone icon in the attach-buttons cluster, left of send.\n Inherits .attach-button-icon base. Subtle brand glow on hover; active state (call\n live) renders a brand-color tint. The orb visual now lives ONLY inside the call\n overlay's banner. */\n.voice-button-icon i {\n color: var(--mj-brand-primary);\n}\n.voice-button-icon:hover:not(:disabled) i {\n filter: drop-shadow(0 0 4px color-mix(in srgb, var(--mj-brand-primary) 55%, transparent));\n}\n.voice-button-icon:disabled i {\n color: var(--mj-text-disabled);\n}\n.voice-button-icon--active {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n.voice-button-icon--active:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n\n/* Voice OPTIONS caret \u2014 a slim chevron hugging the phone button. Opens the agent/model\n picker; intentionally quieter (smaller icon, narrower hit area) than the phone so the\n common instant-start click stays the visual primary. */\n.voice-options-button-icon {\n width: 20px;\n margin-left: -4px;\n}\n.voice-options-button-icon i {\n font-size: 0.7rem;\n color: var(--mj-text-muted);\n}\n.voice-options-button-icon:hover:not(:disabled) i {\n color: var(--mj-brand-primary);\n}\n.voice-options-button-icon:disabled i {\n color: var(--mj-text-disabled);\n}\n"] }]
274
- }], null, { mentionEditor: [{
275
- type: ViewChild,
276
- args: ['mentionEditor']
277
- }], placeholder: [{
278
- type: Input
279
- }], disabled: [{
280
- type: Input
281
- }], value: [{
282
- type: Input
283
- }], showCharacterCount: [{
284
- type: Input
285
- }], enableMentions: [{
286
- type: Input
287
- }], currentUser: [{
288
- type: Input
289
- }], rows: [{
290
- type: Input
291
- }], enableAttachments: [{
292
- type: Input
293
- }], maxAttachments: [{
294
- type: Input
295
- }], maxAttachmentSizeBytes: [{
296
- type: Input
297
- }], acceptedFileTypes: [{
298
- type: Input
299
- }], enableRealtime: [{
300
- type: Input
301
- }], voiceActive: [{
302
- type: Input
303
- }], canStartRealtime: [{
304
- type: Input
305
- }], enablePlanMode: [{
306
- type: Input
307
- }], planModeActive: [{
308
- type: Input
309
- }], textSubmitted: [{
310
- type: Output
311
- }], valueChange: [{
312
- type: Output
313
- }], attachmentsChanged: [{
314
- type: Output
315
- }], attachmentError: [{
316
- type: Output
317
- }], attachmentClicked: [{
318
- type: Output
319
- }], voiceRequested: [{
320
- type: Output
321
- }], voiceOptionsRequested: [{
322
- type: Output
323
- }], planModeToggle: [{
324
- type: Output
325
- }] }); })();
326
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputBoxComponent, { className: "MessageInputBoxComponent", filePath: "src/lib/components/message/message-input-box.component.ts", lineNumber: 27 }); })();
327
- //# sourceMappingURL=message-input-box.component.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"message-input-box.component.js","sourceRoot":"","sources":["../../../../src/lib/components/message/message-input-box.component.ts","../../../../src/lib/components/message/message-input-box.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';\nimport { UserInfo } from '@memberjunction/core';\nimport { MentionSuggestion } from '../../services/mention-autocomplete.service';\nimport { MentionEditorComponent, PendingAttachment } from '../mention/mention-editor.component';\n\n/**\n * Reusable message input box component (presentational)\n * Now uses MentionEditorComponent for rich @mention functionality with chips\n *\n * Handles:\n * - Text input with keyboard shortcuts via MentionEditorComponent\n * - @mention autocomplete with visual chips (contentEditable)\n * - Send button\n *\n * Does NOT handle:\n * - Saving messages to database\n * - Agent invocation\n * - Artifact creation\n * - Conversation management\n */\n@Component({\n standalone: false,\n selector: 'mj-message-input-box',\n templateUrl: './message-input-box.component.html',\n styleUrls: ['./message-input-box.component.css']\n})\nexport class MessageInputBoxComponent {\n @ViewChild('mentionEditor') mentionEditor?: MentionEditorComponent;\n\n @Input() placeholder: string = 'Type your message to start a new conversation...';\n @Input() disabled: boolean = false;\n @Input() value: string = '';\n @Input() showCharacterCount: boolean = false;\n @Input() enableMentions: boolean = true;\n @Input() currentUser?: UserInfo;\n @Input() rows: number = 3;\n\n // Attachment settings\n @Input() enableAttachments: boolean = true;\n @Input() maxAttachments: number = 10;\n @Input() maxAttachmentSizeBytes: number = 20 * 1024 * 1024; // 20MB\n @Input() acceptedFileTypes: string = 'image/*';\n\n /** Shows the in-composer mic button when true. */\n @Input() enableRealtime: boolean = false;\n /** Whether a realtime voice session is currently active (mic renders in its active state). */\n @Input() voiceActive: boolean = false;\n /** Whether a voice session can be started right now (mic disabled when false). */\n @Input() canStartRealtime: boolean = true;\n /** Shows the in-composer Plan Mode toggle button when true. */\n @Input() enablePlanMode: boolean = false;\n /** Current Plan Mode toggle state (renders the button in its active state). */\n @Input() planModeActive: boolean = false;\n\n @Output() textSubmitted = new EventEmitter<string>();\n @Output() valueChange = new EventEmitter<string>();\n @Output() attachmentsChanged = new EventEmitter<PendingAttachment[]>();\n @Output() attachmentError = new EventEmitter<string>();\n @Output() attachmentClicked = new EventEmitter<PendingAttachment>();\n /** Emitted when the user clicks the mic button to start/stop a voice session. */\n @Output() voiceRequested = new EventEmitter<void>();\n /**\n * Emitted when the user clicks the small caret next to the phone button — the host opens the\n * voice agent/model picker so call options (which agent, which voice model) stay reachable\n * without adding friction to the plain phone click's instant-start path.\n */\n @Output() voiceOptionsRequested = new EventEmitter<void>();\n /** Emitted when the user clicks the in-composer Plan Mode toggle button. */\n @Output() planModeToggle = new EventEmitter<void>();\n\n onRealtimeClick(): void {\n this.voiceRequested.emit();\n }\n\n onRealtimeOptionsClick(): void {\n this.voiceOptionsRequested.emit();\n }\n\n get canSend(): boolean {\n const hasText = this.value.trim().length > 0;\n const hasAttachments = this.mentionEditor?.hasAttachments() || false;\n return !this.disabled && (hasText || hasAttachments);\n }\n\n /**\n * Handle value changes from MentionEditorComponent\n */\n onValueChange(newValue: string): void {\n this.value = newValue;\n this.valueChange.emit(this.value);\n }\n\n /**\n * Handle attachment changes from MentionEditorComponent\n */\n onAttachmentsChanged(attachments: PendingAttachment[]): void {\n this.attachmentsChanged.emit(attachments);\n }\n\n /**\n * Handle attachment errors from MentionEditorComponent\n */\n onAttachmentError(error: string): void {\n this.attachmentError.emit(error);\n }\n\n /**\n * Handle attachment click from MentionEditorComponent\n */\n onAttachmentClicked(attachment: PendingAttachment): void {\n this.attachmentClicked.emit(attachment);\n }\n\n /**\n * Handle Enter key from MentionEditorComponent\n * Extracts plain text with JSON-encoded mentions for message submission\n */\n onEnterPressed(_text: string): void {\n this.onSendClick();\n }\n\n /**\n * Handle mention selection from MentionEditorComponent\n */\n onMentionSelected(suggestion: MentionSuggestion): void {\n // MentionEditorComponent already inserts the mention chip\n // This is just for additional tracking/analytics if needed\n }\n\n /**\n * Send the message\n * Extracts plain text with JSON-encoded mentions for proper persistence\n */\n onSendClick(): void {\n if (this.canSend) {\n // Get plain text with JSON-encoded mentions (preserves configuration info)\n const textToSend = this.mentionEditor?.getPlainTextWithJsonMentions() || this.value.trim();\n this.textSubmitted.emit(textToSend);\n this.value = ''; // Clear input after sending\n\n // Clear the editor content\n if (this.mentionEditor) {\n this.mentionEditor.clear();\n }\n\n this.valueChange.emit(this.value);\n }\n }\n\n /**\n * Handle clicks on the container - focus the mention editor\n * Only moves cursor to end if clicking outside the contentEditable area\n */\n onContainerClick(event: MouseEvent): void {\n const target = event.target as HTMLElement;\n\n // Don't handle clicks on the send button\n if (target.closest('.send-button-icon')) {\n return;\n }\n\n const editor = this.mentionEditor?.editorRef?.nativeElement;\n if (!editor) return;\n\n // If clicking directly on the editor or its children, let the browser handle cursor placement\n if (target === editor || editor.contains(target)) {\n return;\n }\n\n // Only if clicking on the container (empty space), focus and move cursor to end\n editor.focus();\n const selection = window.getSelection();\n const range = document.createRange();\n\n if (selection) {\n range.selectNodeContents(editor);\n range.collapse(false); // Collapse to end\n selection.removeAllRanges();\n selection.addRange(range);\n }\n }\n\n /**\n * Public method to focus the input programmatically\n */\n focus(): void {\n const editor = this.mentionEditor?.editorRef?.nativeElement;\n if (editor) {\n editor.focus();\n }\n }\n\n /**\n * Get mention chip data including configuration presets\n */\n getMentionChipsData(): Array<{ id: string; type: string; name: string; presetId?: string; presetName?: string }> {\n return this.mentionEditor?.getMentionChipsData() || [];\n }\n\n /**\n * Get pending attachments from the editor\n */\n getPendingAttachments(): PendingAttachment[] {\n return this.mentionEditor?.getPendingAttachments() || [];\n }\n\n /**\n * Open file picker programmatically\n */\n openFilePicker(): void {\n this.mentionEditor?.openFilePicker();\n }\n\n /**\n * Add an artifact as a pending attachment (called by parent after artifact selection)\n */\n AddArtifactAttachment(artifact: {\n fileID: string; fileName: string; mimeType: string;\n sizeBytes: number; artifactVersionId?: string;\n }): PendingAttachment | undefined {\n return this.mentionEditor?.AddArtifactAttachment(artifact);\n }\n}\n","<div class=\"message-input-box-container\" (click)=\"onContainerClick($event)\">\n <div class=\"input-wrapper\">\n <mj-mention-editor\n #mentionEditor\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [currentUser]=\"currentUser\"\n [enableMentions]=\"enableMentions\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n [(ngModel)]=\"value\"\n (valueChange)=\"onValueChange($event)\"\n (enterPressed)=\"onEnterPressed($event)\"\n (mentionSelected)=\"onMentionSelected($event)\"\n (attachmentsChanged)=\"onAttachmentsChanged($event)\"\n (attachmentError)=\"onAttachmentError($event)\"\n (attachmentClicked)=\"onAttachmentClicked($event)\">\n </mj-mention-editor>\n\n <!-- Attach + voice + plan-mode buttons - Positioned over editor -->\n @if (enableAttachments || enableRealtime || enablePlanMode) {\n <div class=\"attach-buttons\">\n @if (enablePlanMode) {\n <button\n class=\"attach-button-icon plan-mode-button-icon\"\n [class.plan-mode-button-icon--active]=\"planModeActive\"\n [disabled]=\"disabled\"\n [attr.aria-pressed]=\"planModeActive\"\n (click)=\"planModeToggle.emit(); $event.stopPropagation()\"\n [title]=\"planModeActive ? 'Plan Mode ON — the agent presents a plan for your approval before it acts' : 'Plan Mode: have the agent present a plan for your approval before it acts'\"\n aria-label=\"Toggle Plan Mode\"\n >\n <i class=\"fa-solid fa-route\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (enableAttachments) {\n <button\n class=\"attach-button-icon\"\n [disabled]=\"disabled\"\n (click)=\"openFilePicker(); $event.stopPropagation()\"\n title=\"Attach file\"\n >\n <i class=\"fa-solid fa-paperclip\"></i>\n </button>\n }\n @if (enableRealtime) {\n <button\n class=\"attach-button-icon voice-button-icon\"\n [class.voice-button-icon--active]=\"voiceActive\"\n [disabled]=\"!canStartRealtime\"\n (click)=\"onRealtimeClick(); $event.stopPropagation()\"\n [title]=\"voiceActive ? 'Voice call active' : 'Start a voice call'\"\n aria-label=\"Start a voice call\"\n >\n <i class=\"fa-solid fa-phone\" aria-hidden=\"true\"></i>\n </button>\n <!-- Caret beside the phone: opens the agent/model picker so call OPTIONS stay one\n click away while the plain phone click keeps its instant-start behavior. -->\n <button\n class=\"attach-button-icon voice-options-button-icon\"\n [disabled]=\"!canStartRealtime\"\n (click)=\"onRealtimeOptionsClick(); $event.stopPropagation()\"\n title=\"Voice call options (choose agent and voice model)\"\n aria-label=\"Voice call options\"\n >\n <i class=\"fa-solid fa-chevron-down\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n }\n\n <!-- Send Button (Icon Only) - Positioned over editor -->\n <button\n class=\"send-button-icon\"\n [disabled]=\"!canSend\"\n (click)=\"onSendClick()\"\n title=\"Send message (Enter)\"\n >\n <i class=\"fa-solid fa-paper-plane\"></i>\n </button>\n </div>\n</div>\n"]}