@memberjunction/ng-conversations 5.36.0 → 5.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts +47 -0
- package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts.map +1 -0
- package/dist/lib/components/conversation/conversation-agent-picker.component.js +253 -0
- package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -0
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +201 -4
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +776 -263
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +2 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.js +6 -3
- package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-mode-picker.component.d.ts +57 -0
- package/dist/lib/components/conversation/conversation-mode-picker.component.d.ts.map +1 -0
- package/dist/lib/components/conversation/conversation-mode-picker.component.js +252 -0
- package/dist/lib/components/conversation/conversation-mode-picker.component.js.map +1 -0
- package/dist/lib/components/dialogs/rating-dialog.component.d.ts +31 -0
- package/dist/lib/components/dialogs/rating-dialog.component.d.ts.map +1 -0
- package/dist/lib/components/dialogs/rating-dialog.component.js +290 -0
- package/dist/lib/components/dialogs/rating-dialog.component.js.map +1 -0
- package/dist/lib/components/mention/mention-editor.component.d.ts +1 -1
- package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
- package/dist/lib/components/mention/mention-editor.component.js +1 -0
- package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts +43 -18
- package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.js +235 -193
- package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
- package/dist/lib/components/message/message-input-box.component.d.ts +1 -1
- package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input-box.component.js +1 -1
- package/dist/lib/components/message/message-input-box.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +58 -4
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +135 -21
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +0 -13
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +126 -152
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.d.ts +88 -5
- package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
- package/dist/lib/components/overlay/chat-overlay.component.js +296 -54
- package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +11 -0
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +13 -3
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/conversations.module.d.ts +59 -57
- package/dist/lib/conversations.module.d.ts.map +1 -1
- package/dist/lib/conversations.module.js +12 -4
- package/dist/lib/conversations.module.js.map +1 -1
- package/dist/lib/models/conversation-state.model.d.ts +0 -27
- package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
- package/dist/lib/models/conversation-state.model.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +1 -9
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +22 -121
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-attachment.service.js +5 -26
- package/dist/lib/services/conversation-attachment.service.js.map +1 -1
- package/dist/lib/services/conversation-bridge.service.d.ts +13 -0
- package/dist/lib/services/conversation-bridge.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-bridge.service.js +15 -0
- package/dist/lib/services/conversation-bridge.service.js.map +1 -1
- package/dist/lib/services/data-cache.service.d.ts.map +1 -1
- package/dist/lib/services/data-cache.service.js +0 -1
- package/dist/lib/services/data-cache.service.js.map +1 -1
- package/dist/lib/services/dialog.service.d.ts +24 -0
- package/dist/lib/services/dialog.service.d.ts.map +1 -1
- package/dist/lib/services/dialog.service.js +45 -0
- package/dist/lib/services/dialog.service.js.map +1 -1
- package/package.json +23 -22
- package/dist/lib/components/message/suggested-responses.component.d.ts +0 -55
- package/dist/lib/components/message/suggested-responses.component.d.ts.map +0 -1
- package/dist/lib/components/message/suggested-responses.component.js +0 -207
- package/dist/lib/components/message/suggested-responses.component.js.map +0 -1
|
@@ -22,8 +22,8 @@ import { AgentClientService } from '@memberjunction/ng-agent-client';
|
|
|
22
22
|
import { ConversationBridgeService } from '../../services/conversation-bridge.service';
|
|
23
23
|
import * as i0 from "@angular/core";
|
|
24
24
|
import * as i1 from "../conversation/conversation-chat-area.component";
|
|
25
|
-
function
|
|
26
|
-
i0.ɵɵelementStart(0, "span",
|
|
25
|
+
function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
26
|
+
i0.ɵɵelementStart(0, "span", 7);
|
|
27
27
|
i0.ɵɵtext(1);
|
|
28
28
|
i0.ɵɵelementEnd();
|
|
29
29
|
} if (rf & 2) {
|
|
@@ -33,63 +33,90 @@ function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Conditional_2_Te
|
|
|
33
33
|
} }
|
|
34
34
|
function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
35
35
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
36
|
-
i0.ɵɵelementStart(0, "div",
|
|
37
|
-
i0.ɵɵlistener("
|
|
38
|
-
i0.ɵɵelement(1, "i", 3);
|
|
39
|
-
i0.ɵɵconditionalCreate(
|
|
36
|
+
i0.ɵɵelementStart(0, "div", 3);
|
|
37
|
+
i0.ɵɵlistener("pointerdown", function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template_div_pointerdown_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnBubblePointerDown($event)); });
|
|
38
|
+
i0.ɵɵelement(1, "i", 4)(2, "i", 5)(3, "i", 6);
|
|
39
|
+
i0.ɵɵconditionalCreate(4, ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Conditional_4_Template, 2, 1, "span", 7);
|
|
40
|
+
i0.ɵɵelementStart(5, "button", 8);
|
|
41
|
+
i0.ɵɵlistener("pointerdown", function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template_button_pointerdown_5_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView($event.stopPropagation()); })("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template_button_click_5_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.Hide($event)); });
|
|
42
|
+
i0.ɵɵelement(6, "i", 9);
|
|
43
|
+
i0.ɵɵelementEnd()();
|
|
44
|
+
} if (rf & 2) {
|
|
45
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
46
|
+
i0.ɵɵstyleProp("bottom", ctx_r1.BubbleBottomPx, "px");
|
|
47
|
+
i0.ɵɵclassProp("is-pressed", ctx_r1.IsBubblePressed)("is-dragging", ctx_r1.IsBubbleDragging);
|
|
48
|
+
i0.ɵɵadvance(4);
|
|
49
|
+
i0.ɵɵconditional(ctx_r1.UnreadCount > 0 ? 4 : -1);
|
|
50
|
+
} }
|
|
51
|
+
function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
52
|
+
i0.ɵɵelementStart(0, "span", 12);
|
|
53
|
+
i0.ɵɵtext(1);
|
|
54
|
+
i0.ɵɵelementEnd();
|
|
55
|
+
} if (rf & 2) {
|
|
56
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
57
|
+
i0.ɵɵadvance();
|
|
58
|
+
i0.ɵɵtextInterpolate(ctx_r1.UnreadCount > 9 ? "9+" : ctx_r1.UnreadCount);
|
|
59
|
+
} }
|
|
60
|
+
function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
61
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
62
|
+
i0.ɵɵelementStart(0, "button", 10);
|
|
63
|
+
i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.Expand()); });
|
|
64
|
+
i0.ɵɵelement(1, "i", 11);
|
|
65
|
+
i0.ɵɵconditionalCreate(2, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_2_Template, 2, 1, "span", 12);
|
|
40
66
|
i0.ɵɵelementEnd();
|
|
41
67
|
} if (rf & 2) {
|
|
42
68
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
69
|
+
i0.ɵɵstyleProp("bottom", ctx_r1.BubbleBottomPx, "px");
|
|
43
70
|
i0.ɵɵadvance(2);
|
|
44
71
|
i0.ɵɵconditional(ctx_r1.UnreadCount > 0 ? 2 : -1);
|
|
45
72
|
} }
|
|
46
|
-
function
|
|
47
|
-
const
|
|
48
|
-
i0.ɵɵelementStart(0, "div",
|
|
49
|
-
i0.ɵɵlistener("mousedown", function
|
|
73
|
+
function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
74
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
75
|
+
i0.ɵɵelementStart(0, "div", 27);
|
|
76
|
+
i0.ɵɵlistener("mousedown", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Conditional_1_Template_div_mousedown_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnResizeStart($event, "left")); });
|
|
50
77
|
i0.ɵɵelementEnd();
|
|
51
|
-
i0.ɵɵelementStart(1, "div",
|
|
52
|
-
i0.ɵɵlistener("mousedown", function
|
|
78
|
+
i0.ɵɵelementStart(1, "div", 28);
|
|
79
|
+
i0.ɵɵlistener("mousedown", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Conditional_1_Template_div_mousedown_1_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnResizeStart($event, "top")); });
|
|
53
80
|
i0.ɵɵelementEnd();
|
|
54
|
-
i0.ɵɵelementStart(2, "div",
|
|
55
|
-
i0.ɵɵlistener("mousedown", function
|
|
81
|
+
i0.ɵɵelementStart(2, "div", 29);
|
|
82
|
+
i0.ɵɵlistener("mousedown", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Conditional_1_Template_div_mousedown_2_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnResizeStart($event, "top-left")); });
|
|
56
83
|
i0.ɵɵelementEnd();
|
|
57
84
|
} }
|
|
58
|
-
function
|
|
59
|
-
const
|
|
60
|
-
i0.ɵɵelementStart(0, "button",
|
|
61
|
-
i0.ɵɵlistener("click", function
|
|
62
|
-
i0.ɵɵelement(1, "i",
|
|
85
|
+
function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
87
|
+
i0.ɵɵelementStart(0, "button", 30);
|
|
88
|
+
i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnOpenFullChatWorkspace()); });
|
|
89
|
+
i0.ɵɵelement(1, "i", 31);
|
|
63
90
|
i0.ɵɵelementEnd();
|
|
64
91
|
} }
|
|
65
|
-
function
|
|
66
|
-
const
|
|
67
|
-
i0.ɵɵelementStart(0, "div",
|
|
68
|
-
i0.ɵɵconditionalCreate(1,
|
|
69
|
-
i0.ɵɵelementStart(2, "div",
|
|
70
|
-
i0.ɵɵelement(4, "i",
|
|
92
|
+
function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
93
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
94
|
+
i0.ɵɵelementStart(0, "div", 13);
|
|
95
|
+
i0.ɵɵconditionalCreate(1, ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Conditional_1_Template, 3, 0);
|
|
96
|
+
i0.ɵɵelementStart(2, "div", 14)(3, "div", 15);
|
|
97
|
+
i0.ɵɵelement(4, "i", 16);
|
|
71
98
|
i0.ɵɵelementStart(5, "span");
|
|
72
99
|
i0.ɵɵtext(6, "AI Assistant");
|
|
73
100
|
i0.ɵɵelementEnd()();
|
|
74
|
-
i0.ɵɵelementStart(7, "div",
|
|
75
|
-
i0.ɵɵlistener("click", function
|
|
76
|
-
i0.ɵɵelement(9, "i",
|
|
101
|
+
i0.ɵɵelementStart(7, "div", 17)(8, "button", 18);
|
|
102
|
+
i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.StartNewConversation()); });
|
|
103
|
+
i0.ɵɵelement(9, "i", 19);
|
|
77
104
|
i0.ɵɵelementEnd();
|
|
78
|
-
i0.ɵɵconditionalCreate(10,
|
|
79
|
-
i0.ɵɵelementStart(11, "button",
|
|
80
|
-
i0.ɵɵlistener("click", function
|
|
81
|
-
i0.ɵɵelement(12, "i",
|
|
105
|
+
i0.ɵɵconditionalCreate(10, ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Conditional_10_Template, 2, 0, "button", 20);
|
|
106
|
+
i0.ɵɵelementStart(11, "button", 21);
|
|
107
|
+
i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleMaximize()); });
|
|
108
|
+
i0.ɵɵelement(12, "i", 22);
|
|
82
109
|
i0.ɵɵelementEnd();
|
|
83
|
-
i0.ɵɵelementStart(13, "button",
|
|
84
|
-
i0.ɵɵlistener("click", function
|
|
85
|
-
i0.ɵɵelement(14, "i",
|
|
110
|
+
i0.ɵɵelementStart(13, "button", 23);
|
|
111
|
+
i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.Collapse()); });
|
|
112
|
+
i0.ɵɵelement(14, "i", 24);
|
|
86
113
|
i0.ɵɵelementEnd()()();
|
|
87
|
-
i0.ɵɵelementStart(15, "div",
|
|
88
|
-
i0.ɵɵlistener("conversationCreated", function
|
|
114
|
+
i0.ɵɵelementStart(15, "div", 25)(16, "mj-conversation-chat-area", 26);
|
|
115
|
+
i0.ɵɵlistener("conversationCreated", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_mj_conversation_chat_area_conversationCreated_16_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnConversationCreated($event)); })("conversationRenamed", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_mj_conversation_chat_area_conversationRenamed_16_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnConversationRenamed($event)); })("pendingMessageConsumed", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_mj_conversation_chat_area_pendingMessageConsumed_16_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnPendingMessageConsumed()); })("openEntityRecord", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_mj_conversation_chat_area_openEntityRecord_16_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnOpenEntityRecord($event)); })("navigationRequest", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_mj_conversation_chat_area_navigationRequest_16_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnNavigationRequest($event)); })("taskClicked", function ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template_mj_conversation_chat_area_taskClicked_16_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTaskClicked($event)); });
|
|
89
116
|
i0.ɵɵelementEnd()()();
|
|
90
117
|
} if (rf & 2) {
|
|
91
118
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
92
|
-
i0.ɵɵstyleProp("width", ctx_r1.State === "maximized" ? null : ctx_r1.PanelWidth, "px")("height", ctx_r1.State === "maximized" ? null : ctx_r1.PanelHeight, "px");
|
|
119
|
+
i0.ɵɵstyleProp("width", ctx_r1.State === "maximized" ? null : ctx_r1.PanelWidth, "px")("height", ctx_r1.State === "maximized" ? null : ctx_r1.PanelHeight, "px")("bottom", ctx_r1.State === "maximized" ? null : ctx_r1.PanelBottomPx, "px");
|
|
93
120
|
i0.ɵɵclassProp("maximized", ctx_r1.State === "maximized");
|
|
94
121
|
i0.ɵɵadvance();
|
|
95
122
|
i0.ɵɵconditional(ctx_r1.State === "expanded" ? 1 : -1);
|
|
@@ -103,13 +130,16 @@ function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template(rf, ctx
|
|
|
103
130
|
i0.ɵɵproperty("environmentId", ctx_r1.EnvironmentId)("currentUser", ctx_r1.CurrentUser)("conversationId", ctx_r1.ConversationId)("conversation", ctx_r1.Conversation)("isNewConversation", ctx_r1.IsNewConversation)("pendingMessage", ctx_r1.PendingMessage)("pendingAttachments", ctx_r1.PendingAttachments)("overlayMode", true)("showExportButton", false)("showShareButton", false)("showArtifactIndicator", false)("appContext", ctx_r1.AppContext)("emptyStateGreeting", ctx_r1.EmptyStateGreeting);
|
|
104
131
|
} }
|
|
105
132
|
function ChatAgentsOverlayComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
106
|
-
i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template,
|
|
107
|
-
i0.ɵɵconditionalCreate(1, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template,
|
|
133
|
+
i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template, 7, 7, "div", 0);
|
|
134
|
+
i0.ɵɵconditionalCreate(1, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template, 3, 3, "button", 1);
|
|
135
|
+
i0.ɵɵconditionalCreate(2, ChatAgentsOverlayComponent_Conditional_0_Conditional_2_Template, 17, 28, "div", 2);
|
|
108
136
|
} if (rf & 2) {
|
|
109
137
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
110
|
-
i0.ɵɵconditional(ctx_r1.State === "collapsed" ? 0 : -1);
|
|
138
|
+
i0.ɵɵconditional(ctx_r1.State === "collapsed" && !ctx_r1.IsHidden ? 0 : -1);
|
|
139
|
+
i0.ɵɵadvance();
|
|
140
|
+
i0.ɵɵconditional(ctx_r1.State === "collapsed" && ctx_r1.IsHidden ? 1 : -1);
|
|
111
141
|
i0.ɵɵadvance();
|
|
112
|
-
i0.ɵɵconditional(ctx_r1.State === "expanded" || ctx_r1.State === "maximized" ?
|
|
142
|
+
i0.ɵɵconditional(ctx_r1.State === "expanded" || ctx_r1.State === "maximized" ? 2 : -1);
|
|
113
143
|
} }
|
|
114
144
|
export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
115
145
|
cdr = inject(ChangeDetectorRef);
|
|
@@ -124,6 +154,15 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
124
154
|
static MIN_HEIGHT = 350;
|
|
125
155
|
static MAX_WIDTH = 900;
|
|
126
156
|
static MAX_HEIGHT = 1000;
|
|
157
|
+
// --- Bubble drag constants ---
|
|
158
|
+
/** Default `bottom` for both bubble and panel (matches CSS 1.5rem). */
|
|
159
|
+
static BASE_BOTTOM_PX = 24;
|
|
160
|
+
/** Floating bubble diameter in pixels (matches CSS 3.5rem). */
|
|
161
|
+
static BUBBLE_SIZE_PX = 56;
|
|
162
|
+
/** Minimum gap to keep between the overlay and the viewport top edge. */
|
|
163
|
+
static VIEWPORT_TOP_PADDING_PX = 16;
|
|
164
|
+
/** Mousedown-to-mousemove distance that promotes a click into a drag. */
|
|
165
|
+
static BUBBLE_DRAG_THRESHOLD_PX = 5;
|
|
127
166
|
// --- Inputs ---
|
|
128
167
|
/** Controls external visibility (e.g., parent hides overlay on chat route) */
|
|
129
168
|
_IsVisible = true;
|
|
@@ -146,6 +185,13 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
146
185
|
AppContext = null;
|
|
147
186
|
/** Greeting message shown in the empty state when no conversation is active */
|
|
148
187
|
EmptyStateGreeting = 'How can I help you?';
|
|
188
|
+
/**
|
|
189
|
+
* Pixels reserved at the top of the viewport that the bubble and panel must not
|
|
190
|
+
* cross. Set this from the host app to the height of any fixed top chrome (e.g.
|
|
191
|
+
* Explorer's shell-header). Defaults to 0 — generic apps without top chrome
|
|
192
|
+
* keep the full viewport available.
|
|
193
|
+
*/
|
|
194
|
+
TopBoundaryPx = 0;
|
|
149
195
|
// --- Outputs ---
|
|
150
196
|
/** Emitted when the overlay visibility changes */
|
|
151
197
|
VisibilityChanged = new EventEmitter();
|
|
@@ -167,6 +213,26 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
167
213
|
/** Panel dimensions (persisted via UserInfoEngine) */
|
|
168
214
|
PanelWidth = ChatAgentsOverlayComponent.DEFAULT_WIDTH;
|
|
169
215
|
PanelHeight = ChatAgentsOverlayComponent.DEFAULT_HEIGHT;
|
|
216
|
+
/**
|
|
217
|
+
* Pixels the floating bubble has been dragged up from its default
|
|
218
|
+
* bottom-right corner position. Always >= 0; clamping at render time
|
|
219
|
+
* keeps the bubble on-screen even after a viewport resize.
|
|
220
|
+
*/
|
|
221
|
+
BubbleOffsetY = 0;
|
|
222
|
+
/** True while the user is actively dragging the bubble; used to swap cursor + suppress click. */
|
|
223
|
+
IsBubbleDragging = false;
|
|
224
|
+
/**
|
|
225
|
+
* True from mousedown until mouseup on the bubble, regardless of whether the
|
|
226
|
+
* gesture became a drag. Used to give immediate "I'm being held" feedback so
|
|
227
|
+
* the user can see drag is possible even before crossing the move threshold.
|
|
228
|
+
*/
|
|
229
|
+
IsBubblePressed = false;
|
|
230
|
+
/**
|
|
231
|
+
* When true, the floating bubble is hidden and replaced by a thin sliver
|
|
232
|
+
* flush with the right edge of the viewport. Persisted across sessions via
|
|
233
|
+
* OverlayPrefs.bubbleHidden. Clicking the sliver restores the bubble.
|
|
234
|
+
*/
|
|
235
|
+
IsHidden = false;
|
|
170
236
|
/** Active conversation ID managed locally */
|
|
171
237
|
_conversationId = null;
|
|
172
238
|
get ConversationId() {
|
|
@@ -187,10 +253,19 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
187
253
|
resizeStartY = 0;
|
|
188
254
|
resizeStartWidth = 0;
|
|
189
255
|
resizeStartHeight = 0;
|
|
256
|
+
/** Bubble drag state */
|
|
257
|
+
bubbleDragStartMouseY = 0;
|
|
258
|
+
bubbleDragStartOffset = 0;
|
|
259
|
+
/** True once the pointer has moved past BUBBLE_DRAG_THRESHOLD_PX; suppresses the implicit click. */
|
|
260
|
+
bubbleDragMoved = false;
|
|
261
|
+
/** ID of the pointer currently driving the drag — guards against multi-touch confusion. */
|
|
262
|
+
activeBubblePointerId = null;
|
|
263
|
+
/** Element that captured the pointer; needed to release capture on end/cancel. */
|
|
264
|
+
bubbleCaptureTarget = null;
|
|
190
265
|
// --- Lifecycle ---
|
|
191
266
|
ngOnInit() {
|
|
192
267
|
this.resolveDefaults();
|
|
193
|
-
this.
|
|
268
|
+
this.loadPreferences();
|
|
194
269
|
this.subscribeToBridgeEvents();
|
|
195
270
|
this.subscribeToToolEvents();
|
|
196
271
|
}
|
|
@@ -198,6 +273,7 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
198
273
|
this.destroy$.next();
|
|
199
274
|
this.destroy$.complete();
|
|
200
275
|
this.removeResizeListeners();
|
|
276
|
+
this.removeBubbleDragListeners();
|
|
201
277
|
}
|
|
202
278
|
// --- Public Methods ---
|
|
203
279
|
/** Toggle between collapsed and expanded states */
|
|
@@ -211,6 +287,12 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
211
287
|
}
|
|
212
288
|
/** Expand the overlay to show the chat panel */
|
|
213
289
|
Expand() {
|
|
290
|
+
// Expanding implies the user wants the chat visible — clear any hidden
|
|
291
|
+
// state so collapse returns to the bubble, not back to the sliver.
|
|
292
|
+
if (this.IsHidden) {
|
|
293
|
+
this.IsHidden = false;
|
|
294
|
+
this.savePreferences();
|
|
295
|
+
}
|
|
214
296
|
this.State = 'expanded';
|
|
215
297
|
this.UnreadCount = 0;
|
|
216
298
|
this.bridge.NotifyOverlayActive(true);
|
|
@@ -290,6 +372,29 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
290
372
|
this.emitConversationSwitched(prevId, null);
|
|
291
373
|
this.cdr.detectChanges();
|
|
292
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* Hide the floating bubble — leaves a thin sliver on the right edge as the
|
|
377
|
+
* only affordance to bring it back. Invoked from the small "×" pill that
|
|
378
|
+
* appears on hover. Stops propagation so the bubble's own click handler
|
|
379
|
+
* doesn't fire and toggle the panel open.
|
|
380
|
+
*/
|
|
381
|
+
Hide(event) {
|
|
382
|
+
event.stopPropagation();
|
|
383
|
+
event.preventDefault();
|
|
384
|
+
if (this.IsHidden)
|
|
385
|
+
return;
|
|
386
|
+
this.IsHidden = true;
|
|
387
|
+
this.savePreferences();
|
|
388
|
+
this.cdr.detectChanges();
|
|
389
|
+
}
|
|
390
|
+
/** Restore the floating bubble after it was hidden. Triggered by clicking the sliver. */
|
|
391
|
+
Show() {
|
|
392
|
+
if (!this.IsHidden)
|
|
393
|
+
return;
|
|
394
|
+
this.IsHidden = false;
|
|
395
|
+
this.savePreferences();
|
|
396
|
+
this.cdr.detectChanges();
|
|
397
|
+
}
|
|
293
398
|
/** Increment unread badge (called externally when messages arrive while collapsed) */
|
|
294
399
|
IncrementUnread() {
|
|
295
400
|
if (this.State === 'collapsed') {
|
|
@@ -330,7 +435,7 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
330
435
|
this.isResizing = false;
|
|
331
436
|
this.resizeEdge = null;
|
|
332
437
|
this.removeResizeListeners();
|
|
333
|
-
this.
|
|
438
|
+
this.savePreferences();
|
|
334
439
|
};
|
|
335
440
|
removeResizeListeners() {
|
|
336
441
|
document.removeEventListener('mousemove', this.onResizeMove);
|
|
@@ -342,6 +447,123 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
342
447
|
clampHeight(value) {
|
|
343
448
|
return Math.max(ChatAgentsOverlayComponent.MIN_HEIGHT, Math.min(ChatAgentsOverlayComponent.MAX_HEIGHT, value));
|
|
344
449
|
}
|
|
450
|
+
// --- Bubble Drag Methods (Pointer Events — unified mouse / touch / pen) ---
|
|
451
|
+
/**
|
|
452
|
+
* Start tracking a potential bubble drag. We don't enter drag mode until
|
|
453
|
+
* the pointer moves past BUBBLE_DRAG_THRESHOLD_PX — releasing before that
|
|
454
|
+
* threshold is treated as a normal click/tap and opens the chat (via Toggle()).
|
|
455
|
+
*
|
|
456
|
+
* Pointer Events (not mousedown) so the same code path serves desktop mouse,
|
|
457
|
+
* touch on phones/tablets, and pen input. setPointerCapture keeps the gesture
|
|
458
|
+
* tied to this element even if the finger or cursor strays off the bubble.
|
|
459
|
+
*/
|
|
460
|
+
OnBubblePointerDown(event) {
|
|
461
|
+
// Mouse: respect primary-button only. Touch/pen: button is always 0, so this passes naturally.
|
|
462
|
+
if (event.pointerType === 'mouse' && event.button !== 0)
|
|
463
|
+
return;
|
|
464
|
+
// Don't start a second drag while one is in flight (e.g. second finger on touch).
|
|
465
|
+
if (this.activeBubblePointerId !== null)
|
|
466
|
+
return;
|
|
467
|
+
event.preventDefault();
|
|
468
|
+
const target = event.currentTarget;
|
|
469
|
+
target.setPointerCapture(event.pointerId);
|
|
470
|
+
this.bubbleCaptureTarget = target;
|
|
471
|
+
this.activeBubblePointerId = event.pointerId;
|
|
472
|
+
this.bubbleDragStartMouseY = event.clientY;
|
|
473
|
+
this.bubbleDragStartOffset = this.BubbleOffsetY;
|
|
474
|
+
this.bubbleDragMoved = false;
|
|
475
|
+
this.IsBubblePressed = true;
|
|
476
|
+
this.cdr.detectChanges();
|
|
477
|
+
document.addEventListener('pointermove', this.onBubbleDragMove);
|
|
478
|
+
document.addEventListener('pointerup', this.onBubbleDragEnd);
|
|
479
|
+
document.addEventListener('pointercancel', this.onBubbleDragEnd);
|
|
480
|
+
}
|
|
481
|
+
onBubbleDragMove = (event) => {
|
|
482
|
+
if (event.pointerId !== this.activeBubblePointerId)
|
|
483
|
+
return;
|
|
484
|
+
const deltaY = this.bubbleDragStartMouseY - event.clientY; // dragging up = positive
|
|
485
|
+
if (!this.bubbleDragMoved) {
|
|
486
|
+
if (Math.abs(deltaY) < ChatAgentsOverlayComponent.BUBBLE_DRAG_THRESHOLD_PX)
|
|
487
|
+
return;
|
|
488
|
+
this.bubbleDragMoved = true;
|
|
489
|
+
this.IsBubbleDragging = true;
|
|
490
|
+
}
|
|
491
|
+
this.BubbleOffsetY = this.clampBubbleOffsetY(this.bubbleDragStartOffset + deltaY);
|
|
492
|
+
this.cdr.detectChanges();
|
|
493
|
+
};
|
|
494
|
+
onBubbleDragEnd = (event) => {
|
|
495
|
+
if (event.pointerId !== this.activeBubblePointerId)
|
|
496
|
+
return;
|
|
497
|
+
this.removeBubbleDragListeners();
|
|
498
|
+
if (this.bubbleCaptureTarget) {
|
|
499
|
+
// Browser may have implicitly released capture on pointerup already (per the
|
|
500
|
+
// Pointer Events spec). releasePointerCapture throws in that race; safe to ignore.
|
|
501
|
+
try {
|
|
502
|
+
this.bubbleCaptureTarget.releasePointerCapture(event.pointerId);
|
|
503
|
+
}
|
|
504
|
+
catch { /* noop */ }
|
|
505
|
+
}
|
|
506
|
+
this.bubbleCaptureTarget = null;
|
|
507
|
+
this.activeBubblePointerId = null;
|
|
508
|
+
const wasDragged = this.bubbleDragMoved;
|
|
509
|
+
const wasCancelled = event.type === 'pointercancel';
|
|
510
|
+
this.bubbleDragMoved = false;
|
|
511
|
+
this.IsBubbleDragging = false;
|
|
512
|
+
this.IsBubblePressed = false;
|
|
513
|
+
if (wasDragged) {
|
|
514
|
+
this.savePreferences();
|
|
515
|
+
this.cdr.detectChanges();
|
|
516
|
+
}
|
|
517
|
+
else if (!wasCancelled) {
|
|
518
|
+
this.Toggle();
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
this.cdr.detectChanges();
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
removeBubbleDragListeners() {
|
|
525
|
+
document.removeEventListener('pointermove', this.onBubbleDragMove);
|
|
526
|
+
document.removeEventListener('pointerup', this.onBubbleDragEnd);
|
|
527
|
+
document.removeEventListener('pointercancel', this.onBubbleDragEnd);
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Reserved space at the top of the viewport — host-supplied chrome plus
|
|
531
|
+
* the padding gap we always keep above the bubble/panel.
|
|
532
|
+
*/
|
|
533
|
+
get topReservedPx() {
|
|
534
|
+
return Math.max(0, this.TopBoundaryPx) + ChatAgentsOverlayComponent.VIEWPORT_TOP_PADDING_PX;
|
|
535
|
+
}
|
|
536
|
+
/** Clamp the offset so the bubble stays fully visible below the top boundary. */
|
|
537
|
+
clampBubbleOffsetY(value) {
|
|
538
|
+
const maxOffset = window.innerHeight
|
|
539
|
+
- ChatAgentsOverlayComponent.BUBBLE_SIZE_PX
|
|
540
|
+
- ChatAgentsOverlayComponent.BASE_BOTTOM_PX
|
|
541
|
+
- this.topReservedPx;
|
|
542
|
+
return Math.max(0, Math.min(Math.max(0, maxOffset), value));
|
|
543
|
+
}
|
|
544
|
+
// --- Render Position Getters ---
|
|
545
|
+
/** Effective `bottom` (px) for the floating bubble, clamped to the current viewport. */
|
|
546
|
+
get BubbleBottomPx() {
|
|
547
|
+
const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;
|
|
548
|
+
const max = window.innerHeight
|
|
549
|
+
- ChatAgentsOverlayComponent.BUBBLE_SIZE_PX
|
|
550
|
+
- this.topReservedPx;
|
|
551
|
+
return Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, Math.min(ideal, Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, max)));
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Effective `bottom` (px) for the expanded panel. Anchors to the bubble's
|
|
555
|
+
* current bottom edge so the panel grows up from where the user parked the
|
|
556
|
+
* bubble, but clamps downward whenever the panel would otherwise extend
|
|
557
|
+
* past the viewport's top boundary — that's the "reposition lower so the
|
|
558
|
+
* chat interface stays visible" behavior.
|
|
559
|
+
*/
|
|
560
|
+
get PanelBottomPx() {
|
|
561
|
+
const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;
|
|
562
|
+
const maxBottomForVisibility = window.innerHeight
|
|
563
|
+
- this.PanelHeight
|
|
564
|
+
- this.topReservedPx;
|
|
565
|
+
return Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, Math.min(ideal, maxBottomForVisibility));
|
|
566
|
+
}
|
|
345
567
|
// --- Private Methods ---
|
|
346
568
|
/** Auto-resolve CurrentUser and EnvironmentId from Metadata when not provided as inputs */
|
|
347
569
|
resolveDefaults() {
|
|
@@ -353,8 +575,8 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
353
575
|
this.EnvironmentId = MJEnvironmentEntityExtended.DefaultEnvironmentID;
|
|
354
576
|
}
|
|
355
577
|
}
|
|
356
|
-
/** Load saved panel size from UserInfoEngine */
|
|
357
|
-
|
|
578
|
+
/** Load saved panel size and bubble position from UserInfoEngine */
|
|
579
|
+
loadPreferences() {
|
|
358
580
|
try {
|
|
359
581
|
const engine = UserInfoEngine.Instance;
|
|
360
582
|
const raw = engine.GetSetting(ChatAgentsOverlayComponent.SIZE_SETTING_KEY);
|
|
@@ -362,17 +584,25 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
362
584
|
const prefs = JSON.parse(raw);
|
|
363
585
|
this.PanelWidth = this.clampWidth(prefs.width);
|
|
364
586
|
this.PanelHeight = this.clampHeight(prefs.height);
|
|
587
|
+
if (typeof prefs.bubbleOffsetY === 'number') {
|
|
588
|
+
this.BubbleOffsetY = Math.max(0, prefs.bubbleOffsetY);
|
|
589
|
+
}
|
|
590
|
+
if (typeof prefs.bubbleHidden === 'boolean') {
|
|
591
|
+
this.IsHidden = prefs.bubbleHidden;
|
|
592
|
+
}
|
|
365
593
|
}
|
|
366
594
|
}
|
|
367
595
|
catch {
|
|
368
596
|
// Use defaults on error
|
|
369
597
|
}
|
|
370
598
|
}
|
|
371
|
-
/** Persist panel size to UserInfoEngine (debounced) */
|
|
372
|
-
|
|
599
|
+
/** Persist panel size and bubble position to UserInfoEngine (debounced) */
|
|
600
|
+
savePreferences() {
|
|
373
601
|
const prefs = {
|
|
374
602
|
width: this.PanelWidth,
|
|
375
|
-
height: this.PanelHeight
|
|
603
|
+
height: this.PanelHeight,
|
|
604
|
+
bubbleOffsetY: this.BubbleOffsetY,
|
|
605
|
+
bubbleHidden: this.IsHidden
|
|
376
606
|
};
|
|
377
607
|
UserInfoEngine.Instance.SetSettingDebounced(ChatAgentsOverlayComponent.SIZE_SETTING_KEY, JSON.stringify(prefs));
|
|
378
608
|
}
|
|
@@ -385,6 +615,16 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
385
615
|
this.handleSwitchToOverlay(event);
|
|
386
616
|
}
|
|
387
617
|
});
|
|
618
|
+
// Allow arbitrary callers (Form Builder cockpit, etc.) to ask the
|
|
619
|
+
// overlay to expand. Idempotent if we're already expanded —
|
|
620
|
+
// Expand() is safe to call in any state.
|
|
621
|
+
this.bridge.ExpandOverlayRequested$
|
|
622
|
+
.pipe(takeUntil(this.destroy$))
|
|
623
|
+
.subscribe(() => {
|
|
624
|
+
if (this.State === 'collapsed') {
|
|
625
|
+
this.Expand();
|
|
626
|
+
}
|
|
627
|
+
});
|
|
388
628
|
this.bridge.ActiveConversationID$
|
|
389
629
|
.pipe(takeUntil(this.destroy$))
|
|
390
630
|
.subscribe((id) => {
|
|
@@ -424,15 +664,15 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
424
664
|
});
|
|
425
665
|
}
|
|
426
666
|
static ɵfac = /*@__PURE__*/ (() => { let ɵChatAgentsOverlayComponent_BaseFactory; return function ChatAgentsOverlayComponent_Factory(__ngFactoryType__) { return (ɵChatAgentsOverlayComponent_BaseFactory || (ɵChatAgentsOverlayComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ChatAgentsOverlayComponent)))(__ngFactoryType__ || ChatAgentsOverlayComponent); }; })();
|
|
427
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ChatAgentsOverlayComponent, selectors: [["mj-chat-agents-overlay"]], inputs: { IsVisible: "IsVisible", CurrentUser: "CurrentUser", EnvironmentId: "EnvironmentId", AppContext: "AppContext", EmptyStateGreeting: "EmptyStateGreeting" }, outputs: { VisibilityChanged: "VisibilityChanged", ToolExecuted: "ToolExecuted", ConversationSwitched: "ConversationSwitched", OpenFullChatWorkspace: "OpenFullChatWorkspace", NavigationRequested: "NavigationRequested", OpenEntityRecord: "OpenEntityRecord", TaskClicked: "TaskClicked" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [["title", "Open
|
|
428
|
-
i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Template,
|
|
667
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ChatAgentsOverlayComponent, selectors: [["mj-chat-agents-overlay"]], inputs: { IsVisible: "IsVisible", CurrentUser: "CurrentUser", EnvironmentId: "EnvironmentId", AppContext: "AppContext", EmptyStateGreeting: "EmptyStateGreeting", TopBoundaryPx: "TopBoundaryPx" }, outputs: { VisibilityChanged: "VisibilityChanged", ToolExecuted: "ToolExecuted", ConversationSwitched: "ConversationSwitched", OpenFullChatWorkspace: "OpenFullChatWorkspace", NavigationRequested: "NavigationRequested", OpenEntityRecord: "OpenEntityRecord", TaskClicked: "TaskClicked" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[1, "chat-overlay-bubble", 3, "is-pressed", "is-dragging", "bottom"], ["type", "button", "title", "Open chat", "aria-label", "Open chat", 1, "chat-overlay-sliver", 3, "bottom"], [1, "chat-overlay-panel", 3, "maximized", "width", "height", "bottom"], [1, "chat-overlay-bubble", 3, "pointerdown"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-up", "chat-overlay-bubble-arrow", "chat-overlay-bubble-arrow-up"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down", "chat-overlay-bubble-arrow", "chat-overlay-bubble-arrow-down"], [1, "fa-solid", "fa-comments", "chat-overlay-bubble-icon"], [1, "chat-overlay-badge"], ["type", "button", "title", "Hide chat \u2014 a thin sliver will remain on the right edge", "aria-label", "Hide chat overlay", 1, "chat-overlay-bubble-close", 3, "pointerdown", "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], ["type", "button", "title", "Open chat", "aria-label", "Open chat", 1, "chat-overlay-sliver", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-comments", "chat-overlay-sliver-icon"], [1, "chat-overlay-badge", "chat-overlay-sliver-badge"], [1, "chat-overlay-panel"], [1, "chat-overlay-header"], [1, "chat-overlay-title"], [1, "fa-solid", "fa-robot"], [1, "chat-overlay-header-actions"], ["title", "New conversation", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-plus"], ["title", "Open in full chat workspace", 1, "chat-overlay-header-btn"], [1, "chat-overlay-header-btn", 3, "click", "title"], [1, "fa-solid"], ["title", "Minimize", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-minus"], [1, "chat-overlay-body"], [3, "conversationCreated", "conversationRenamed", "pendingMessageConsumed", "openEntityRecord", "navigationRequest", "taskClicked", "environmentId", "currentUser", "conversationId", "conversation", "isNewConversation", "pendingMessage", "pendingAttachments", "overlayMode", "showExportButton", "showShareButton", "showArtifactIndicator", "appContext", "emptyStateGreeting"], [1, "resize-handle", "resize-left", 3, "mousedown"], [1, "resize-handle", "resize-top", 3, "mousedown"], [1, "resize-handle", "resize-top-left", 3, "mousedown"], ["title", "Open in full chat workspace", 1, "chat-overlay-header-btn", 3, "click"], [1, "fa-solid", "fa-up-right-from-square"]], template: function ChatAgentsOverlayComponent_Template(rf, ctx) { if (rf & 1) {
|
|
668
|
+
i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Template, 3, 3);
|
|
429
669
|
} if (rf & 2) {
|
|
430
670
|
i0.ɵɵconditional(ctx.IsVisible ? 0 : -1);
|
|
431
|
-
} }, dependencies: [i1.ConversationChatAreaComponent], styles: ["\n\n\n\n\n\n\n\n\n.chat-overlay-bubble[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n width: 3.5rem;\n height: 3.5rem;\n border-radius: 50%;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n z-index:
|
|
671
|
+
} }, dependencies: [i1.ConversationChatAreaComponent], styles: ["\n\n\n\n\n\n\n\n\n.chat-overlay-bubble[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n width: 3.5rem;\n height: 3.5rem;\n border-radius: 50%;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n z-index: 2147483647;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: _ngcontent-%COMP%_overlayBubbleIn 0.3s ease;\n \n\n\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n\n\n\n\n\n\n.chat-overlay-bubble-arrow[_ngcontent-%COMP%] {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n color: var(--mj-text-muted);\n font-size: 0.65rem;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.18s ease;\n}\n\n.chat-overlay-bubble-arrow-up[_ngcontent-%COMP%] {\n top: -0.85rem;\n}\n\n.chat-overlay-bubble-arrow-down[_ngcontent-%COMP%] {\n bottom: -0.85rem;\n}\n\n\n\n.chat-overlay-bubble[_ngcontent-%COMP%]:hover .chat-overlay-bubble-arrow[_ngcontent-%COMP%], \n.chat-overlay-bubble.is-pressed[_ngcontent-%COMP%] .chat-overlay-bubble-arrow[_ngcontent-%COMP%], \n.chat-overlay-bubble.is-dragging[_ngcontent-%COMP%] .chat-overlay-bubble-arrow[_ngcontent-%COMP%] {\n opacity: 0.85;\n}\n\n\n\n\n\n@media (hover: none) {\n .chat-overlay-bubble-arrow[_ngcontent-%COMP%] {\n opacity: 0.5;\n }\n}\n\n.chat-overlay-bubble[_ngcontent-%COMP%]:hover {\n transform: scale(1.08);\n box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);\n}\n\n\n\n\n.chat-overlay-bubble.is-pressed[_ngcontent-%COMP%] {\n cursor: grabbing;\n transform: scale(0.94);\n transition: transform 0.08s ease;\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.25),\n 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n\n\n.chat-overlay-bubble.is-dragging[_ngcontent-%COMP%] {\n cursor: grabbing;\n transform: scale(1.04);\n transition: none;\n box-shadow:\n 0 8px 28px rgba(0, 0, 0, 0.35),\n 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n@keyframes _ngcontent-%COMP%_overlayBubbleIn {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.chat-overlay-bubble-icon[_ngcontent-%COMP%] {\n font-size: 1.3rem;\n}\n\n.chat-overlay-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 1.2rem;\n height: 1.2rem;\n border-radius: 9999px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 0.65rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 0.25rem;\n border: 2px solid var(--mj-bg-page);\n}\n\n\n\n\n\n.chat-overlay-bubble-close[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n \n\n\n\n right: 100%;\n transform: translateY(-50%);\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border-radius: 9999px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-strong);\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.65rem;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;\n}\n\n.chat-overlay-bubble[_ngcontent-%COMP%]:hover .chat-overlay-bubble-close[_ngcontent-%COMP%] {\n opacity: 1;\n pointer-events: auto;\n}\n\n.chat-overlay-bubble-close[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-brand-primary);\n transform: translateY(-50%) scale(1.08);\n}\n\n\n\n@media (hover: none) {\n .chat-overlay-bubble-close[_ngcontent-%COMP%] {\n opacity: 0.7;\n pointer-events: auto;\n }\n}\n\n\n\n.chat-overlay-bubble.is-dragging[_ngcontent-%COMP%] .chat-overlay-bubble-close[_ngcontent-%COMP%], \n.chat-overlay-bubble.is-pressed[_ngcontent-%COMP%] .chat-overlay-bubble-close[_ngcontent-%COMP%] {\n opacity: 0;\n pointer-events: none;\n}\n\n\n\n\n.chat-overlay-sliver[_ngcontent-%COMP%] {\n position: fixed;\n right: 0;\n width: 0.875rem; \n\n height: 5rem; \n\n padding: 0;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px 0 0 8px;\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n z-index: 2147483647;\n transition: width 0.18s ease, background 0.15s ease;\n animation: _ngcontent-%COMP%_overlayBubbleIn 0.25s ease;\n}\n\n.chat-overlay-sliver[_ngcontent-%COMP%]:hover {\n width: 1.5rem; \n\n background: color-mix(in srgb, var(--mj-brand-primary) 85%, white);\n}\n\n.chat-overlay-sliver-icon[_ngcontent-%COMP%] {\n font-size: 0.55rem;\n opacity: 0.95;\n}\n\n.chat-overlay-sliver[_ngcontent-%COMP%]:hover .chat-overlay-sliver-icon[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n}\n\n.chat-overlay-sliver-badge[_ngcontent-%COMP%] {\n \n\n top: -6px;\n right: -6px;\n}\n\n\n\n\n.chat-overlay-panel[_ngcontent-%COMP%] {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n border-radius: 12px;\n background: var(--mj-bg-surface);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-border-strong));\n box-shadow:\n 0 8px 32px rgba(0, 0, 0, 0.3),\n 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 2147483647;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: _ngcontent-%COMP%_overlayPanelIn 0.25s ease;\n max-height: calc(100vh - 3rem);\n max-width: calc(100vw - 3rem);\n}\n\n.chat-overlay-panel.maximized[_ngcontent-%COMP%] {\n bottom: 1rem;\n right: 1rem;\n width: calc(100vw - 2rem) !important;\n height: calc(100vh - 2rem) !important;\n max-height: none;\n max-width: none;\n border-radius: 12px;\n}\n\n@keyframes _ngcontent-%COMP%_overlayPanelIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(10px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n\n\n\n.resize-handle[_ngcontent-%COMP%] {\n position: absolute;\n z-index: 2;\n}\n\n.resize-left[_ngcontent-%COMP%] {\n left: -3px;\n top: 20px;\n bottom: 20px;\n width: 6px;\n cursor: ew-resize;\n}\n\n.resize-top[_ngcontent-%COMP%] {\n top: -3px;\n left: 20px;\n right: 20px;\n height: 6px;\n cursor: ns-resize;\n}\n\n.resize-top-left[_ngcontent-%COMP%] {\n top: -4px;\n left: -4px;\n width: 16px;\n height: 16px;\n cursor: nwse-resize;\n}\n\n.resize-handle[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 3px;\n}\n\n\n\n\n.chat-overlay-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.6rem 0.75rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.chat-overlay-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.chat-overlay-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.chat-overlay-header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.25rem;\n}\n\n.chat-overlay-header-btn[_ngcontent-%COMP%] {\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 6px;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n transition: all 0.15s ease;\n}\n\n.chat-overlay-header-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n\n\n.chat-overlay-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.chat-overlay-body[_ngcontent-%COMP%] mj-conversation-chat-area[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n\n\n\n\n\n\n@media (max-width: 640px) {\n .chat-overlay-panel[_ngcontent-%COMP%] {\n bottom: 0 !important;\n right: 0;\n width: 100% !important;\n height: 100vh !important;\n max-height: 100vh;\n border-radius: 0;\n }\n\n .chat-overlay-bubble[_ngcontent-%COMP%] {\n \n\n\n\n\n width: 2.75rem;\n height: 2.75rem;\n right: 1rem;\n }\n\n .chat-overlay-bubble-icon[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n }\n\n .chat-overlay-badge[_ngcontent-%COMP%] {\n min-width: 1rem;\n height: 1rem;\n font-size: 0.6rem;\n top: -3px;\n right: -3px;\n }\n\n .resize-handle[_ngcontent-%COMP%] {\n display: none;\n }\n\n \n\n .chat-overlay-sliver[_ngcontent-%COMP%] {\n width: 1.25rem;\n height: 4.5rem;\n }\n}"] });
|
|
432
672
|
}
|
|
433
673
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ChatAgentsOverlayComponent, [{
|
|
434
674
|
type: Component,
|
|
435
|
-
args: [{ standalone: false, selector: 'mj-chat-agents-overlay', template: "@if (IsVisible) {\n <!-- Floating Button (collapsed state) -->\n @if (State === 'collapsed') {\n <div class=\"chat-overlay-bubble\" (click)=\"Toggle()\" title=\"Open Chat\">\n <i class=\"fa-solid fa-comments chat-overlay-bubble-icon\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n </div>\n }\n\n <!-- Expanded / Maximized Chat Panel -->\n @if (State === 'expanded' || State === 'maximized') {\n <div class=\"chat-overlay-panel\"\n [class.maximized]=\"State === 'maximized'\"\n [style.width.px]=\"State === 'maximized' ? null : PanelWidth\"\n [style.height.px]=\"State === 'maximized' ? null : PanelHeight\">\n\n <!-- Resize handles (only in expanded, not maximized) -->\n @if (State === 'expanded') {\n <div class=\"resize-handle resize-left\"\n (mousedown)=\"OnResizeStart($event, 'left')\"></div>\n <div class=\"resize-handle resize-top\"\n (mousedown)=\"OnResizeStart($event, 'top')\"></div>\n <div class=\"resize-handle resize-top-left\"\n (mousedown)=\"OnResizeStart($event, 'top-left')\"></div>\n }\n\n <!-- Panel Header -->\n <div class=\"chat-overlay-header\">\n <div class=\"chat-overlay-title\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>AI Assistant</span>\n </div>\n <div class=\"chat-overlay-header-actions\">\n <button\n class=\"chat-overlay-header-btn\"\n title=\"New conversation\"\n (click)=\"StartNewConversation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n @if (ConversationId) {\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Open in full chat workspace\"\n (click)=\"OnOpenFullChatWorkspace()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n }\n <button\n class=\"chat-overlay-header-btn\"\n [title]=\"State === 'maximized' ? 'Restore size' : 'Maximize'\"\n (click)=\"ToggleMaximize()\">\n <i class=\"fa-solid\" [class.fa-expand]=\"State !== 'maximized'\" [class.fa-compress]=\"State === 'maximized'\"></i>\n </button>\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Minimize\"\n (click)=\"Collapse()\">\n <i class=\"fa-solid fa-minus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Chat Content \u2014 wraps conversation-chat-area -->\n <div class=\"chat-overlay-body\">\n <mj-conversation-chat-area\n [environmentId]=\"EnvironmentId\"\n [currentUser]=\"CurrentUser\"\n [conversationId]=\"ConversationId\"\n [conversation]=\"Conversation\"\n [isNewConversation]=\"IsNewConversation\"\n [pendingMessage]=\"PendingMessage\"\n [pendingAttachments]=\"PendingAttachments\"\n [overlayMode]=\"true\"\n [showExportButton]=\"false\"\n [showShareButton]=\"false\"\n [showArtifactIndicator]=\"false\"\n [appContext]=\"AppContext\"\n [emptyStateGreeting]=\"EmptyStateGreeting\"\n (conversationCreated)=\"OnConversationCreated($event)\"\n (conversationRenamed)=\"OnConversationRenamed($event)\"\n (pendingMessageConsumed)=\"OnPendingMessageConsumed()\"\n (openEntityRecord)=\"OnOpenEntityRecord($event)\"\n (navigationRequest)=\"OnNavigationRequest($event)\"\n (taskClicked)=\"OnTaskClicked($event)\"\n ></mj-conversation-chat-area>\n </div>\n </div>\n }\n}\n", styles: ["/* ============================================================\n Chat Overlay \u2014 Floating Bubble + Expanding Panel\n All colors use MJ design tokens (--mj-* CSS variables).\n ============================================================ */\n\n/* --- Floating Bubble (collapsed state) --- */\n\n.chat-overlay-bubble {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n width: 3.5rem;\n height: 3.5rem;\n border-radius: 50%;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n z-index: 999;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: overlayBubbleIn 0.3s ease;\n}\n\n.chat-overlay-bubble:hover {\n transform: scale(1.08);\n box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);\n}\n\n@keyframes overlayBubbleIn {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.chat-overlay-bubble-icon {\n font-size: 1.3rem;\n}\n\n.chat-overlay-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 1.2rem;\n height: 1.2rem;\n border-radius: 9999px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 0.65rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 0.25rem;\n border: 2px solid var(--mj-bg-page);\n}\n\n/* --- Expanded Panel --- */\n\n.chat-overlay-panel {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n border-radius: 12px;\n background: var(--mj-bg-surface);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-border-strong));\n box-shadow:\n 0 8px 32px rgba(0, 0, 0, 0.3),\n 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 999;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: overlayPanelIn 0.25s ease;\n max-height: calc(100vh - 3rem);\n max-width: calc(100vw - 3rem);\n}\n\n.chat-overlay-panel.maximized {\n bottom: 1rem;\n right: 1rem;\n width: calc(100vw - 2rem) !important;\n height: calc(100vh - 2rem) !important;\n max-height: none;\n max-width: none;\n border-radius: 12px;\n}\n\n@keyframes overlayPanelIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(10px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* --- Resize Handles --- */\n\n.resize-handle {\n position: absolute;\n z-index: 2;\n}\n\n.resize-left {\n left: -3px;\n top: 20px;\n bottom: 20px;\n width: 6px;\n cursor: ew-resize;\n}\n\n.resize-top {\n top: -3px;\n left: 20px;\n right: 20px;\n height: 6px;\n cursor: ns-resize;\n}\n\n.resize-top-left {\n top: -4px;\n left: -4px;\n width: 16px;\n height: 16px;\n cursor: nwse-resize;\n}\n\n.resize-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 3px;\n}\n\n/* --- Panel Header --- */\n\n.chat-overlay-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.6rem 0.75rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.chat-overlay-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.chat-overlay-title i {\n color: var(--mj-brand-primary);\n}\n\n.chat-overlay-header-actions {\n display: flex;\n gap: 0.25rem;\n}\n\n.chat-overlay-header-btn {\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 6px;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n transition: all 0.15s ease;\n}\n\n.chat-overlay-header-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* --- Panel Body --- */\n\n.chat-overlay-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.chat-overlay-body mj-conversation-chat-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* --- Mobile Responsive --- */\n\n@media (max-width: 480px) {\n .chat-overlay-panel {\n bottom: 0;\n right: 0;\n width: 100% !important;\n height: 100vh !important;\n max-height: 100vh;\n border-radius: 0;\n }\n\n .chat-overlay-bubble {\n bottom: 1rem;\n right: 1rem;\n }\n\n .resize-handle {\n display: none;\n }\n}\n"] }]
|
|
675
|
+
args: [{ standalone: false, selector: 'mj-chat-agents-overlay', template: "@if (IsVisible) {\n <!-- Floating Button (collapsed state, not hidden) -->\n @if (State === 'collapsed' && !IsHidden) {\n <div class=\"chat-overlay-bubble\"\n [class.is-pressed]=\"IsBubblePressed\"\n [class.is-dragging]=\"IsBubbleDragging\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (pointerdown)=\"OnBubblePointerDown($event)\">\n <i class=\"fa-solid fa-chevron-up chat-overlay-bubble-arrow chat-overlay-bubble-arrow-up\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-chevron-down chat-overlay-bubble-arrow chat-overlay-bubble-arrow-down\" aria-hidden=\"true\"></i>\n <i class=\"fa-solid fa-comments chat-overlay-bubble-icon\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n <!-- Hide affordance: revealed on hover. pointerdown stops drag from starting; click hides the bubble. -->\n <button type=\"button\"\n class=\"chat-overlay-bubble-close\"\n title=\"Hide chat \u2014 a thin sliver will remain on the right edge\"\n aria-label=\"Hide chat overlay\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"Hide($event)\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <!-- Collapsed sliver \u2014 flush with the right edge when the bubble is hidden.\n Click opens the chat directly; closing returns to the bubble (not the\n sliver). To re-enter hidden mode the user clicks the \u00D7 pill again. -->\n @if (State === 'collapsed' && IsHidden) {\n <button type=\"button\"\n class=\"chat-overlay-sliver\"\n title=\"Open chat\"\n aria-label=\"Open chat\"\n [style.bottom.px]=\"BubbleBottomPx\"\n (click)=\"Expand()\">\n <i class=\"fa-solid fa-comments chat-overlay-sliver-icon\" aria-hidden=\"true\"></i>\n @if (UnreadCount > 0) {\n <span class=\"chat-overlay-badge chat-overlay-sliver-badge\">{{ UnreadCount > 9 ? '9+' : UnreadCount }}</span>\n }\n </button>\n }\n\n <!-- Expanded / Maximized Chat Panel -->\n @if (State === 'expanded' || State === 'maximized') {\n <div class=\"chat-overlay-panel\"\n [class.maximized]=\"State === 'maximized'\"\n [style.width.px]=\"State === 'maximized' ? null : PanelWidth\"\n [style.height.px]=\"State === 'maximized' ? null : PanelHeight\"\n [style.bottom.px]=\"State === 'maximized' ? null : PanelBottomPx\">\n\n <!-- Resize handles (only in expanded, not maximized) -->\n @if (State === 'expanded') {\n <div class=\"resize-handle resize-left\"\n (mousedown)=\"OnResizeStart($event, 'left')\"></div>\n <div class=\"resize-handle resize-top\"\n (mousedown)=\"OnResizeStart($event, 'top')\"></div>\n <div class=\"resize-handle resize-top-left\"\n (mousedown)=\"OnResizeStart($event, 'top-left')\"></div>\n }\n\n <!-- Panel Header -->\n <div class=\"chat-overlay-header\">\n <div class=\"chat-overlay-title\">\n <i class=\"fa-solid fa-robot\"></i>\n <span>AI Assistant</span>\n </div>\n <div class=\"chat-overlay-header-actions\">\n <button\n class=\"chat-overlay-header-btn\"\n title=\"New conversation\"\n (click)=\"StartNewConversation()\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n @if (ConversationId) {\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Open in full chat workspace\"\n (click)=\"OnOpenFullChatWorkspace()\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n }\n <button\n class=\"chat-overlay-header-btn\"\n [title]=\"State === 'maximized' ? 'Restore size' : 'Maximize'\"\n (click)=\"ToggleMaximize()\">\n <i class=\"fa-solid\" [class.fa-expand]=\"State !== 'maximized'\" [class.fa-compress]=\"State === 'maximized'\"></i>\n </button>\n <button\n class=\"chat-overlay-header-btn\"\n title=\"Minimize\"\n (click)=\"Collapse()\">\n <i class=\"fa-solid fa-minus\"></i>\n </button>\n </div>\n </div>\n\n <!-- Chat Content \u2014 wraps conversation-chat-area -->\n <div class=\"chat-overlay-body\">\n <mj-conversation-chat-area\n [environmentId]=\"EnvironmentId\"\n [currentUser]=\"CurrentUser\"\n [conversationId]=\"ConversationId\"\n [conversation]=\"Conversation\"\n [isNewConversation]=\"IsNewConversation\"\n [pendingMessage]=\"PendingMessage\"\n [pendingAttachments]=\"PendingAttachments\"\n [overlayMode]=\"true\"\n [showExportButton]=\"false\"\n [showShareButton]=\"false\"\n [showArtifactIndicator]=\"false\"\n [appContext]=\"AppContext\"\n [emptyStateGreeting]=\"EmptyStateGreeting\"\n (conversationCreated)=\"OnConversationCreated($event)\"\n (conversationRenamed)=\"OnConversationRenamed($event)\"\n (pendingMessageConsumed)=\"OnPendingMessageConsumed()\"\n (openEntityRecord)=\"OnOpenEntityRecord($event)\"\n (navigationRequest)=\"OnNavigationRequest($event)\"\n (taskClicked)=\"OnTaskClicked($event)\"\n ></mj-conversation-chat-area>\n </div>\n </div>\n }\n}\n", styles: ["/* ============================================================\n Chat Overlay \u2014 Floating Bubble + Expanding Panel\n All colors use MJ design tokens (--mj-* CSS variables).\n ============================================================ */\n\n/* --- Floating Bubble (collapsed state) --- */\n\n.chat-overlay-bubble {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n width: 3.5rem;\n height: 3.5rem;\n border-radius: 50%;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n z-index: 2147483647;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: overlayBubbleIn 0.3s ease;\n /* Required for touch drag: blocks browser pan/zoom so pointermove fires\n continuously instead of being swallowed by scroll-handling. */\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n\n/* Subtle up/down chevrons just outside the bubble, hinting that it can be\n dragged vertically. On hover-capable devices (mouse/pen) they stay hidden\n in the resting state and reveal on hover/press/drag \u2014 keeps the corner\n visually clean. On touch-only devices (no hover) they're always visible at\n low opacity so the affordance is discoverable without needing a hover. */\n.chat-overlay-bubble-arrow {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n color: var(--mj-text-muted);\n font-size: 0.65rem;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.18s ease;\n}\n\n.chat-overlay-bubble-arrow-up {\n top: -0.85rem;\n}\n\n.chat-overlay-bubble-arrow-down {\n bottom: -0.85rem;\n}\n\n/* Hover-capable devices: reveal on hover, press, or active drag. */\n.chat-overlay-bubble:hover .chat-overlay-bubble-arrow,\n.chat-overlay-bubble.is-pressed .chat-overlay-bubble-arrow,\n.chat-overlay-bubble.is-dragging .chat-overlay-bubble-arrow {\n opacity: 0.85;\n}\n\n/* Touch-only devices (no hover): always show at subtle opacity. The\n :hover/.is-pressed/.is-dragging rules above still apply via higher\n specificity, so touching the bubble briefly bumps them to 0.85. */\n@media (hover: none) {\n .chat-overlay-bubble-arrow {\n opacity: 0.5;\n }\n}\n\n.chat-overlay-bubble:hover {\n transform: scale(1.08);\n box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);\n}\n\n/* Immediate press feedback \u2014 fires on mousedown before the drag threshold is crossed,\n so the user sees \"I'm being held\" right away and learns the bubble is draggable. */\n.chat-overlay-bubble.is-pressed {\n cursor: grabbing;\n transform: scale(0.94);\n transition: transform 0.08s ease;\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.25),\n 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n/* Active drag \u2014 overrides the press state once movement passes the threshold. */\n.chat-overlay-bubble.is-dragging {\n cursor: grabbing;\n transform: scale(1.04);\n transition: none;\n box-shadow:\n 0 8px 28px rgba(0, 0, 0, 0.35),\n 0 0 0 4px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n@keyframes overlayBubbleIn {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.chat-overlay-bubble-icon {\n font-size: 1.3rem;\n}\n\n.chat-overlay-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 1.2rem;\n height: 1.2rem;\n border-radius: 9999px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 0.65rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 0.25rem;\n border: 2px solid var(--mj-bg-page);\n}\n\n/* --- Hide-bubble affordance (\"\u00D7\" pill on the outer-left edge of the bubble) ---\n Revealed on hover. Touch-only devices (no hover) get a permanent low-opacity\n render so the affordance is reachable without a hover gesture. */\n.chat-overlay-bubble-close {\n position: absolute;\n top: 50%;\n /* Sits flush with the bubble's left bounding-box edge \u2014 no dead-zone gap that\n would drop the :hover state mid-reach. The bubble's circular shape means the\n visible space between the circle and the pill still reads as a gap. */\n right: 100%;\n transform: translateY(-50%);\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border-radius: 9999px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-strong);\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.65rem;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;\n}\n\n.chat-overlay-bubble:hover .chat-overlay-bubble-close {\n opacity: 1;\n pointer-events: auto;\n}\n\n.chat-overlay-bubble-close:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-brand-primary);\n transform: translateY(-50%) scale(1.08);\n}\n\n/* Touch devices: keep the pill reachable without a hover gesture. */\n@media (hover: none) {\n .chat-overlay-bubble-close {\n opacity: 0.7;\n pointer-events: auto;\n }\n}\n\n/* While actively dragging, suppress the close pill \u2014 it shouldn't compete with the drag affordance. */\n.chat-overlay-bubble.is-dragging .chat-overlay-bubble-close,\n.chat-overlay-bubble.is-pressed .chat-overlay-bubble-close {\n opacity: 0;\n pointer-events: none;\n}\n\n/* --- Collapsed sliver (right edge, replaces bubble when hidden) --- */\n\n.chat-overlay-sliver {\n position: fixed;\n right: 0;\n width: 0.875rem; /* 14px sliver */\n height: 5rem; /* 80px tall */\n padding: 0;\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px 0 0 8px;\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n z-index: 2147483647;\n transition: width 0.18s ease, background 0.15s ease;\n animation: overlayBubbleIn 0.25s ease;\n}\n\n.chat-overlay-sliver:hover {\n width: 1.5rem; /* widens slightly to invite the click */\n background: color-mix(in srgb, var(--mj-brand-primary) 85%, white);\n}\n\n.chat-overlay-sliver-icon {\n font-size: 0.55rem;\n opacity: 0.95;\n}\n\n.chat-overlay-sliver:hover .chat-overlay-sliver-icon {\n font-size: 0.7rem;\n}\n\n.chat-overlay-sliver-badge {\n /* Pull the badge a hair outside the sliver so it isn't clipped by the narrow width. */\n top: -6px;\n right: -6px;\n}\n\n/* --- Expanded Panel --- */\n\n.chat-overlay-panel {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n border-radius: 12px;\n background: var(--mj-bg-surface);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-border-strong));\n box-shadow:\n 0 8px 32px rgba(0, 0, 0, 0.3),\n 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 2147483647;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: overlayPanelIn 0.25s ease;\n max-height: calc(100vh - 3rem);\n max-width: calc(100vw - 3rem);\n}\n\n.chat-overlay-panel.maximized {\n bottom: 1rem;\n right: 1rem;\n width: calc(100vw - 2rem) !important;\n height: calc(100vh - 2rem) !important;\n max-height: none;\n max-width: none;\n border-radius: 12px;\n}\n\n@keyframes overlayPanelIn {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(10px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n/* --- Resize Handles --- */\n\n.resize-handle {\n position: absolute;\n z-index: 2;\n}\n\n.resize-left {\n left: -3px;\n top: 20px;\n bottom: 20px;\n width: 6px;\n cursor: ew-resize;\n}\n\n.resize-top {\n top: -3px;\n left: 20px;\n right: 20px;\n height: 6px;\n cursor: ns-resize;\n}\n\n.resize-top-left {\n top: -4px;\n left: -4px;\n width: 16px;\n height: 16px;\n cursor: nwse-resize;\n}\n\n.resize-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n border-radius: 3px;\n}\n\n/* --- Panel Header --- */\n\n.chat-overlay-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.6rem 0.75rem;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n flex-shrink: 0;\n}\n\n.chat-overlay-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n\n.chat-overlay-title i {\n color: var(--mj-brand-primary);\n}\n\n.chat-overlay-header-actions {\n display: flex;\n gap: 0.25rem;\n}\n\n.chat-overlay-header-btn {\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 6px;\n border: none;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n transition: all 0.15s ease;\n}\n\n.chat-overlay-header-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n/* --- Panel Body --- */\n\n.chat-overlay-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.chat-overlay-body mj-conversation-chat-area {\n flex: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* --- Mobile / Small-Screen Responsive ---\n 640px = small-screen cutoff (covers all phones in both orientations). Tablets\n in portrait (\u2265768px) keep the floating-panel treatment because they have the\n real estate for it. */\n\n@media (max-width: 640px) {\n .chat-overlay-panel {\n bottom: 0 !important;\n right: 0;\n width: 100% !important;\n height: 100vh !important;\n max-height: 100vh;\n border-radius: 0;\n }\n\n .chat-overlay-bubble {\n /* No !important on `bottom` \u2014 the inline [style.bottom.px] binding owns it\n so users can drag the bubble out of the way of underlying app buttons.\n Smaller diameter on small screens: 2.75rem (44px) hits the WCAG minimum\n touch target while ~38% less occluding than the desktop 3.5rem. */\n width: 2.75rem;\n height: 2.75rem;\n right: 1rem;\n }\n\n .chat-overlay-bubble-icon {\n font-size: 1.1rem;\n }\n\n .chat-overlay-badge {\n min-width: 1rem;\n height: 1rem;\n font-size: 0.6rem;\n top: -3px;\n right: -3px;\n }\n\n .resize-handle {\n display: none;\n }\n\n /* Slightly wider sliver on touch so it meets the WCAG minimum touch target. */\n .chat-overlay-sliver {\n width: 1.25rem;\n height: 4.5rem;\n }\n}\n"] }]
|
|
436
676
|
}], null, { IsVisible: [{
|
|
437
677
|
type: Input
|
|
438
678
|
}], CurrentUser: [{
|
|
@@ -443,6 +683,8 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
443
683
|
type: Input
|
|
444
684
|
}], EmptyStateGreeting: [{
|
|
445
685
|
type: Input
|
|
686
|
+
}], TopBoundaryPx: [{
|
|
687
|
+
type: Input
|
|
446
688
|
}], VisibilityChanged: [{
|
|
447
689
|
type: Output
|
|
448
690
|
}], ToolExecuted: [{
|
|
@@ -458,5 +700,5 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
|
|
|
458
700
|
}], TaskClicked: [{
|
|
459
701
|
type: Output
|
|
460
702
|
}] }); })();
|
|
461
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ChatAgentsOverlayComponent, { className: "ChatAgentsOverlayComponent", filePath: "src/lib/components/overlay/chat-overlay.component.ts", lineNumber:
|
|
703
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ChatAgentsOverlayComponent, { className: "ChatAgentsOverlayComponent", filePath: "src/lib/components/overlay/chat-overlay.component.ts", lineNumber: 63 }); })();
|
|
462
704
|
//# sourceMappingURL=chat-overlay.component.js.map
|