@memberjunction/ng-conversations 5.35.0 → 5.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +62 -2
  2. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  3. package/dist/lib/components/conversation/conversation-chat-area.component.js +300 -24
  4. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  5. package/dist/lib/components/dialogs/rating-dialog.component.d.ts +31 -0
  6. package/dist/lib/components/dialogs/rating-dialog.component.d.ts.map +1 -0
  7. package/dist/lib/components/dialogs/rating-dialog.component.js +290 -0
  8. package/dist/lib/components/dialogs/rating-dialog.component.js.map +1 -0
  9. package/dist/lib/components/mention/mention-editor.component.d.ts +1 -1
  10. package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
  11. package/dist/lib/components/mention/mention-editor.component.js +1 -0
  12. package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
  13. package/dist/lib/components/message/conversation-message-rating.component.d.ts +43 -18
  14. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  15. package/dist/lib/components/message/conversation-message-rating.component.js +235 -193
  16. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  17. package/dist/lib/components/message/message-input-box.component.d.ts +1 -1
  18. package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
  19. package/dist/lib/components/message/message-input-box.component.js +1 -1
  20. package/dist/lib/components/message/message-input-box.component.js.map +1 -1
  21. package/dist/lib/components/message/message-input.component.d.ts +7 -1
  22. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  23. package/dist/lib/components/message/message-input.component.js +28 -3
  24. package/dist/lib/components/message/message-input.component.js.map +1 -1
  25. package/dist/lib/components/message/message-item.component.js +20 -20
  26. package/dist/lib/components/message/message-item.component.js.map +1 -1
  27. package/dist/lib/components/overlay/chat-overlay.component.d.ts +73 -5
  28. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  29. package/dist/lib/components/overlay/chat-overlay.component.js +202 -37
  30. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  31. package/dist/lib/conversations.module.d.ts +24 -23
  32. package/dist/lib/conversations.module.d.ts.map +1 -1
  33. package/dist/lib/conversations.module.js +4 -0
  34. package/dist/lib/conversations.module.js.map +1 -1
  35. package/dist/lib/services/data-cache.service.d.ts.map +1 -1
  36. package/dist/lib/services/data-cache.service.js +0 -1
  37. package/dist/lib/services/data-cache.service.js.map +1 -1
  38. package/dist/lib/services/dialog.service.d.ts +24 -0
  39. package/dist/lib/services/dialog.service.d.ts.map +1 -1
  40. package/dist/lib/services/dialog.service.js +45 -0
  41. package/dist/lib/services/dialog.service.js.map +1 -1
  42. package/package.json +22 -22
@@ -40,6 +40,14 @@ export declare class ChatAgentsOverlayComponent extends BaseAngularComponent imp
40
40
  private static readonly MIN_HEIGHT;
41
41
  private static readonly MAX_WIDTH;
42
42
  private static readonly MAX_HEIGHT;
43
+ /** Default `bottom` for both bubble and panel (matches CSS 1.5rem). */
44
+ private static readonly BASE_BOTTOM_PX;
45
+ /** Floating bubble diameter in pixels (matches CSS 3.5rem). */
46
+ private static readonly BUBBLE_SIZE_PX;
47
+ /** Minimum gap to keep between the overlay and the viewport top edge. */
48
+ private static readonly VIEWPORT_TOP_PADDING_PX;
49
+ /** Mousedown-to-mousemove distance that promotes a click into a drag. */
50
+ private static readonly BUBBLE_DRAG_THRESHOLD_PX;
43
51
  /** Controls external visibility (e.g., parent hides overlay on chat route) */
44
52
  private _IsVisible;
45
53
  set IsVisible(value: boolean);
@@ -52,6 +60,13 @@ export declare class ChatAgentsOverlayComponent extends BaseAngularComponent imp
52
60
  AppContext: Record<string, unknown> | null;
53
61
  /** Greeting message shown in the empty state when no conversation is active */
54
62
  EmptyStateGreeting: string;
63
+ /**
64
+ * Pixels reserved at the top of the viewport that the bubble and panel must not
65
+ * cross. Set this from the host app to the height of any fixed top chrome (e.g.
66
+ * Explorer's shell-header). Defaults to 0 — generic apps without top chrome
67
+ * keep the full viewport available.
68
+ */
69
+ TopBoundaryPx: number;
55
70
  /** Emitted when the overlay visibility changes */
56
71
  VisibilityChanged: EventEmitter<ChatOverlayState>;
57
72
  /** Emitted when a tool finishes executing in the agent client */
@@ -74,6 +89,20 @@ export declare class ChatAgentsOverlayComponent extends BaseAngularComponent imp
74
89
  /** Panel dimensions (persisted via UserInfoEngine) */
75
90
  PanelWidth: number;
76
91
  PanelHeight: number;
92
+ /**
93
+ * Pixels the floating bubble has been dragged up from its default
94
+ * bottom-right corner position. Always >= 0; clamping at render time
95
+ * keeps the bubble on-screen even after a viewport resize.
96
+ */
97
+ BubbleOffsetY: number;
98
+ /** True while the user is actively dragging the bubble; used to swap cursor + suppress click. */
99
+ IsBubbleDragging: boolean;
100
+ /**
101
+ * True from mousedown until mouseup on the bubble, regardless of whether the
102
+ * gesture became a drag. Used to give immediate "I'm being held" feedback so
103
+ * the user can see drag is possible even before crossing the move threshold.
104
+ */
105
+ IsBubblePressed: boolean;
77
106
  /** Active conversation ID managed locally */
78
107
  private _conversationId;
79
108
  get ConversationId(): string | null;
@@ -92,6 +121,15 @@ export declare class ChatAgentsOverlayComponent extends BaseAngularComponent imp
92
121
  private resizeStartY;
93
122
  private resizeStartWidth;
94
123
  private resizeStartHeight;
124
+ /** Bubble drag state */
125
+ private bubbleDragStartMouseY;
126
+ private bubbleDragStartOffset;
127
+ /** True once the pointer has moved past BUBBLE_DRAG_THRESHOLD_PX; suppresses the implicit click. */
128
+ private bubbleDragMoved;
129
+ /** ID of the pointer currently driving the drag — guards against multi-touch confusion. */
130
+ private activeBubblePointerId;
131
+ /** Element that captured the pointer; needed to release capture on end/cancel. */
132
+ private bubbleCaptureTarget;
95
133
  ngOnInit(): void;
96
134
  ngOnDestroy(): void;
97
135
  /** Toggle between collapsed and expanded states */
@@ -138,12 +176,42 @@ export declare class ChatAgentsOverlayComponent extends BaseAngularComponent imp
138
176
  private removeResizeListeners;
139
177
  private clampWidth;
140
178
  private clampHeight;
179
+ /**
180
+ * Start tracking a potential bubble drag. We don't enter drag mode until
181
+ * the pointer moves past BUBBLE_DRAG_THRESHOLD_PX — releasing before that
182
+ * threshold is treated as a normal click/tap and opens the chat (via Toggle()).
183
+ *
184
+ * Pointer Events (not mousedown) so the same code path serves desktop mouse,
185
+ * touch on phones/tablets, and pen input. setPointerCapture keeps the gesture
186
+ * tied to this element even if the finger or cursor strays off the bubble.
187
+ */
188
+ OnBubblePointerDown(event: PointerEvent): void;
189
+ private onBubbleDragMove;
190
+ private onBubbleDragEnd;
191
+ private removeBubbleDragListeners;
192
+ /**
193
+ * Reserved space at the top of the viewport — host-supplied chrome plus
194
+ * the padding gap we always keep above the bubble/panel.
195
+ */
196
+ private get topReservedPx();
197
+ /** Clamp the offset so the bubble stays fully visible below the top boundary. */
198
+ private clampBubbleOffsetY;
199
+ /** Effective `bottom` (px) for the floating bubble, clamped to the current viewport. */
200
+ get BubbleBottomPx(): number;
201
+ /**
202
+ * Effective `bottom` (px) for the expanded panel. Anchors to the bubble's
203
+ * current bottom edge so the panel grows up from where the user parked the
204
+ * bubble, but clamps downward whenever the panel would otherwise extend
205
+ * past the viewport's top boundary — that's the "reposition lower so the
206
+ * chat interface stays visible" behavior.
207
+ */
208
+ get PanelBottomPx(): number;
141
209
  /** Auto-resolve CurrentUser and EnvironmentId from Metadata when not provided as inputs */
142
210
  private resolveDefaults;
143
- /** Load saved panel size from UserInfoEngine */
144
- private loadSizePreferences;
145
- /** Persist panel size to UserInfoEngine (debounced) */
146
- private saveSizePreferences;
211
+ /** Load saved panel size and bubble position from UserInfoEngine */
212
+ private loadPreferences;
213
+ /** Persist panel size and bubble position to UserInfoEngine (debounced) */
214
+ private savePreferences;
147
215
  /** Subscribe to bridge events for cross-view coordination */
148
216
  private subscribeToBridgeEvents;
149
217
  /** Subscribe to agent client tool execution events */
@@ -153,6 +221,6 @@ export declare class ChatAgentsOverlayComponent extends BaseAngularComponent imp
153
221
  /** Emit a conversation switched event */
154
222
  private emitConversationSwitched;
155
223
  static ɵfac: i0.ɵɵFactoryDeclaration<ChatAgentsOverlayComponent, never>;
156
- static ɵcmp: i0.ɵɵComponentDeclaration<ChatAgentsOverlayComponent, "mj-chat-agents-overlay", never, { "IsVisible": { "alias": "IsVisible"; "required": false; }; "CurrentUser": { "alias": "CurrentUser"; "required": false; }; "EnvironmentId": { "alias": "EnvironmentId"; "required": false; }; "AppContext": { "alias": "AppContext"; "required": false; }; "EmptyStateGreeting": { "alias": "EmptyStateGreeting"; "required": false; }; }, { "VisibilityChanged": "VisibilityChanged"; "ToolExecuted": "ToolExecuted"; "ConversationSwitched": "ConversationSwitched"; "OpenFullChatWorkspace": "OpenFullChatWorkspace"; "NavigationRequested": "NavigationRequested"; "OpenEntityRecord": "OpenEntityRecord"; "TaskClicked": "TaskClicked"; }, never, never, false, never>;
224
+ static ɵcmp: i0.ɵɵComponentDeclaration<ChatAgentsOverlayComponent, "mj-chat-agents-overlay", never, { "IsVisible": { "alias": "IsVisible"; "required": false; }; "CurrentUser": { "alias": "CurrentUser"; "required": false; }; "EnvironmentId": { "alias": "EnvironmentId"; "required": false; }; "AppContext": { "alias": "AppContext"; "required": false; }; "EmptyStateGreeting": { "alias": "EmptyStateGreeting"; "required": false; }; "TopBoundaryPx": { "alias": "TopBoundaryPx"; "required": false; }; }, { "VisibilityChanged": "VisibilityChanged"; "ToolExecuted": "ToolExecuted"; "ConversationSwitched": "ConversationSwitched"; "OpenFullChatWorkspace": "OpenFullChatWorkspace"; "NavigationRequested": "NavigationRequested"; "OpenEntityRecord": "OpenEntityRecord"; "TaskClicked": "TaskClicked"; }, never, never, false, never>;
157
225
  }
158
226
  //# sourceMappingURL=chat-overlay.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-overlay.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/overlay/chat-overlay.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-overlay.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/overlay/chat-overlay.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAEH,YAAY,EAEZ,SAAS,EACT,MAAM,EAIT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAAE,QAAQ,EAAY,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAA+C,MAAM,+BAA+B,CAAC;AAEhI,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;;AAExE,wCAAwC;AACxC,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,CAAC;AAEtE,wEAAwE;AACxE,MAAM,WAAW,gCAAgC;IAC7C,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAUD,qBAMa,0BAA2B,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAC7F,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,QAAQ,CAAuB;IAGvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAsB;IAC9D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAO;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAO;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAO;IACzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAO;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAQ;IAG1C,uEAAuE;IACvE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAM;IAC5C,+DAA+D;IAC/D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAM;IAC5C,yEAAyE;IACzE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAM;IACrD,yEAAyE;IACzE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAK;IAIrD,8EAA8E;IAC9E,OAAO,CAAC,UAAU,CAAQ;IAE1B,IACI,SAAS,CAAC,KAAK,EAAE,OAAO,EAO3B;IACD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,gHAAgH;IACvG,WAAW,EAAG,QAAQ,CAAC;IAEhC,4GAA4G;IACnG,aAAa,EAAG,MAAM,CAAC;IAEhC,8GAA8G;IACrG,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAQ;IAE3D,+EAA+E;IACtE,kBAAkB,EAAE,MAAM,CAAyB;IAE5D;;;;;OAKG;IACM,aAAa,EAAE,MAAM,CAAK;IAInC,kDAAkD;IACxC,iBAAiB,iCAAwC;IAEnE,iEAAiE;IACvD,YAAY,sCAA6C;IAEnE,kEAAkE;IACxD,oBAAoB,iDAAwD;IAEtF,qEAAqE;IAC3D,qBAAqB,8BAAqC;IAEpE,iEAAiE;IACvD,mBAAmB,kCAAyC;IAEtE,sDAAsD;IAC5C,gBAAgB;oBAAiC,MAAM;sBAAgB,YAAY;OAAK;IAElG,qCAAqC;IAC3B,WAAW,6BAAoC;IAIlD,KAAK,EAAE,gBAAgB,CAAe;IACtC,WAAW,SAAK;IAEvB,sDAAsD;IAC/C,UAAU,SAA4C;IACtD,WAAW,SAA6C;IAE/D;;;;OAIG;IACI,aAAa,SAAK;IAEzB,iGAAiG;IAC1F,gBAAgB,UAAS;IAEhC;;;;OAIG;IACI,eAAe,UAAS;IAE/B,6CAA6C;IAC7C,OAAO,CAAC,eAAe,CAAuB;IAC9C,IAAW,cAAc,IAAI,MAAM,GAAG,IAAI,CAEzC;IAED,iCAAiC;IAC1B,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAQ;IAExD,wDAAwD;IACjD,iBAAiB,UAAQ;IAEhC,0DAA0D;IACnD,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE5C,8DAA8D;IACvD,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAQ;IAE7D,wBAAwB;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAA4C;IAC9D,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,iBAAiB,CAAK;IAE9B,wBAAwB;IACxB,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,qBAAqB,CAAK;IAClC,oGAAoG;IACpG,OAAO,CAAC,eAAe,CAAS;IAChC,2FAA2F;IAC3F,OAAO,CAAC,qBAAqB,CAAuB;IACpD,kFAAkF;IAClF,OAAO,CAAC,mBAAmB,CAA4B;IAIvD,QAAQ,IAAI,IAAI;IAOhB,WAAW,IAAI,IAAI;IASnB,mDAAmD;IAC5C,MAAM,IAAI,IAAI;IAQrB,gDAAgD;IACzC,MAAM,IAAI,IAAI;IAQrB,kDAAkD;IAC3C,QAAQ,IAAI,IAAI;IAOvB,mDAAmD;IAC5C,cAAc,IAAI,IAAI;IAW7B,6DAA6D;IACtD,uBAAuB,IAAI,IAAI;IAMtC,sDAAsD;IAC/C,qBAAqB,CAAC,KAAK,EAAE;QAChC,YAAY,EAAE,oBAAoB,CAAC;QACnC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;KAC5C,GAAG,IAAI;IAYR,mDAAmD;IAC5C,wBAAwB,IAAI,IAAI;IAKvC,gDAAgD;IACzC,qBAAqB,CAAC,MAAM,EAAE;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,GAAG,IAAI;IAKvG,yCAAyC;IAClC,kBAAkB,CAAC,KAAK,EAAE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,YAAY,CAAA;KAAC,GAAG,IAAI;IAIxF,oDAAoD;IAC7C,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAI1D,4CAA4C;IACrC,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAI9C,8CAA8C;IACvC,oBAAoB,IAAI,IAAI;IAcnC,sFAAsF;IAC/E,eAAe,IAAI,IAAI;IAS9B,4CAA4C;IACrC,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,IAAI;IAchF,OAAO,CAAC,YAAY,CAalB;IAEF,OAAO,CAAC,WAAW,CAMjB;IAEF,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAMnB;;;;;;;;OAQG;IACI,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAuBrD,OAAO,CAAC,gBAAgB,CAUtB;IAEF,OAAO,CAAC,eAAe,CAyBrB;IAEF,OAAO,CAAC,yBAAyB;IAMjC;;;OAGG;IACH,OAAO,KAAK,aAAa,GAExB;IAED,iFAAiF;IACjF,OAAO,CAAC,kBAAkB;IAU1B,wFAAwF;IACxF,IAAW,cAAc,IAAI,MAAM,CASlC;IAED;;;;;;OAMG;IACH,IAAW,aAAa,IAAI,MAAM,CASjC;IAID,2FAA2F;IAC3F,OAAO,CAAC,eAAe;IAUvB,oEAAoE;IACpE,OAAO,CAAC,eAAe;IAiBvB,2EAA2E;IAC3E,OAAO,CAAC,eAAe;IAYvB,6DAA6D;IAC7D,OAAO,CAAC,uBAAuB;IAwB/B,sDAAsD;IACtD,OAAO,CAAC,qBAAqB;IAQ7B,2DAA2D;IAC3D,OAAO,CAAC,qBAAqB;IAS7B,yCAAyC;IACzC,OAAO,CAAC,wBAAwB;yCApiBvB,0BAA0B;2CAA1B,0BAA0B;CA0iBtC"}
@@ -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 ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
26
- i0.ɵɵelementStart(0, "span", 4);
25
+ function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) {
26
+ i0.ɵɵelementStart(0, "span", 6);
27
27
  i0.ɵɵtext(1);
28
28
  i0.ɵɵelementEnd();
29
29
  } if (rf & 2) {
@@ -34,62 +34,64 @@ function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Conditional_2_Te
34
34
  function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
35
35
  const _r1 = i0.ɵɵgetCurrentView();
36
36
  i0.ɵɵelementStart(0, "div", 2);
37
- i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.Toggle()); });
38
- i0.ɵɵelement(1, "i", 3);
39
- i0.ɵɵconditionalCreate(2, ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Conditional_2_Template, 2, 1, "span", 4);
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", 3)(2, "i", 4)(3, "i", 5);
39
+ i0.ɵɵconditionalCreate(4, ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Conditional_4_Template, 2, 1, "span", 6);
40
40
  i0.ɵɵelementEnd();
41
41
  } if (rf & 2) {
42
42
  const ctx_r1 = i0.ɵɵnextContext(2);
43
- i0.ɵɵadvance(2);
44
- i0.ɵɵconditional(ctx_r1.UnreadCount > 0 ? 2 : -1);
43
+ i0.ɵɵstyleProp("bottom", ctx_r1.BubbleBottomPx, "px");
44
+ i0.ɵɵclassProp("is-pressed", ctx_r1.IsBubblePressed)("is-dragging", ctx_r1.IsBubbleDragging);
45
+ i0.ɵɵadvance(4);
46
+ i0.ɵɵconditional(ctx_r1.UnreadCount > 0 ? 4 : -1);
45
47
  } }
46
48
  function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
47
49
  const _r4 = i0.ɵɵgetCurrentView();
48
- i0.ɵɵelementStart(0, "div", 19);
50
+ i0.ɵɵelementStart(0, "div", 21);
49
51
  i0.ɵɵlistener("mousedown", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_1_Template_div_mousedown_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnResizeStart($event, "left")); });
50
52
  i0.ɵɵelementEnd();
51
- i0.ɵɵelementStart(1, "div", 20);
53
+ i0.ɵɵelementStart(1, "div", 22);
52
54
  i0.ɵɵlistener("mousedown", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_1_Template_div_mousedown_1_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnResizeStart($event, "top")); });
53
55
  i0.ɵɵelementEnd();
54
- i0.ɵɵelementStart(2, "div", 21);
56
+ i0.ɵɵelementStart(2, "div", 23);
55
57
  i0.ɵɵlistener("mousedown", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_1_Template_div_mousedown_2_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnResizeStart($event, "top-left")); });
56
58
  i0.ɵɵelementEnd();
57
59
  } }
58
60
  function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_10_Template(rf, ctx) { if (rf & 1) {
59
61
  const _r5 = i0.ɵɵgetCurrentView();
60
- i0.ɵɵelementStart(0, "button", 22);
62
+ i0.ɵɵelementStart(0, "button", 24);
61
63
  i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnOpenFullChatWorkspace()); });
62
- i0.ɵɵelement(1, "i", 23);
64
+ i0.ɵɵelement(1, "i", 25);
63
65
  i0.ɵɵelementEnd();
64
66
  } }
65
67
  function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
66
68
  const _r3 = i0.ɵɵgetCurrentView();
67
- i0.ɵɵelementStart(0, "div", 5);
69
+ i0.ɵɵelementStart(0, "div", 7);
68
70
  i0.ɵɵconditionalCreate(1, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_1_Template, 3, 0);
69
- i0.ɵɵelementStart(2, "div", 6)(3, "div", 7);
70
- i0.ɵɵelement(4, "i", 8);
71
+ i0.ɵɵelementStart(2, "div", 8)(3, "div", 9);
72
+ i0.ɵɵelement(4, "i", 10);
71
73
  i0.ɵɵelementStart(5, "span");
72
74
  i0.ɵɵtext(6, "AI Assistant");
73
75
  i0.ɵɵelementEnd()();
74
- i0.ɵɵelementStart(7, "div", 9)(8, "button", 10);
76
+ i0.ɵɵelementStart(7, "div", 11)(8, "button", 12);
75
77
  i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.StartNewConversation()); });
76
- i0.ɵɵelement(9, "i", 11);
78
+ i0.ɵɵelement(9, "i", 13);
77
79
  i0.ɵɵelementEnd();
78
- i0.ɵɵconditionalCreate(10, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_10_Template, 2, 0, "button", 12);
79
- i0.ɵɵelementStart(11, "button", 13);
80
+ i0.ɵɵconditionalCreate(10, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Conditional_10_Template, 2, 0, "button", 14);
81
+ i0.ɵɵelementStart(11, "button", 15);
80
82
  i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleMaximize()); });
81
- i0.ɵɵelement(12, "i", 14);
83
+ i0.ɵɵelement(12, "i", 16);
82
84
  i0.ɵɵelementEnd();
83
- i0.ɵɵelementStart(13, "button", 15);
85
+ i0.ɵɵelementStart(13, "button", 17);
84
86
  i0.ɵɵlistener("click", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.Collapse()); });
85
- i0.ɵɵelement(14, "i", 16);
87
+ i0.ɵɵelement(14, "i", 18);
86
88
  i0.ɵɵelementEnd()()();
87
- i0.ɵɵelementStart(15, "div", 17)(16, "mj-conversation-chat-area", 18);
89
+ i0.ɵɵelementStart(15, "div", 19)(16, "mj-conversation-chat-area", 20);
88
90
  i0.ɵɵlistener("conversationCreated", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_mj_conversation_chat_area_conversationCreated_16_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnConversationCreated($event)); })("conversationRenamed", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_mj_conversation_chat_area_conversationRenamed_16_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnConversationRenamed($event)); })("pendingMessageConsumed", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_mj_conversation_chat_area_pendingMessageConsumed_16_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnPendingMessageConsumed()); })("openEntityRecord", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_mj_conversation_chat_area_openEntityRecord_16_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnOpenEntityRecord($event)); })("navigationRequest", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_mj_conversation_chat_area_navigationRequest_16_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnNavigationRequest($event)); })("taskClicked", function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template_mj_conversation_chat_area_taskClicked_16_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTaskClicked($event)); });
89
91
  i0.ɵɵelementEnd()()();
90
92
  } if (rf & 2) {
91
93
  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");
94
+ 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
95
  i0.ɵɵclassProp("maximized", ctx_r1.State === "maximized");
94
96
  i0.ɵɵadvance();
95
97
  i0.ɵɵconditional(ctx_r1.State === "expanded" ? 1 : -1);
@@ -103,8 +105,8 @@ function ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template(rf, ctx
103
105
  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
106
  } }
105
107
  function ChatAgentsOverlayComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
106
- i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template, 3, 1, "div", 0);
107
- i0.ɵɵconditionalCreate(1, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template, 17, 26, "div", 1);
108
+ i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Conditional_0_Template, 5, 7, "div", 0);
109
+ i0.ɵɵconditionalCreate(1, ChatAgentsOverlayComponent_Conditional_0_Conditional_1_Template, 17, 28, "div", 1);
108
110
  } if (rf & 2) {
109
111
  const ctx_r1 = i0.ɵɵnextContext();
110
112
  i0.ɵɵconditional(ctx_r1.State === "collapsed" ? 0 : -1);
@@ -124,6 +126,15 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
124
126
  static MIN_HEIGHT = 350;
125
127
  static MAX_WIDTH = 900;
126
128
  static MAX_HEIGHT = 1000;
129
+ // --- Bubble drag constants ---
130
+ /** Default `bottom` for both bubble and panel (matches CSS 1.5rem). */
131
+ static BASE_BOTTOM_PX = 24;
132
+ /** Floating bubble diameter in pixels (matches CSS 3.5rem). */
133
+ static BUBBLE_SIZE_PX = 56;
134
+ /** Minimum gap to keep between the overlay and the viewport top edge. */
135
+ static VIEWPORT_TOP_PADDING_PX = 16;
136
+ /** Mousedown-to-mousemove distance that promotes a click into a drag. */
137
+ static BUBBLE_DRAG_THRESHOLD_PX = 5;
127
138
  // --- Inputs ---
128
139
  /** Controls external visibility (e.g., parent hides overlay on chat route) */
129
140
  _IsVisible = true;
@@ -146,6 +157,13 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
146
157
  AppContext = null;
147
158
  /** Greeting message shown in the empty state when no conversation is active */
148
159
  EmptyStateGreeting = 'How can I help you?';
160
+ /**
161
+ * Pixels reserved at the top of the viewport that the bubble and panel must not
162
+ * cross. Set this from the host app to the height of any fixed top chrome (e.g.
163
+ * Explorer's shell-header). Defaults to 0 — generic apps without top chrome
164
+ * keep the full viewport available.
165
+ */
166
+ TopBoundaryPx = 0;
149
167
  // --- Outputs ---
150
168
  /** Emitted when the overlay visibility changes */
151
169
  VisibilityChanged = new EventEmitter();
@@ -167,6 +185,20 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
167
185
  /** Panel dimensions (persisted via UserInfoEngine) */
168
186
  PanelWidth = ChatAgentsOverlayComponent.DEFAULT_WIDTH;
169
187
  PanelHeight = ChatAgentsOverlayComponent.DEFAULT_HEIGHT;
188
+ /**
189
+ * Pixels the floating bubble has been dragged up from its default
190
+ * bottom-right corner position. Always >= 0; clamping at render time
191
+ * keeps the bubble on-screen even after a viewport resize.
192
+ */
193
+ BubbleOffsetY = 0;
194
+ /** True while the user is actively dragging the bubble; used to swap cursor + suppress click. */
195
+ IsBubbleDragging = false;
196
+ /**
197
+ * True from mousedown until mouseup on the bubble, regardless of whether the
198
+ * gesture became a drag. Used to give immediate "I'm being held" feedback so
199
+ * the user can see drag is possible even before crossing the move threshold.
200
+ */
201
+ IsBubblePressed = false;
170
202
  /** Active conversation ID managed locally */
171
203
  _conversationId = null;
172
204
  get ConversationId() {
@@ -187,10 +219,19 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
187
219
  resizeStartY = 0;
188
220
  resizeStartWidth = 0;
189
221
  resizeStartHeight = 0;
222
+ /** Bubble drag state */
223
+ bubbleDragStartMouseY = 0;
224
+ bubbleDragStartOffset = 0;
225
+ /** True once the pointer has moved past BUBBLE_DRAG_THRESHOLD_PX; suppresses the implicit click. */
226
+ bubbleDragMoved = false;
227
+ /** ID of the pointer currently driving the drag — guards against multi-touch confusion. */
228
+ activeBubblePointerId = null;
229
+ /** Element that captured the pointer; needed to release capture on end/cancel. */
230
+ bubbleCaptureTarget = null;
190
231
  // --- Lifecycle ---
191
232
  ngOnInit() {
192
233
  this.resolveDefaults();
193
- this.loadSizePreferences();
234
+ this.loadPreferences();
194
235
  this.subscribeToBridgeEvents();
195
236
  this.subscribeToToolEvents();
196
237
  }
@@ -198,6 +239,7 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
198
239
  this.destroy$.next();
199
240
  this.destroy$.complete();
200
241
  this.removeResizeListeners();
242
+ this.removeBubbleDragListeners();
201
243
  }
202
244
  // --- Public Methods ---
203
245
  /** Toggle between collapsed and expanded states */
@@ -330,7 +372,7 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
330
372
  this.isResizing = false;
331
373
  this.resizeEdge = null;
332
374
  this.removeResizeListeners();
333
- this.saveSizePreferences();
375
+ this.savePreferences();
334
376
  };
335
377
  removeResizeListeners() {
336
378
  document.removeEventListener('mousemove', this.onResizeMove);
@@ -342,6 +384,123 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
342
384
  clampHeight(value) {
343
385
  return Math.max(ChatAgentsOverlayComponent.MIN_HEIGHT, Math.min(ChatAgentsOverlayComponent.MAX_HEIGHT, value));
344
386
  }
387
+ // --- Bubble Drag Methods (Pointer Events — unified mouse / touch / pen) ---
388
+ /**
389
+ * Start tracking a potential bubble drag. We don't enter drag mode until
390
+ * the pointer moves past BUBBLE_DRAG_THRESHOLD_PX — releasing before that
391
+ * threshold is treated as a normal click/tap and opens the chat (via Toggle()).
392
+ *
393
+ * Pointer Events (not mousedown) so the same code path serves desktop mouse,
394
+ * touch on phones/tablets, and pen input. setPointerCapture keeps the gesture
395
+ * tied to this element even if the finger or cursor strays off the bubble.
396
+ */
397
+ OnBubblePointerDown(event) {
398
+ // Mouse: respect primary-button only. Touch/pen: button is always 0, so this passes naturally.
399
+ if (event.pointerType === 'mouse' && event.button !== 0)
400
+ return;
401
+ // Don't start a second drag while one is in flight (e.g. second finger on touch).
402
+ if (this.activeBubblePointerId !== null)
403
+ return;
404
+ event.preventDefault();
405
+ const target = event.currentTarget;
406
+ target.setPointerCapture(event.pointerId);
407
+ this.bubbleCaptureTarget = target;
408
+ this.activeBubblePointerId = event.pointerId;
409
+ this.bubbleDragStartMouseY = event.clientY;
410
+ this.bubbleDragStartOffset = this.BubbleOffsetY;
411
+ this.bubbleDragMoved = false;
412
+ this.IsBubblePressed = true;
413
+ this.cdr.detectChanges();
414
+ document.addEventListener('pointermove', this.onBubbleDragMove);
415
+ document.addEventListener('pointerup', this.onBubbleDragEnd);
416
+ document.addEventListener('pointercancel', this.onBubbleDragEnd);
417
+ }
418
+ onBubbleDragMove = (event) => {
419
+ if (event.pointerId !== this.activeBubblePointerId)
420
+ return;
421
+ const deltaY = this.bubbleDragStartMouseY - event.clientY; // dragging up = positive
422
+ if (!this.bubbleDragMoved) {
423
+ if (Math.abs(deltaY) < ChatAgentsOverlayComponent.BUBBLE_DRAG_THRESHOLD_PX)
424
+ return;
425
+ this.bubbleDragMoved = true;
426
+ this.IsBubbleDragging = true;
427
+ }
428
+ this.BubbleOffsetY = this.clampBubbleOffsetY(this.bubbleDragStartOffset + deltaY);
429
+ this.cdr.detectChanges();
430
+ };
431
+ onBubbleDragEnd = (event) => {
432
+ if (event.pointerId !== this.activeBubblePointerId)
433
+ return;
434
+ this.removeBubbleDragListeners();
435
+ if (this.bubbleCaptureTarget) {
436
+ // Browser may have implicitly released capture on pointerup already (per the
437
+ // Pointer Events spec). releasePointerCapture throws in that race; safe to ignore.
438
+ try {
439
+ this.bubbleCaptureTarget.releasePointerCapture(event.pointerId);
440
+ }
441
+ catch { /* noop */ }
442
+ }
443
+ this.bubbleCaptureTarget = null;
444
+ this.activeBubblePointerId = null;
445
+ const wasDragged = this.bubbleDragMoved;
446
+ const wasCancelled = event.type === 'pointercancel';
447
+ this.bubbleDragMoved = false;
448
+ this.IsBubbleDragging = false;
449
+ this.IsBubblePressed = false;
450
+ if (wasDragged) {
451
+ this.savePreferences();
452
+ this.cdr.detectChanges();
453
+ }
454
+ else if (!wasCancelled) {
455
+ this.Toggle();
456
+ }
457
+ else {
458
+ this.cdr.detectChanges();
459
+ }
460
+ };
461
+ removeBubbleDragListeners() {
462
+ document.removeEventListener('pointermove', this.onBubbleDragMove);
463
+ document.removeEventListener('pointerup', this.onBubbleDragEnd);
464
+ document.removeEventListener('pointercancel', this.onBubbleDragEnd);
465
+ }
466
+ /**
467
+ * Reserved space at the top of the viewport — host-supplied chrome plus
468
+ * the padding gap we always keep above the bubble/panel.
469
+ */
470
+ get topReservedPx() {
471
+ return Math.max(0, this.TopBoundaryPx) + ChatAgentsOverlayComponent.VIEWPORT_TOP_PADDING_PX;
472
+ }
473
+ /** Clamp the offset so the bubble stays fully visible below the top boundary. */
474
+ clampBubbleOffsetY(value) {
475
+ const maxOffset = window.innerHeight
476
+ - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX
477
+ - ChatAgentsOverlayComponent.BASE_BOTTOM_PX
478
+ - this.topReservedPx;
479
+ return Math.max(0, Math.min(Math.max(0, maxOffset), value));
480
+ }
481
+ // --- Render Position Getters ---
482
+ /** Effective `bottom` (px) for the floating bubble, clamped to the current viewport. */
483
+ get BubbleBottomPx() {
484
+ const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;
485
+ const max = window.innerHeight
486
+ - ChatAgentsOverlayComponent.BUBBLE_SIZE_PX
487
+ - this.topReservedPx;
488
+ return Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, Math.min(ideal, Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, max)));
489
+ }
490
+ /**
491
+ * Effective `bottom` (px) for the expanded panel. Anchors to the bubble's
492
+ * current bottom edge so the panel grows up from where the user parked the
493
+ * bubble, but clamps downward whenever the panel would otherwise extend
494
+ * past the viewport's top boundary — that's the "reposition lower so the
495
+ * chat interface stays visible" behavior.
496
+ */
497
+ get PanelBottomPx() {
498
+ const ideal = ChatAgentsOverlayComponent.BASE_BOTTOM_PX + this.BubbleOffsetY;
499
+ const maxBottomForVisibility = window.innerHeight
500
+ - this.PanelHeight
501
+ - this.topReservedPx;
502
+ return Math.max(ChatAgentsOverlayComponent.BASE_BOTTOM_PX, Math.min(ideal, maxBottomForVisibility));
503
+ }
345
504
  // --- Private Methods ---
346
505
  /** Auto-resolve CurrentUser and EnvironmentId from Metadata when not provided as inputs */
347
506
  resolveDefaults() {
@@ -353,8 +512,8 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
353
512
  this.EnvironmentId = MJEnvironmentEntityExtended.DefaultEnvironmentID;
354
513
  }
355
514
  }
356
- /** Load saved panel size from UserInfoEngine */
357
- loadSizePreferences() {
515
+ /** Load saved panel size and bubble position from UserInfoEngine */
516
+ loadPreferences() {
358
517
  try {
359
518
  const engine = UserInfoEngine.Instance;
360
519
  const raw = engine.GetSetting(ChatAgentsOverlayComponent.SIZE_SETTING_KEY);
@@ -362,17 +521,21 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
362
521
  const prefs = JSON.parse(raw);
363
522
  this.PanelWidth = this.clampWidth(prefs.width);
364
523
  this.PanelHeight = this.clampHeight(prefs.height);
524
+ if (typeof prefs.bubbleOffsetY === 'number') {
525
+ this.BubbleOffsetY = Math.max(0, prefs.bubbleOffsetY);
526
+ }
365
527
  }
366
528
  }
367
529
  catch {
368
530
  // Use defaults on error
369
531
  }
370
532
  }
371
- /** Persist panel size to UserInfoEngine (debounced) */
372
- saveSizePreferences() {
533
+ /** Persist panel size and bubble position to UserInfoEngine (debounced) */
534
+ savePreferences() {
373
535
  const prefs = {
374
536
  width: this.PanelWidth,
375
- height: this.PanelHeight
537
+ height: this.PanelHeight,
538
+ bubbleOffsetY: this.BubbleOffsetY
376
539
  };
377
540
  UserInfoEngine.Instance.SetSettingDebounced(ChatAgentsOverlayComponent.SIZE_SETTING_KEY, JSON.stringify(prefs));
378
541
  }
@@ -424,15 +587,15 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
424
587
  });
425
588
  }
426
589
  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 Chat", 1, "chat-overlay-bubble"], [1, "chat-overlay-panel", 3, "maximized", "width", "height"], ["title", "Open Chat", 1, "chat-overlay-bubble", 3, "click"], [1, "fa-solid", "fa-comments", "chat-overlay-bubble-icon"], [1, "chat-overlay-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) {
590
+ 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"], [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"], [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) {
428
591
  i0.ɵɵconditionalCreate(0, ChatAgentsOverlayComponent_Conditional_0_Template, 2, 2);
429
592
  } if (rf & 2) {
430
593
  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: 999;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: _ngcontent-%COMP%_overlayBubbleIn 0.3s ease;\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@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.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: 999;\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@media (max-width: 480px) {\n .chat-overlay-panel[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n bottom: 1rem;\n right: 1rem;\n }\n\n .resize-handle[_ngcontent-%COMP%] {\n display: none;\n }\n}"] });
594
+ } }, 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.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}"] });
432
595
  }
433
596
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ChatAgentsOverlayComponent, [{
434
597
  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"] }]
598
+ 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\"\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 </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 [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/* --- 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"] }]
436
599
  }], null, { IsVisible: [{
437
600
  type: Input
438
601
  }], CurrentUser: [{
@@ -443,6 +606,8 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
443
606
  type: Input
444
607
  }], EmptyStateGreeting: [{
445
608
  type: Input
609
+ }], TopBoundaryPx: [{
610
+ type: Input
446
611
  }], VisibilityChanged: [{
447
612
  type: Output
448
613
  }], ToolExecuted: [{
@@ -458,5 +623,5 @@ export class ChatAgentsOverlayComponent extends BaseAngularComponent {
458
623
  }], TaskClicked: [{
459
624
  type: Output
460
625
  }] }); })();
461
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ChatAgentsOverlayComponent, { className: "ChatAgentsOverlayComponent", filePath: "src/lib/components/overlay/chat-overlay.component.ts", lineNumber: 59 }); })();
626
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ChatAgentsOverlayComponent, { className: "ChatAgentsOverlayComponent", filePath: "src/lib/components/overlay/chat-overlay.component.ts", lineNumber: 61 }); })();
462
627
  //# sourceMappingURL=chat-overlay.component.js.map