@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.
Files changed (79) hide show
  1. package/README.md +2 -2
  2. package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts +47 -0
  3. package/dist/lib/components/conversation/conversation-agent-picker.component.d.ts.map +1 -0
  4. package/dist/lib/components/conversation/conversation-agent-picker.component.js +253 -0
  5. package/dist/lib/components/conversation/conversation-agent-picker.component.js.map +1 -0
  6. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +201 -4
  7. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  8. package/dist/lib/components/conversation/conversation-chat-area.component.js +776 -263
  9. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  10. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +2 -1
  11. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  12. package/dist/lib/components/conversation/conversation-empty-state.component.js +6 -3
  13. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  14. package/dist/lib/components/conversation/conversation-mode-picker.component.d.ts +57 -0
  15. package/dist/lib/components/conversation/conversation-mode-picker.component.d.ts.map +1 -0
  16. package/dist/lib/components/conversation/conversation-mode-picker.component.js +252 -0
  17. package/dist/lib/components/conversation/conversation-mode-picker.component.js.map +1 -0
  18. package/dist/lib/components/dialogs/rating-dialog.component.d.ts +31 -0
  19. package/dist/lib/components/dialogs/rating-dialog.component.d.ts.map +1 -0
  20. package/dist/lib/components/dialogs/rating-dialog.component.js +290 -0
  21. package/dist/lib/components/dialogs/rating-dialog.component.js.map +1 -0
  22. package/dist/lib/components/mention/mention-editor.component.d.ts +1 -1
  23. package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
  24. package/dist/lib/components/mention/mention-editor.component.js +1 -0
  25. package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
  26. package/dist/lib/components/message/conversation-message-rating.component.d.ts +43 -18
  27. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  28. package/dist/lib/components/message/conversation-message-rating.component.js +235 -193
  29. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  30. package/dist/lib/components/message/message-input-box.component.d.ts +1 -1
  31. package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
  32. package/dist/lib/components/message/message-input-box.component.js +1 -1
  33. package/dist/lib/components/message/message-input-box.component.js.map +1 -1
  34. package/dist/lib/components/message/message-input.component.d.ts +58 -4
  35. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  36. package/dist/lib/components/message/message-input.component.js +135 -21
  37. package/dist/lib/components/message/message-input.component.js.map +1 -1
  38. package/dist/lib/components/message/message-item.component.d.ts +0 -13
  39. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  40. package/dist/lib/components/message/message-item.component.js +126 -152
  41. package/dist/lib/components/message/message-item.component.js.map +1 -1
  42. package/dist/lib/components/overlay/chat-overlay.component.d.ts +88 -5
  43. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  44. package/dist/lib/components/overlay/chat-overlay.component.js +296 -54
  45. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  46. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +11 -0
  47. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  48. package/dist/lib/components/workspace/conversation-workspace.component.js +13 -3
  49. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  50. package/dist/lib/conversations.module.d.ts +59 -57
  51. package/dist/lib/conversations.module.d.ts.map +1 -1
  52. package/dist/lib/conversations.module.js +12 -4
  53. package/dist/lib/conversations.module.js.map +1 -1
  54. package/dist/lib/models/conversation-state.model.d.ts +0 -27
  55. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  56. package/dist/lib/models/conversation-state.model.js.map +1 -1
  57. package/dist/lib/services/conversation-agent.service.d.ts +1 -9
  58. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  59. package/dist/lib/services/conversation-agent.service.js +22 -121
  60. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  61. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  62. package/dist/lib/services/conversation-attachment.service.js +5 -26
  63. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  64. package/dist/lib/services/conversation-bridge.service.d.ts +13 -0
  65. package/dist/lib/services/conversation-bridge.service.d.ts.map +1 -1
  66. package/dist/lib/services/conversation-bridge.service.js +15 -0
  67. package/dist/lib/services/conversation-bridge.service.js.map +1 -1
  68. package/dist/lib/services/data-cache.service.d.ts.map +1 -1
  69. package/dist/lib/services/data-cache.service.js +0 -1
  70. package/dist/lib/services/data-cache.service.js.map +1 -1
  71. package/dist/lib/services/dialog.service.d.ts +24 -0
  72. package/dist/lib/services/dialog.service.d.ts.map +1 -1
  73. package/dist/lib/services/dialog.service.js +45 -0
  74. package/dist/lib/services/dialog.service.js.map +1 -1
  75. package/package.json +23 -22
  76. package/dist/lib/components/message/suggested-responses.component.d.ts +0 -55
  77. package/dist/lib/components/message/suggested-responses.component.d.ts.map +0 -1
  78. package/dist/lib/components/message/suggested-responses.component.js +0 -207
  79. package/dist/lib/components/message/suggested-responses.component.js.map +0 -1
@@ -7,6 +7,7 @@ export declare class ConversationEmptyStateComponent {
7
7
  disabled: boolean;
8
8
  showSidebarToggle: boolean;
9
9
  enableAttachments: boolean;
10
+ enableMentions: boolean;
10
11
  maxAttachments: number;
11
12
  maxAttachmentSizeBytes: number;
12
13
  acceptedFileTypes: string;
@@ -45,6 +46,6 @@ export declare class ConversationEmptyStateComponent {
45
46
  }): void;
46
47
  onSuggestedPromptClicked(prompt: string): void;
47
48
  static ɵfac: i0.ɵɵFactoryDeclaration<ConversationEmptyStateComponent, never>;
48
- static ɵcmp: i0.ɵɵComponentDeclaration<ConversationEmptyStateComponent, "mj-conversation-empty-state", never, { "currentUser": { "alias": "currentUser"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "showSidebarToggle": { "alias": "showSidebarToggle"; "required": false; }; "enableAttachments": { "alias": "enableAttachments"; "required": false; }; "maxAttachments": { "alias": "maxAttachments"; "required": false; }; "maxAttachmentSizeBytes": { "alias": "maxAttachmentSizeBytes"; "required": false; }; "acceptedFileTypes": { "alias": "acceptedFileTypes"; "required": false; }; "greeting": { "alias": "greeting"; "required": false; }; "overlayMode": { "alias": "overlayMode"; "required": false; }; }, { "messageSent": "messageSent"; "sidebarToggleClicked": "sidebarToggleClicked"; }, never, never, false, never>;
49
+ static ɵcmp: i0.ɵɵComponentDeclaration<ConversationEmptyStateComponent, "mj-conversation-empty-state", never, { "currentUser": { "alias": "currentUser"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "showSidebarToggle": { "alias": "showSidebarToggle"; "required": false; }; "enableAttachments": { "alias": "enableAttachments"; "required": false; }; "enableMentions": { "alias": "enableMentions"; "required": false; }; "maxAttachments": { "alias": "maxAttachments"; "required": false; }; "maxAttachmentSizeBytes": { "alias": "maxAttachmentSizeBytes"; "required": false; }; "acceptedFileTypes": { "alias": "acceptedFileTypes"; "required": false; }; "greeting": { "alias": "greeting"; "required": false; }; "overlayMode": { "alias": "overlayMode"; "required": false; }; }, { "messageSent": "messageSent"; "sidebarToggleClicked": "sidebarToggleClicked"; }, never, never, false, never>;
49
50
  }
50
51
  //# sourceMappingURL=conversation-empty-state.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-empty-state.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/conversation/conversation-empty-state.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAa,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;;AAGxE,qBAMa,+BAA+B;IACjC,WAAW,EAAG,QAAQ,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAS;IAC1B,iBAAiB,EAAE,OAAO,CAAS;IACnC,iBAAiB,EAAE,OAAO,CAAS;IACnC,cAAc,EAAE,MAAM,CAAM;IAC5B,sBAAsB,EAAE,MAAM,CAAoB;IAClD,iBAAiB,EAAE,MAAM,CAAa;IAE/C,2FAA2F;IAClF,QAAQ,EAAE,MAAM,CAAyB;IAElD,8EAA8E;IAC9E,OAAO,CAAC,YAAY,CAAS;IAC7B,IACI,WAAW,CAAC,KAAK,EAAE,OAAO,EAK7B;IACD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEiC,OAAO,CAAC,YAAY,CAAC,CAAwB;IAErE,WAAW;cAA2B,MAAM;qBAAe,iBAAiB,EAAE;OAAK;IACnF,oBAAoB,qBAA4B;IAEnD,WAAW,EAAE,MAAM,CAAM;IAGhC,OAAO,CAAC,mBAAmB,CA0GzB;IAGK,gBAAgB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAM;;IAOnF;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAK3B;;;OAGG;IACI,UAAU,IAAI,IAAI;IAQzB,kBAAkB,CAAC,KAAK,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,iBAAiB,EAAE,CAAA;KAAC,GAAG,IAAI;IAIjF,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;yCA7KnC,+BAA+B;2CAA/B,+BAA+B;CAkL3C"}
1
+ {"version":3,"file":"conversation-empty-state.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/conversation/conversation-empty-state.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAa,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;;AAGxE,qBAMa,+BAA+B;IACjC,WAAW,EAAG,QAAQ,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAS;IAC1B,iBAAiB,EAAE,OAAO,CAAS;IACnC,iBAAiB,EAAE,OAAO,CAAS;IACnC,cAAc,EAAE,OAAO,CAAQ;IAC/B,cAAc,EAAE,MAAM,CAAM;IAC5B,sBAAsB,EAAE,MAAM,CAAoB;IAClD,iBAAiB,EAAE,MAAM,CAAa;IAE/C,2FAA2F;IAClF,QAAQ,EAAE,MAAM,CAAyB;IAElD,8EAA8E;IAC9E,OAAO,CAAC,YAAY,CAAS;IAC7B,IACI,WAAW,CAAC,KAAK,EAAE,OAAO,EAK7B;IACD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEiC,OAAO,CAAC,YAAY,CAAC,CAAwB;IAErE,WAAW;cAA2B,MAAM;qBAAe,iBAAiB,EAAE;OAAK;IACnF,oBAAoB,qBAA4B;IAEnD,WAAW,EAAE,MAAM,CAAM;IAGhC,OAAO,CAAC,mBAAmB,CA0GzB;IAGK,gBAAgB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAAC,CAAM;;IAOnF;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAK3B;;;OAGG;IACI,UAAU,IAAI,IAAI;IAQzB,kBAAkB,CAAC,KAAK,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,iBAAiB,EAAE,CAAA;KAAC,GAAG,IAAI;IAIjF,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;yCA9KnC,+BAA+B;2CAA/B,+BAA+B;CAmL3C"}
@@ -97,6 +97,7 @@ export class ConversationEmptyStateComponent {
97
97
  disabled = false;
98
98
  showSidebarToggle = false;
99
99
  enableAttachments = false;
100
+ enableMentions = true;
100
101
  maxAttachments = 10;
101
102
  maxAttachmentSizeBytes = 20 * 1024 * 1024;
102
103
  acceptedFileTypes = 'image/*';
@@ -261,7 +262,7 @@ export class ConversationEmptyStateComponent {
261
262
  } if (rf & 2) {
262
263
  let _t;
263
264
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.messageInput = _t.first);
264
- } }, inputs: { currentUser: "currentUser", disabled: "disabled", showSidebarToggle: "showSidebarToggle", enableAttachments: "enableAttachments", maxAttachments: "maxAttachments", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", acceptedFileTypes: "acceptedFileTypes", greeting: "greeting", overlayMode: "overlayMode" }, outputs: { messageSent: "messageSent", sidebarToggleClicked: "sidebarToggleClicked" }, standalone: false, decls: 10, vars: 18, consts: [[1, "conversation-empty-state"], ["title", "Show conversations", 1, "sidebar-toggle-btn"], [1, "loading-overlay"], [1, "empty-state-container"], [1, "greeting-section"], [1, "suggested-prompts"], [1, "overlay-greeting"], [1, "message-input-wrapper"], [3, "emptyStateSubmit", "placeholder", "disabled", "currentUser", "emptyStateMode", "enableAttachments", "maxAttachments", "maxAttachmentSizeBytes", "acceptedFileTypes"], [1, "tips-section"], ["title", "Show conversations", 1, "sidebar-toggle-btn", 3, "click"], [1, "fas", "fa-table-columns"], ["text", "Creating your conversation...", "size", "large"], [1, "greeting-icon"], [1, "fa-solid", "fa-comments", "fa-3x"], [1, "greeting-title"], [1, "greeting-subtitle"], [1, "prompt-grid"], [1, "prompt-card", 3, "disabled"], [1, "prompt-card", 3, "click"], [1, "prompt-icon"], [1, "prompt-content"], [1, "prompt-title"], [1, "prompt-text"], [1, "overlay-greeting-text"], [1, "tip-item"], [1, "fa-solid", "fa-at"], [1, "fa-solid", "fa-keyboard"]], template: function ConversationEmptyStateComponent_Template(rf, ctx) { if (rf & 1) {
265
+ } }, inputs: { currentUser: "currentUser", disabled: "disabled", showSidebarToggle: "showSidebarToggle", enableAttachments: "enableAttachments", enableMentions: "enableMentions", maxAttachments: "maxAttachments", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", acceptedFileTypes: "acceptedFileTypes", greeting: "greeting", overlayMode: "overlayMode" }, outputs: { messageSent: "messageSent", sidebarToggleClicked: "sidebarToggleClicked" }, standalone: false, decls: 10, vars: 19, consts: [[1, "conversation-empty-state"], ["title", "Show conversations", 1, "sidebar-toggle-btn"], [1, "loading-overlay"], [1, "empty-state-container"], [1, "greeting-section"], [1, "suggested-prompts"], [1, "overlay-greeting"], [1, "message-input-wrapper"], [3, "emptyStateSubmit", "placeholder", "disabled", "currentUser", "emptyStateMode", "enableMentions", "enableAttachments", "maxAttachments", "maxAttachmentSizeBytes", "acceptedFileTypes"], [1, "tips-section"], ["title", "Show conversations", 1, "sidebar-toggle-btn", 3, "click"], [1, "fas", "fa-table-columns"], ["text", "Creating your conversation...", "size", "large"], [1, "greeting-icon"], [1, "fa-solid", "fa-comments", "fa-3x"], [1, "greeting-title"], [1, "greeting-subtitle"], [1, "prompt-grid"], [1, "prompt-card", 3, "disabled"], [1, "prompt-card", 3, "click"], [1, "prompt-icon"], [1, "prompt-content"], [1, "prompt-title"], [1, "prompt-text"], [1, "overlay-greeting-text"], [1, "tip-item"], [1, "fa-solid", "fa-at"], [1, "fa-solid", "fa-keyboard"]], template: function ConversationEmptyStateComponent_Template(rf, ctx) { if (rf & 1) {
265
266
  i0.ɵɵelementStart(0, "div", 0);
266
267
  i0.ɵɵconditionalCreate(1, ConversationEmptyStateComponent_Conditional_1_Template, 2, 0, "button", 1);
267
268
  i0.ɵɵconditionalCreate(2, ConversationEmptyStateComponent_Conditional_2_Template, 2, 0, "div", 2);
@@ -289,14 +290,14 @@ export class ConversationEmptyStateComponent {
289
290
  i0.ɵɵadvance();
290
291
  i0.ɵɵconditional(ctx.overlayMode ? 6 : -1);
291
292
  i0.ɵɵadvance(2);
292
- i0.ɵɵproperty("placeholder", ctx.overlayMode ? "Type a message..." : "Type your message to start a new conversation...")("disabled", ctx.disabled)("currentUser", ctx.currentUser)("emptyStateMode", true)("enableAttachments", ctx.enableAttachments)("maxAttachments", ctx.maxAttachments)("maxAttachmentSizeBytes", ctx.maxAttachmentSizeBytes)("acceptedFileTypes", ctx.acceptedFileTypes);
293
+ i0.ɵɵproperty("placeholder", ctx.overlayMode ? "Type a message..." : "Type your message to start a new conversation...")("disabled", ctx.disabled)("currentUser", ctx.currentUser)("emptyStateMode", true)("enableMentions", ctx.enableMentions)("enableAttachments", ctx.enableAttachments)("maxAttachments", ctx.maxAttachments)("maxAttachmentSizeBytes", ctx.maxAttachmentSizeBytes)("acceptedFileTypes", ctx.acceptedFileTypes);
293
294
  i0.ɵɵadvance();
294
295
  i0.ɵɵconditional(!ctx.overlayMode ? 9 : -1);
295
296
  } }, dependencies: [i1.LoadingComponent, i2.MessageInputComponent], styles: ["[_nghost-%COMP%] {\n display: flex;\n flex: 1;\n height: 100%;\n min-height: 0;\n}\n\n.conversation-empty-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n width: 100%;\n padding: 2rem;\n overflow-y: auto;\n position: relative;\n}\n\n\n\n.sidebar-toggle-btn[_ngcontent-%COMP%] {\n position: absolute;\n top: 12px;\n left: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n z-index: 10;\n}\n\n.sidebar-toggle-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.sidebar-toggle-btn[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n}\n\n.sidebar-toggle-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: color 0.15s ease;\n}\n\n.sidebar-toggle-btn[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n}\n@media (max-width: 768px) {\n .conversation-empty-state[_ngcontent-%COMP%] {\n align-items: flex-start;\n padding: 1rem 0.75rem;\n }\n}\n\n.loading-overlay[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease-in;\n}\n\n.loading-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n padding: 2rem;\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n box-shadow: 0 4px 20px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n.loading-content[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.loading-message[_ngcontent-%COMP%] {\n font-size: 1rem;\n color: var(--mj-text-primary);\n font-weight: 500;\n margin: 0;\n}\n\n.empty-state-container[_ngcontent-%COMP%] {\n max-width: 800px;\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 2rem;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease-in;\n transition: opacity 0.2s ease;\n}\n.empty-state-container.loading[_ngcontent-%COMP%] {\n opacity: 0.4;\n pointer-events: none;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n.greeting-section[_ngcontent-%COMP%] {\n text-align: center;\n padding: 2rem 0;\n}\n\n.greeting-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n margin-bottom: 1rem;\n opacity: 0.8;\n}\n\n.greeting-title[_ngcontent-%COMP%] {\n font-size: 2rem;\n font-weight: 600;\n margin: 0 0 0.5rem 0;\n color: var(--mj-text-primary);\n}\n\n.greeting-subtitle[_ngcontent-%COMP%] {\n font-size: 1rem;\n color: var(--mj-text-secondary);\n margin: 0;\n line-height: 1.5;\n}\n\n\n\n.suggested-prompts[_ngcontent-%COMP%] {\n margin: 1rem 0;\n}\n\n.prompt-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n gap: 1rem;\n}\n\n.prompt-card[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 1rem;\n padding: 1.25rem;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n.prompt-card[_ngcontent-%COMP%]:hover:not(.disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-brand-primary);\n transform: translateY(-2px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n.prompt-card.disabled[_ngcontent-%COMP%] {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.prompt-icon[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 1.2rem;\n}\n\n.prompt-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.prompt-title[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.95rem;\n color: var(--mj-text-primary);\n margin-bottom: 0.25rem;\n}\n\n.prompt-text[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n color: var(--mj-text-secondary);\n line-height: 1.4;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n\n\n.message-input-wrapper[_ngcontent-%COMP%] {\n margin: 1.5rem 0;\n width: 100%;\n}\n\n\n\n.tips-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding: 1rem 0;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.tip-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n}\n.tip-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 24px;\n text-align: center;\n color: var(--mj-brand-primary);\n opacity: 0.7;\n}\n.tip-item[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n\n\n.conversation-empty-state.overlay-mode[_ngcontent-%COMP%] {\n padding: 1rem;\n align-items: center;\n justify-content: center;\n}\n\n.overlay-mode[_ngcontent-%COMP%] .empty-state-container[_ngcontent-%COMP%] {\n gap: 0.75rem;\n max-width: 100%;\n justify-content: center;\n}\n\n.overlay-greeting[_ngcontent-%COMP%] {\n text-align: center;\n padding: 1rem 0 0;\n}\n\n.overlay-greeting-text[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.overlay-mode[_ngcontent-%COMP%] .message-input-wrapper[_ngcontent-%COMP%] {\n margin: 0.5rem 0;\n}\n\n\n\n@media (max-width: 768px) {\n .empty-state-container[_ngcontent-%COMP%] {\n gap: 0.75rem;\n }\n .greeting-section[_ngcontent-%COMP%] {\n padding: 0.25rem 0;\n }\n .greeting-icon[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n margin-bottom: 0.25rem;\n }\n .greeting-title[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n }\n .greeting-subtitle[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n padding: 0 0.5rem;\n }\n .prompt-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n }\n .prompt-card[_ngcontent-%COMP%] {\n padding: 0.5rem;\n flex-direction: column;\n gap: 0.5rem;\n }\n .prompt-icon[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n font-size: 0.85rem;\n }\n .prompt-title[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n }\n .prompt-text[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n -webkit-line-clamp: 1;\n }\n .message-input-wrapper[_ngcontent-%COMP%] {\n margin: 0.5rem 0;\n }\n .tips-section[_ngcontent-%COMP%] {\n display: none;\n }\n .loading-content[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n .loading-message[_ngcontent-%COMP%] {\n font-size: 0.85rem;\n }\n}\n\n\n@media (max-width: 480px) {\n .empty-state-container[_ngcontent-%COMP%] {\n gap: 0.5rem;\n }\n .greeting-section[_ngcontent-%COMP%] {\n padding: 0.25rem 0;\n }\n .greeting-icon[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n margin-bottom: 0.25rem;\n }\n .greeting-title[_ngcontent-%COMP%] {\n font-size: 1rem;\n }\n .greeting-subtitle[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n padding: 0 0.25rem;\n }\n .prompt-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 0.4rem;\n }\n .prompt-card[_ngcontent-%COMP%] {\n padding: 0.4rem;\n flex-direction: column;\n gap: 0.4rem;\n }\n .prompt-icon[_ngcontent-%COMP%] {\n width: 24px;\n height: 24px;\n font-size: 0.75rem;\n border-radius: 4px;\n }\n .prompt-title[_ngcontent-%COMP%] {\n font-size: 0.7rem;\n }\n .prompt-text[_ngcontent-%COMP%] {\n font-size: 0.65rem;\n -webkit-line-clamp: 1;\n }\n .message-input-wrapper[_ngcontent-%COMP%] {\n margin: 0.4rem 0;\n }\n .tips-section[_ngcontent-%COMP%] {\n display: none;\n }\n .loading-content[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n .loading-message[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n }\n}"] });
296
297
  }
297
298
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ConversationEmptyStateComponent, [{
298
299
  type: Component,
299
- args: [{ standalone: false, selector: 'mj-conversation-empty-state', template: "<div class=\"conversation-empty-state\" [class.overlay-mode]=\"overlayMode\">\n <!-- Sidebar Toggle Button (top-left when sidebar is collapsed) -->\n @if (showSidebarToggle) {\n <button class=\"sidebar-toggle-btn\"\n (click)=\"sidebarToggleClicked.emit()\"\n title=\"Show conversations\">\n <i class=\"fas fa-table-columns\"></i>\n </button>\n }\n\n <!-- Loading Overlay -->\n @if (disabled) {\n <div class=\"loading-overlay\">\n <mj-loading text=\"Creating your conversation...\" size=\"large\"></mj-loading>\n </div>\n }\n\n <div class=\"empty-state-container\" [class.loading]=\"disabled\">\n <!-- Greeting Header (hidden in overlay mode) -->\n @if (!overlayMode) {\n <div class=\"greeting-section\">\n <div class=\"greeting-icon\">\n <i class=\"fa-solid fa-comments fa-3x\"></i>\n </div>\n <h1 class=\"greeting-title\">Welcome to Conversations</h1>\n <p class=\"greeting-subtitle\">\n Start a new conversation by typing a message below, or choose a suggested prompt to get started.\n </p>\n </div>\n }\n\n <!-- Suggested Prompts (hidden in overlay mode) -->\n @if (suggestedPrompts.length > 0) {\n <div class=\"suggested-prompts\">\n <div class=\"prompt-grid\">\n @for (prompt of suggestedPrompts; track prompt) {\n <div\n class=\"prompt-card\"\n (click)=\"onSuggestedPromptClicked(prompt.prompt)\"\n [class.disabled]=\"disabled\"\n >\n <div class=\"prompt-icon\">\n <i class=\"fa-solid {{prompt.icon}}\"></i>\n </div>\n <div class=\"prompt-content\">\n <div class=\"prompt-title\">{{prompt.title}}</div>\n <div class=\"prompt-text\">{{prompt.prompt}}</div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Compact greeting for overlay mode -->\n @if (overlayMode) {\n <div class=\"overlay-greeting\">\n <p class=\"overlay-greeting-text\">{{ greeting }}</p>\n </div>\n }\n\n <!-- Message Input (using full mj-message-input in empty state mode) -->\n <div class=\"message-input-wrapper\">\n <mj-message-input\n [placeholder]=\"overlayMode ? 'Type a message...' : 'Type your message to start a new conversation...'\"\n [disabled]=\"disabled\"\n [currentUser]=\"currentUser\"\n [emptyStateMode]=\"true\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n (emptyStateSubmit)=\"onEmptyStateSubmit($event)\">\n </mj-message-input>\n </div>\n\n <!-- Footer Tips (hidden in overlay mode) -->\n @if (!overlayMode) {\n <div class=\"tips-section\">\n <div class=\"tip-item\">\n <i class=\"fa-solid fa-at\"></i>\n <span>Use <strong>&#64;AgentName</strong> to directly invoke a specific agent</span>\n </div>\n <div class=\"tip-item\">\n <i class=\"fa-solid fa-keyboard\"></i>\n <span>Press <strong>Enter</strong> to send, <strong>Shift+Enter</strong> for new line</span>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host {\n display: flex;\n flex: 1;\n height: 100%;\n min-height: 0;\n}\n\n.conversation-empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n width: 100%;\n padding: 2rem;\n overflow-y: auto;\n position: relative;\n}\n\n/* Sidebar toggle button - positioned in top-left */\n.sidebar-toggle-btn {\n position: absolute;\n top: 12px;\n left: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n z-index: 10;\n}\n\n.sidebar-toggle-btn:hover {\n background: color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.sidebar-toggle-btn:active {\n background: color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n}\n\n.sidebar-toggle-btn i {\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: color 0.15s ease;\n}\n\n.sidebar-toggle-btn:hover i {\n color: var(--mj-text-primary);\n}\n@media (max-width: 768px) {\n .conversation-empty-state {\n align-items: flex-start;\n padding: 1rem 0.75rem;\n }\n}\n\n.loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n animation: fadeIn 0.2s ease-in;\n}\n\n.loading-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n padding: 2rem;\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n box-shadow: 0 4px 20px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n.loading-content i {\n color: var(--mj-brand-primary);\n}\n\n.loading-message {\n font-size: 1rem;\n color: var(--mj-text-primary);\n font-weight: 500;\n margin: 0;\n}\n\n.empty-state-container {\n max-width: 800px;\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 2rem;\n animation: fadeIn 0.3s ease-in;\n transition: opacity 0.2s ease;\n}\n.empty-state-container.loading {\n opacity: 0.4;\n pointer-events: none;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n/* Greeting Section */\n.greeting-section {\n text-align: center;\n padding: 2rem 0;\n}\n\n.greeting-icon {\n color: var(--mj-brand-primary);\n margin-bottom: 1rem;\n opacity: 0.8;\n}\n\n.greeting-title {\n font-size: 2rem;\n font-weight: 600;\n margin: 0 0 0.5rem 0;\n color: var(--mj-text-primary);\n}\n\n.greeting-subtitle {\n font-size: 1rem;\n color: var(--mj-text-secondary);\n margin: 0;\n line-height: 1.5;\n}\n\n/* Suggested Prompts */\n.suggested-prompts {\n margin: 1rem 0;\n}\n\n.prompt-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n gap: 1rem;\n}\n\n.prompt-card {\n display: flex;\n align-items: flex-start;\n gap: 1rem;\n padding: 1.25rem;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n.prompt-card:hover:not(.disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-brand-primary);\n transform: translateY(-2px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n.prompt-card.disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.prompt-icon {\n flex-shrink: 0;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 1.2rem;\n}\n\n.prompt-content {\n flex: 1;\n min-width: 0;\n}\n\n.prompt-title {\n font-weight: 600;\n font-size: 0.95rem;\n color: var(--mj-text-primary);\n margin-bottom: 0.25rem;\n}\n\n.prompt-text {\n font-size: 0.85rem;\n color: var(--mj-text-secondary);\n line-height: 1.4;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n/* Message Input Wrapper */\n.message-input-wrapper {\n margin: 1.5rem 0;\n width: 100%;\n}\n\n/* Tips Section */\n.tips-section {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding: 1rem 0;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.tip-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n}\n.tip-item i {\n flex-shrink: 0;\n width: 24px;\n text-align: center;\n color: var(--mj-brand-primary);\n opacity: 0.7;\n}\n.tip-item strong {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n/* Overlay Mode \u2014 compact layout for floating chat widget */\n.conversation-empty-state.overlay-mode {\n padding: 1rem;\n align-items: center;\n justify-content: center;\n}\n\n.overlay-mode .empty-state-container {\n gap: 0.75rem;\n max-width: 100%;\n justify-content: center;\n}\n\n.overlay-greeting {\n text-align: center;\n padding: 1rem 0 0;\n}\n\n.overlay-greeting-text {\n font-size: 1.1rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.overlay-mode .message-input-wrapper {\n margin: 0.5rem 0;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .empty-state-container {\n gap: 0.75rem;\n }\n .greeting-section {\n padding: 0.25rem 0;\n }\n .greeting-icon {\n font-size: 1.5rem;\n margin-bottom: 0.25rem;\n }\n .greeting-title {\n font-size: 1.1rem;\n }\n .greeting-subtitle {\n font-size: 0.75rem;\n padding: 0 0.5rem;\n }\n .prompt-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n }\n .prompt-card {\n padding: 0.5rem;\n flex-direction: column;\n gap: 0.5rem;\n }\n .prompt-icon {\n width: 28px;\n height: 28px;\n font-size: 0.85rem;\n }\n .prompt-title {\n font-size: 0.75rem;\n }\n .prompt-text {\n font-size: 0.7rem;\n -webkit-line-clamp: 1;\n }\n .message-input-wrapper {\n margin: 0.5rem 0;\n }\n .tips-section {\n display: none;\n }\n .loading-content {\n padding: 1rem;\n }\n .loading-message {\n font-size: 0.85rem;\n }\n}\n/* Small Phone adjustments */\n@media (max-width: 480px) {\n .empty-state-container {\n gap: 0.5rem;\n }\n .greeting-section {\n padding: 0.25rem 0;\n }\n .greeting-icon {\n font-size: 1.25rem;\n margin-bottom: 0.25rem;\n }\n .greeting-title {\n font-size: 1rem;\n }\n .greeting-subtitle {\n font-size: 0.7rem;\n padding: 0 0.25rem;\n }\n .prompt-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 0.4rem;\n }\n .prompt-card {\n padding: 0.4rem;\n flex-direction: column;\n gap: 0.4rem;\n }\n .prompt-icon {\n width: 24px;\n height: 24px;\n font-size: 0.75rem;\n border-radius: 4px;\n }\n .prompt-title {\n font-size: 0.7rem;\n }\n .prompt-text {\n font-size: 0.65rem;\n -webkit-line-clamp: 1;\n }\n .message-input-wrapper {\n margin: 0.4rem 0;\n }\n .tips-section {\n display: none;\n }\n .loading-content {\n padding: 1rem;\n }\n .loading-message {\n font-size: 0.8rem;\n }\n}\n"] }]
300
+ args: [{ standalone: false, selector: 'mj-conversation-empty-state', template: "<div class=\"conversation-empty-state\" [class.overlay-mode]=\"overlayMode\">\n <!-- Sidebar Toggle Button (top-left when sidebar is collapsed) -->\n @if (showSidebarToggle) {\n <button class=\"sidebar-toggle-btn\"\n (click)=\"sidebarToggleClicked.emit()\"\n title=\"Show conversations\">\n <i class=\"fas fa-table-columns\"></i>\n </button>\n }\n\n <!-- Loading Overlay -->\n @if (disabled) {\n <div class=\"loading-overlay\">\n <mj-loading text=\"Creating your conversation...\" size=\"large\"></mj-loading>\n </div>\n }\n\n <div class=\"empty-state-container\" [class.loading]=\"disabled\">\n <!-- Greeting Header (hidden in overlay mode) -->\n @if (!overlayMode) {\n <div class=\"greeting-section\">\n <div class=\"greeting-icon\">\n <i class=\"fa-solid fa-comments fa-3x\"></i>\n </div>\n <h1 class=\"greeting-title\">Welcome to Conversations</h1>\n <p class=\"greeting-subtitle\">\n Start a new conversation by typing a message below, or choose a suggested prompt to get started.\n </p>\n </div>\n }\n\n <!-- Suggested Prompts (hidden in overlay mode) -->\n @if (suggestedPrompts.length > 0) {\n <div class=\"suggested-prompts\">\n <div class=\"prompt-grid\">\n @for (prompt of suggestedPrompts; track prompt) {\n <div\n class=\"prompt-card\"\n (click)=\"onSuggestedPromptClicked(prompt.prompt)\"\n [class.disabled]=\"disabled\"\n >\n <div class=\"prompt-icon\">\n <i class=\"fa-solid {{prompt.icon}}\"></i>\n </div>\n <div class=\"prompt-content\">\n <div class=\"prompt-title\">{{prompt.title}}</div>\n <div class=\"prompt-text\">{{prompt.prompt}}</div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Compact greeting for overlay mode -->\n @if (overlayMode) {\n <div class=\"overlay-greeting\">\n <p class=\"overlay-greeting-text\">{{ greeting }}</p>\n </div>\n }\n\n <!-- Message Input (using full mj-message-input in empty state mode) -->\n <div class=\"message-input-wrapper\">\n <mj-message-input\n [placeholder]=\"overlayMode ? 'Type a message...' : 'Type your message to start a new conversation...'\"\n [disabled]=\"disabled\"\n [currentUser]=\"currentUser\"\n [emptyStateMode]=\"true\"\n [enableMentions]=\"enableMentions\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n (emptyStateSubmit)=\"onEmptyStateSubmit($event)\">\n </mj-message-input>\n </div>\n\n <!-- Footer Tips (hidden in overlay mode) -->\n @if (!overlayMode) {\n <div class=\"tips-section\">\n <div class=\"tip-item\">\n <i class=\"fa-solid fa-at\"></i>\n <span>Use <strong>&#64;AgentName</strong> to directly invoke a specific agent</span>\n </div>\n <div class=\"tip-item\">\n <i class=\"fa-solid fa-keyboard\"></i>\n <span>Press <strong>Enter</strong> to send, <strong>Shift+Enter</strong> for new line</span>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host {\n display: flex;\n flex: 1;\n height: 100%;\n min-height: 0;\n}\n\n.conversation-empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n width: 100%;\n padding: 2rem;\n overflow-y: auto;\n position: relative;\n}\n\n/* Sidebar toggle button - positioned in top-left */\n.sidebar-toggle-btn {\n position: absolute;\n top: 12px;\n left: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n z-index: 10;\n}\n\n.sidebar-toggle-btn:hover {\n background: color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.sidebar-toggle-btn:active {\n background: color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n}\n\n.sidebar-toggle-btn i {\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: color 0.15s ease;\n}\n\n.sidebar-toggle-btn:hover i {\n color: var(--mj-text-primary);\n}\n@media (max-width: 768px) {\n .conversation-empty-state {\n align-items: flex-start;\n padding: 1rem 0.75rem;\n }\n}\n\n.loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n animation: fadeIn 0.2s ease-in;\n}\n\n.loading-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n padding: 2rem;\n background: var(--mj-bg-surface-card);\n border-radius: 12px;\n box-shadow: 0 4px 20px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n.loading-content i {\n color: var(--mj-brand-primary);\n}\n\n.loading-message {\n font-size: 1rem;\n color: var(--mj-text-primary);\n font-weight: 500;\n margin: 0;\n}\n\n.empty-state-container {\n max-width: 800px;\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 2rem;\n animation: fadeIn 0.3s ease-in;\n transition: opacity 0.2s ease;\n}\n.empty-state-container.loading {\n opacity: 0.4;\n pointer-events: none;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n/* Greeting Section */\n.greeting-section {\n text-align: center;\n padding: 2rem 0;\n}\n\n.greeting-icon {\n color: var(--mj-brand-primary);\n margin-bottom: 1rem;\n opacity: 0.8;\n}\n\n.greeting-title {\n font-size: 2rem;\n font-weight: 600;\n margin: 0 0 0.5rem 0;\n color: var(--mj-text-primary);\n}\n\n.greeting-subtitle {\n font-size: 1rem;\n color: var(--mj-text-secondary);\n margin: 0;\n line-height: 1.5;\n}\n\n/* Suggested Prompts */\n.suggested-prompts {\n margin: 1rem 0;\n}\n\n.prompt-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n gap: 1rem;\n}\n\n.prompt-card {\n display: flex;\n align-items: flex-start;\n gap: 1rem;\n padding: 1.25rem;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n.prompt-card:hover:not(.disabled) {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-brand-primary);\n transform: translateY(-2px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-text-primary) 10%, transparent);\n}\n.prompt-card.disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.prompt-icon {\n flex-shrink: 0;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-radius: 8px;\n font-size: 1.2rem;\n}\n\n.prompt-content {\n flex: 1;\n min-width: 0;\n}\n\n.prompt-title {\n font-weight: 600;\n font-size: 0.95rem;\n color: var(--mj-text-primary);\n margin-bottom: 0.25rem;\n}\n\n.prompt-text {\n font-size: 0.85rem;\n color: var(--mj-text-secondary);\n line-height: 1.4;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n/* Message Input Wrapper */\n.message-input-wrapper {\n margin: 1.5rem 0;\n width: 100%;\n}\n\n/* Tips Section */\n.tips-section {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding: 1rem 0;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.tip-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 0.875rem;\n color: var(--mj-text-secondary);\n}\n.tip-item i {\n flex-shrink: 0;\n width: 24px;\n text-align: center;\n color: var(--mj-brand-primary);\n opacity: 0.7;\n}\n.tip-item strong {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n/* Overlay Mode \u2014 compact layout for floating chat widget */\n.conversation-empty-state.overlay-mode {\n padding: 1rem;\n align-items: center;\n justify-content: center;\n}\n\n.overlay-mode .empty-state-container {\n gap: 0.75rem;\n max-width: 100%;\n justify-content: center;\n}\n\n.overlay-greeting {\n text-align: center;\n padding: 1rem 0 0;\n}\n\n.overlay-greeting-text {\n font-size: 1.1rem;\n font-weight: 500;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.overlay-mode .message-input-wrapper {\n margin: 0.5rem 0;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .empty-state-container {\n gap: 0.75rem;\n }\n .greeting-section {\n padding: 0.25rem 0;\n }\n .greeting-icon {\n font-size: 1.5rem;\n margin-bottom: 0.25rem;\n }\n .greeting-title {\n font-size: 1.1rem;\n }\n .greeting-subtitle {\n font-size: 0.75rem;\n padding: 0 0.5rem;\n }\n .prompt-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n }\n .prompt-card {\n padding: 0.5rem;\n flex-direction: column;\n gap: 0.5rem;\n }\n .prompt-icon {\n width: 28px;\n height: 28px;\n font-size: 0.85rem;\n }\n .prompt-title {\n font-size: 0.75rem;\n }\n .prompt-text {\n font-size: 0.7rem;\n -webkit-line-clamp: 1;\n }\n .message-input-wrapper {\n margin: 0.5rem 0;\n }\n .tips-section {\n display: none;\n }\n .loading-content {\n padding: 1rem;\n }\n .loading-message {\n font-size: 0.85rem;\n }\n}\n/* Small Phone adjustments */\n@media (max-width: 480px) {\n .empty-state-container {\n gap: 0.5rem;\n }\n .greeting-section {\n padding: 0.25rem 0;\n }\n .greeting-icon {\n font-size: 1.25rem;\n margin-bottom: 0.25rem;\n }\n .greeting-title {\n font-size: 1rem;\n }\n .greeting-subtitle {\n font-size: 0.7rem;\n padding: 0 0.25rem;\n }\n .prompt-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 0.4rem;\n }\n .prompt-card {\n padding: 0.4rem;\n flex-direction: column;\n gap: 0.4rem;\n }\n .prompt-icon {\n width: 24px;\n height: 24px;\n font-size: 0.75rem;\n border-radius: 4px;\n }\n .prompt-title {\n font-size: 0.7rem;\n }\n .prompt-text {\n font-size: 0.65rem;\n -webkit-line-clamp: 1;\n }\n .message-input-wrapper {\n margin: 0.4rem 0;\n }\n .tips-section {\n display: none;\n }\n .loading-content {\n padding: 1rem;\n }\n .loading-message {\n font-size: 0.8rem;\n }\n}\n"] }]
300
301
  }], () => [], { currentUser: [{
301
302
  type: Input
302
303
  }], disabled: [{
@@ -305,6 +306,8 @@ export class ConversationEmptyStateComponent {
305
306
  type: Input
306
307
  }], enableAttachments: [{
307
308
  type: Input
309
+ }], enableMentions: [{
310
+ type: Input
308
311
  }], maxAttachments: [{
309
312
  type: Input
310
313
  }], maxAttachmentSizeBytes: [{
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-empty-state.component.js","sourceRoot":"","sources":["../../../../src/lib/components/conversation/conversation-empty-state.component.ts","../../../../src/lib/components/conversation/conversation-empty-state.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';\nimport { UserInfo } from '@memberjunction/core';\nimport { PendingAttachment } from '../mention/mention-editor.component';\nimport { MessageInputComponent } from '../message/message-input.component';\n\n@Component({\n standalone: false,\n selector: 'mj-conversation-empty-state',\n templateUrl: './conversation-empty-state.component.html',\n styleUrls: ['./conversation-empty-state.component.css']\n})\nexport class ConversationEmptyStateComponent {\n @Input() currentUser!: UserInfo;\n @Input() disabled: boolean = false;\n @Input() showSidebarToggle: boolean = false;\n @Input() enableAttachments: boolean = false;\n @Input() maxAttachments: number = 10;\n @Input() maxAttachmentSizeBytes: number = 20 * 1024 * 1024;\n @Input() acceptedFileTypes: string = 'image/*';\n\n /** Greeting text shown in the empty state. Set by host app via overlay/chat-area chain. */\n @Input() greeting: string = 'How can I help you?';\n\n /** When true (overlay context), suggested prompts are hidden to save space */\n private _overlayMode = false;\n @Input()\n set overlayMode(value: boolean) {\n this._overlayMode = value;\n if (value) {\n this.suggestedPrompts = [];\n }\n }\n get overlayMode(): boolean {\n return this._overlayMode;\n }\n\n @ViewChild(MessageInputComponent) private messageInput?: MessageInputComponent;\n\n @Output() messageSent = new EventEmitter<{text: string; attachments: PendingAttachment[]}>();\n @Output() sidebarToggleClicked = new EventEmitter<void>();\n\n public messageText: string = '';\n\n // All available suggested prompts (business user focused)\n private allSuggestedPrompts: Array<{icon: string; title: string; prompt: string}> = [\n // Data Analysis & Insights\n {\n icon: 'fa-clock-rotate-left',\n title: 'Recent changes',\n prompt: 'Show me what\\'s changed in my data recently'\n },\n {\n icon: 'fa-list-check',\n title: 'Pending items',\n prompt: 'Find all my incomplete or pending items'\n },\n {\n icon: 'fa-magnifying-glass',\n title: 'Search everything',\n prompt: 'Search everything in my system for a specific topic'\n },\n {\n icon: 'fa-clipboard-check',\n title: 'Data quality',\n prompt: 'Analyze my data and find duplicates or inconsistencies'\n },\n {\n icon: 'fa-inbox',\n title: 'Catch up',\n prompt: 'Create a summary of activity while I was away'\n },\n\n // Research & Information Gathering\n {\n icon: 'fa-download',\n title: 'Research & save',\n prompt: 'Research a topic and save the findings to my database'\n },\n {\n icon: 'fa-code-compare',\n title: 'Compare sources',\n prompt: 'Compare my data with information from the web'\n },\n {\n icon: 'fa-folder-open',\n title: 'Search files',\n prompt: 'Search my files and documents for related information'\n },\n {\n icon: 'fa-layer-group',\n title: 'Multi-source search',\n prompt: 'Find relevant information across all my data sources'\n },\n {\n icon: 'fa-sitemap',\n title: 'Comprehensive research',\n prompt: 'Gather information on a topic from multiple sources'\n },\n\n // Automation & Agent Building\n {\n icon: 'fa-calendar-day',\n title: 'Daily summaries',\n prompt: 'Create an agent to send me daily data summaries'\n },\n {\n icon: 'fa-bell',\n title: 'Change alerts',\n prompt: 'Build an agent that monitors data changes and alerts me'\n },\n {\n icon: 'fa-file-chart-column',\n title: 'Automated reports',\n prompt: 'Design an agent to aggregate data and create reports'\n },\n {\n icon: 'fa-arrows-rotate',\n title: 'Data sync',\n prompt: 'Help me create an agent that syncs data with external systems'\n },\n {\n icon: 'fa-file-import',\n title: 'File processor',\n prompt: 'Build an agent that processes files and updates my database'\n },\n {\n icon: 'fa-slack',\n title: 'Slack notifications',\n prompt: 'Create an agent to post updates to Slack when data changes'\n },\n {\n icon: 'fa-broom',\n title: 'Data cleanup',\n prompt: 'Design an agent that validates and cleans up my data regularly'\n },\n {\n icon: 'fa-chart-pie',\n title: 'Auto visualizations',\n prompt: 'Build an agent that generates visualizations from my data'\n },\n {\n icon: 'fa-graduation-cap',\n title: 'Research compiler',\n prompt: 'Create an agent to research topics and compile findings'\n },\n {\n icon: 'fa-diagram-project',\n title: 'Workflow automation',\n prompt: 'Help me design a workflow agent with approval steps'\n }\n ];\n\n // Randomly selected prompts to display (refreshed on each load)\n public suggestedPrompts: Array<{icon: string; title: string; prompt: string}> = [];\n\n constructor() {\n // Select 4 random prompts on initialization\n this.suggestedPrompts = this.selectRandomPrompts(4);\n }\n\n /**\n * Select random prompts from the full list\n */\n private selectRandomPrompts(count: number): Array<{icon: string; title: string; prompt: string}> {\n const shuffled = [...this.allSuggestedPrompts].sort(() => Math.random() - 0.5);\n return shuffled.slice(0, count);\n }\n\n /**\n * Focus the message input programmatically.\n * Called by parent when the user clicks \"New Conversation\" while already on the empty state.\n */\n public FocusInput(): void {\n setTimeout(() => {\n if (this.messageInput) {\n this.messageInput.inputBox?.focus();\n }\n }, 100);\n }\n\n onEmptyStateSubmit(event: {text: string; attachments: PendingAttachment[]}): void {\n this.messageSent.emit(event);\n }\n\n onSuggestedPromptClicked(prompt: string): void {\n if (!this.disabled) {\n this.messageSent.emit({ text: prompt, attachments: [] });\n }\n }\n}\n","<div class=\"conversation-empty-state\" [class.overlay-mode]=\"overlayMode\">\n <!-- Sidebar Toggle Button (top-left when sidebar is collapsed) -->\n @if (showSidebarToggle) {\n <button class=\"sidebar-toggle-btn\"\n (click)=\"sidebarToggleClicked.emit()\"\n title=\"Show conversations\">\n <i class=\"fas fa-table-columns\"></i>\n </button>\n }\n\n <!-- Loading Overlay -->\n @if (disabled) {\n <div class=\"loading-overlay\">\n <mj-loading text=\"Creating your conversation...\" size=\"large\"></mj-loading>\n </div>\n }\n\n <div class=\"empty-state-container\" [class.loading]=\"disabled\">\n <!-- Greeting Header (hidden in overlay mode) -->\n @if (!overlayMode) {\n <div class=\"greeting-section\">\n <div class=\"greeting-icon\">\n <i class=\"fa-solid fa-comments fa-3x\"></i>\n </div>\n <h1 class=\"greeting-title\">Welcome to Conversations</h1>\n <p class=\"greeting-subtitle\">\n Start a new conversation by typing a message below, or choose a suggested prompt to get started.\n </p>\n </div>\n }\n\n <!-- Suggested Prompts (hidden in overlay mode) -->\n @if (suggestedPrompts.length > 0) {\n <div class=\"suggested-prompts\">\n <div class=\"prompt-grid\">\n @for (prompt of suggestedPrompts; track prompt) {\n <div\n class=\"prompt-card\"\n (click)=\"onSuggestedPromptClicked(prompt.prompt)\"\n [class.disabled]=\"disabled\"\n >\n <div class=\"prompt-icon\">\n <i class=\"fa-solid {{prompt.icon}}\"></i>\n </div>\n <div class=\"prompt-content\">\n <div class=\"prompt-title\">{{prompt.title}}</div>\n <div class=\"prompt-text\">{{prompt.prompt}}</div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Compact greeting for overlay mode -->\n @if (overlayMode) {\n <div class=\"overlay-greeting\">\n <p class=\"overlay-greeting-text\">{{ greeting }}</p>\n </div>\n }\n\n <!-- Message Input (using full mj-message-input in empty state mode) -->\n <div class=\"message-input-wrapper\">\n <mj-message-input\n [placeholder]=\"overlayMode ? 'Type a message...' : 'Type your message to start a new conversation...'\"\n [disabled]=\"disabled\"\n [currentUser]=\"currentUser\"\n [emptyStateMode]=\"true\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n (emptyStateSubmit)=\"onEmptyStateSubmit($event)\">\n </mj-message-input>\n </div>\n\n <!-- Footer Tips (hidden in overlay mode) -->\n @if (!overlayMode) {\n <div class=\"tips-section\">\n <div class=\"tip-item\">\n <i class=\"fa-solid fa-at\"></i>\n <span>Use <strong>&#64;AgentName</strong> to directly invoke a specific agent</span>\n </div>\n <div class=\"tip-item\">\n <i class=\"fa-solid fa-keyboard\"></i>\n <span>Press <strong>Enter</strong> to send, <strong>Shift+Enter</strong> for new line</span>\n </div>\n </div>\n }\n </div>\n</div>\n"]}
1
+ {"version":3,"file":"conversation-empty-state.component.js","sourceRoot":"","sources":["../../../../src/lib/components/conversation/conversation-empty-state.component.ts","../../../../src/lib/components/conversation/conversation-empty-state.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';\nimport { UserInfo } from '@memberjunction/core';\nimport { PendingAttachment } from '../mention/mention-editor.component';\nimport { MessageInputComponent } from '../message/message-input.component';\n\n@Component({\n standalone: false,\n selector: 'mj-conversation-empty-state',\n templateUrl: './conversation-empty-state.component.html',\n styleUrls: ['./conversation-empty-state.component.css']\n})\nexport class ConversationEmptyStateComponent {\n @Input() currentUser!: UserInfo;\n @Input() disabled: boolean = false;\n @Input() showSidebarToggle: boolean = false;\n @Input() enableAttachments: boolean = false;\n @Input() enableMentions: boolean = true;\n @Input() maxAttachments: number = 10;\n @Input() maxAttachmentSizeBytes: number = 20 * 1024 * 1024;\n @Input() acceptedFileTypes: string = 'image/*';\n\n /** Greeting text shown in the empty state. Set by host app via overlay/chat-area chain. */\n @Input() greeting: string = 'How can I help you?';\n\n /** When true (overlay context), suggested prompts are hidden to save space */\n private _overlayMode = false;\n @Input()\n set overlayMode(value: boolean) {\n this._overlayMode = value;\n if (value) {\n this.suggestedPrompts = [];\n }\n }\n get overlayMode(): boolean {\n return this._overlayMode;\n }\n\n @ViewChild(MessageInputComponent) private messageInput?: MessageInputComponent;\n\n @Output() messageSent = new EventEmitter<{text: string; attachments: PendingAttachment[]}>();\n @Output() sidebarToggleClicked = new EventEmitter<void>();\n\n public messageText: string = '';\n\n // All available suggested prompts (business user focused)\n private allSuggestedPrompts: Array<{icon: string; title: string; prompt: string}> = [\n // Data Analysis & Insights\n {\n icon: 'fa-clock-rotate-left',\n title: 'Recent changes',\n prompt: 'Show me what\\'s changed in my data recently'\n },\n {\n icon: 'fa-list-check',\n title: 'Pending items',\n prompt: 'Find all my incomplete or pending items'\n },\n {\n icon: 'fa-magnifying-glass',\n title: 'Search everything',\n prompt: 'Search everything in my system for a specific topic'\n },\n {\n icon: 'fa-clipboard-check',\n title: 'Data quality',\n prompt: 'Analyze my data and find duplicates or inconsistencies'\n },\n {\n icon: 'fa-inbox',\n title: 'Catch up',\n prompt: 'Create a summary of activity while I was away'\n },\n\n // Research & Information Gathering\n {\n icon: 'fa-download',\n title: 'Research & save',\n prompt: 'Research a topic and save the findings to my database'\n },\n {\n icon: 'fa-code-compare',\n title: 'Compare sources',\n prompt: 'Compare my data with information from the web'\n },\n {\n icon: 'fa-folder-open',\n title: 'Search files',\n prompt: 'Search my files and documents for related information'\n },\n {\n icon: 'fa-layer-group',\n title: 'Multi-source search',\n prompt: 'Find relevant information across all my data sources'\n },\n {\n icon: 'fa-sitemap',\n title: 'Comprehensive research',\n prompt: 'Gather information on a topic from multiple sources'\n },\n\n // Automation & Agent Building\n {\n icon: 'fa-calendar-day',\n title: 'Daily summaries',\n prompt: 'Create an agent to send me daily data summaries'\n },\n {\n icon: 'fa-bell',\n title: 'Change alerts',\n prompt: 'Build an agent that monitors data changes and alerts me'\n },\n {\n icon: 'fa-file-chart-column',\n title: 'Automated reports',\n prompt: 'Design an agent to aggregate data and create reports'\n },\n {\n icon: 'fa-arrows-rotate',\n title: 'Data sync',\n prompt: 'Help me create an agent that syncs data with external systems'\n },\n {\n icon: 'fa-file-import',\n title: 'File processor',\n prompt: 'Build an agent that processes files and updates my database'\n },\n {\n icon: 'fa-slack',\n title: 'Slack notifications',\n prompt: 'Create an agent to post updates to Slack when data changes'\n },\n {\n icon: 'fa-broom',\n title: 'Data cleanup',\n prompt: 'Design an agent that validates and cleans up my data regularly'\n },\n {\n icon: 'fa-chart-pie',\n title: 'Auto visualizations',\n prompt: 'Build an agent that generates visualizations from my data'\n },\n {\n icon: 'fa-graduation-cap',\n title: 'Research compiler',\n prompt: 'Create an agent to research topics and compile findings'\n },\n {\n icon: 'fa-diagram-project',\n title: 'Workflow automation',\n prompt: 'Help me design a workflow agent with approval steps'\n }\n ];\n\n // Randomly selected prompts to display (refreshed on each load)\n public suggestedPrompts: Array<{icon: string; title: string; prompt: string}> = [];\n\n constructor() {\n // Select 4 random prompts on initialization\n this.suggestedPrompts = this.selectRandomPrompts(4);\n }\n\n /**\n * Select random prompts from the full list\n */\n private selectRandomPrompts(count: number): Array<{icon: string; title: string; prompt: string}> {\n const shuffled = [...this.allSuggestedPrompts].sort(() => Math.random() - 0.5);\n return shuffled.slice(0, count);\n }\n\n /**\n * Focus the message input programmatically.\n * Called by parent when the user clicks \"New Conversation\" while already on the empty state.\n */\n public FocusInput(): void {\n setTimeout(() => {\n if (this.messageInput) {\n this.messageInput.inputBox?.focus();\n }\n }, 100);\n }\n\n onEmptyStateSubmit(event: {text: string; attachments: PendingAttachment[]}): void {\n this.messageSent.emit(event);\n }\n\n onSuggestedPromptClicked(prompt: string): void {\n if (!this.disabled) {\n this.messageSent.emit({ text: prompt, attachments: [] });\n }\n }\n}\n","<div class=\"conversation-empty-state\" [class.overlay-mode]=\"overlayMode\">\n <!-- Sidebar Toggle Button (top-left when sidebar is collapsed) -->\n @if (showSidebarToggle) {\n <button class=\"sidebar-toggle-btn\"\n (click)=\"sidebarToggleClicked.emit()\"\n title=\"Show conversations\">\n <i class=\"fas fa-table-columns\"></i>\n </button>\n }\n\n <!-- Loading Overlay -->\n @if (disabled) {\n <div class=\"loading-overlay\">\n <mj-loading text=\"Creating your conversation...\" size=\"large\"></mj-loading>\n </div>\n }\n\n <div class=\"empty-state-container\" [class.loading]=\"disabled\">\n <!-- Greeting Header (hidden in overlay mode) -->\n @if (!overlayMode) {\n <div class=\"greeting-section\">\n <div class=\"greeting-icon\">\n <i class=\"fa-solid fa-comments fa-3x\"></i>\n </div>\n <h1 class=\"greeting-title\">Welcome to Conversations</h1>\n <p class=\"greeting-subtitle\">\n Start a new conversation by typing a message below, or choose a suggested prompt to get started.\n </p>\n </div>\n }\n\n <!-- Suggested Prompts (hidden in overlay mode) -->\n @if (suggestedPrompts.length > 0) {\n <div class=\"suggested-prompts\">\n <div class=\"prompt-grid\">\n @for (prompt of suggestedPrompts; track prompt) {\n <div\n class=\"prompt-card\"\n (click)=\"onSuggestedPromptClicked(prompt.prompt)\"\n [class.disabled]=\"disabled\"\n >\n <div class=\"prompt-icon\">\n <i class=\"fa-solid {{prompt.icon}}\"></i>\n </div>\n <div class=\"prompt-content\">\n <div class=\"prompt-title\">{{prompt.title}}</div>\n <div class=\"prompt-text\">{{prompt.prompt}}</div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Compact greeting for overlay mode -->\n @if (overlayMode) {\n <div class=\"overlay-greeting\">\n <p class=\"overlay-greeting-text\">{{ greeting }}</p>\n </div>\n }\n\n <!-- Message Input (using full mj-message-input in empty state mode) -->\n <div class=\"message-input-wrapper\">\n <mj-message-input\n [placeholder]=\"overlayMode ? 'Type a message...' : 'Type your message to start a new conversation...'\"\n [disabled]=\"disabled\"\n [currentUser]=\"currentUser\"\n [emptyStateMode]=\"true\"\n [enableMentions]=\"enableMentions\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n (emptyStateSubmit)=\"onEmptyStateSubmit($event)\">\n </mj-message-input>\n </div>\n\n <!-- Footer Tips (hidden in overlay mode) -->\n @if (!overlayMode) {\n <div class=\"tips-section\">\n <div class=\"tip-item\">\n <i class=\"fa-solid fa-at\"></i>\n <span>Use <strong>&#64;AgentName</strong> to directly invoke a specific agent</span>\n </div>\n <div class=\"tip-item\">\n <i class=\"fa-solid fa-keyboard\"></i>\n <span>Press <strong>Enter</strong> to send, <strong>Shift+Enter</strong> for new line</span>\n </div>\n </div>\n }\n </div>\n</div>\n"]}
@@ -0,0 +1,57 @@
1
+ import { EventEmitter, OnInit } from '@angular/core';
2
+ import type { MJAIAgentConfigurationEntity } from '@memberjunction/core-entities';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * Per-agent quality/speed mode picker. Sits next to the agent picker in
6
+ * the chat-area header. Lists the **active agent's** configured
7
+ * presets (e.g. Draft / Standard / High) from
8
+ * `AIEngineBase.Instance.GetAgentConfigurationPresets(agentId)` and lets
9
+ * the user pick the one applied to all SUBSEQUENT requests in this
10
+ * conversation. Past messages are not retroactively re-routed.
11
+ *
12
+ * Choice persists per-user, per-agent via `UserInfoEngine` (key
13
+ * `mj.agentMode.<agentId>` = preset name). Cross-device, cross-browser
14
+ * — same model the form-variant preference uses. No DB schema changes.
15
+ *
16
+ * Auto-hides when the active agent has fewer than 2 presets — a
17
+ * single-mode agent doesn't need a switcher.
18
+ */
19
+ export declare class ConversationModePickerComponent implements OnInit {
20
+ /**
21
+ * The agent the picker should show presets for. When this changes,
22
+ * the picker re-resolves the available presets and the user's saved
23
+ * choice for that agent. Null hides the picker entirely.
24
+ */
25
+ set AgentID(value: string | null);
26
+ get AgentID(): string | null;
27
+ /** Disable interactions (e.g. during agent execution). */
28
+ Disabled: boolean;
29
+ /**
30
+ * Emitted whenever the user picks a preset. Payload is the
31
+ * `MJ: AI Agent Configurations.ID` — exactly what
32
+ * `MessageInputComponent` forwards as `agentConfigurationPresetId`
33
+ * on the next message route. Null when the picker is cleared or
34
+ * the active agent has no presets.
35
+ */
36
+ PresetChanged: EventEmitter<string | null>;
37
+ Presets: MJAIAgentConfigurationEntity[];
38
+ CurrentPreset: MJAIAgentConfigurationEntity | null;
39
+ IsOpen: boolean;
40
+ private _agentID;
41
+ private readonly cdr;
42
+ ngOnInit(): Promise<void>;
43
+ get CurrentLabel(): string;
44
+ get ButtonTitle(): string;
45
+ IsSelected(p: MJAIAgentConfigurationEntity): boolean;
46
+ Toggle(event: MouseEvent): void;
47
+ PickPreset(p: MJAIAgentConfigurationEntity): void;
48
+ /** Re-load presets for the active agent and apply the saved choice. */
49
+ private refresh;
50
+ /** User's saved pick (by Name) → preset, or the agent's IsDefault row. */
51
+ private resolveSavedOrDefault;
52
+ private storageKey;
53
+ OnDocumentClick(_event: MouseEvent): void;
54
+ static ɵfac: i0.ɵɵFactoryDeclaration<ConversationModePickerComponent, never>;
55
+ static ɵcmp: i0.ɵɵComponentDeclaration<ConversationModePickerComponent, "mj-conversation-mode-picker", never, { "AgentID": { "alias": "AgentID"; "required": false; }; "Disabled": { "alias": "Disabled"; "required": false; }; }, { "PresetChanged": "PresetChanged"; }, never, never, false, never>;
56
+ }
57
+ //# sourceMappingURL=conversation-mode-picker.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-mode-picker.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/conversation/conversation-mode-picker.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,YAAY,EAGZ,MAAM,EAGT,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;;AAIlF;;;;;;;;;;;;;;GAcG;AACH,qBA+Ea,+BAAgC,YAAW,MAAM;IAC1D;;;;OAIG;IACH,IACW,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAItC;IACD,IAAW,OAAO,IAAI,MAAM,GAAG,IAAI,CAA0B;IAE7D,0DAA0D;IACjD,QAAQ,EAAE,OAAO,CAAS;IAEnC;;;;;;OAMG;IACO,aAAa,8BAAqC;IAErD,OAAO,EAAE,4BAA4B,EAAE,CAAM;IAC7C,aAAa,EAAE,4BAA4B,GAAG,IAAI,CAAQ;IAC1D,MAAM,UAAS;IAEtB,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA6B;IAEpC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,IAAW,YAAY,IAAI,MAAM,CAEhC;IAED,IAAW,WAAW,IAAI,MAAM,CAK/B;IAEM,UAAU,CAAC,CAAC,EAAE,4BAA4B,GAAG,OAAO;IAIpD,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAO/B,UAAU,CAAC,CAAC,EAAE,4BAA4B,GAAG,IAAI;IAkBxD,uEAAuE;YACzD,OAAO;IAmBrB,0EAA0E;IAC1E,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,UAAU;IAKX,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;yCAjHvC,+BAA+B;2CAA/B,+BAA+B;CAuH3C"}
@@ -0,0 +1,252 @@
1
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostListener, Input, Output, inject, } from '@angular/core';
2
+ import { LogError } from '@memberjunction/core';
3
+ import { AIEngineBase } from '@memberjunction/ai-engine-base';
4
+ import { UserInfoEngine } from '@memberjunction/core-entities';
5
+ import { UUIDsEqual } from '@memberjunction/global';
6
+ import * as i0 from "@angular/core";
7
+ const _forTrack0 = ($index, $item) => $item.ID;
8
+ function ConversationModePickerComponent_Conditional_0_Conditional_5_For_4_Conditional_4_Template(rf, ctx) { if (rf & 1) {
9
+ i0.ɵɵelementStart(0, "span", 12);
10
+ i0.ɵɵtext(1);
11
+ i0.ɵɵelementEnd();
12
+ } if (rf & 2) {
13
+ const p_r5 = i0.ɵɵnextContext().$implicit;
14
+ i0.ɵɵadvance();
15
+ i0.ɵɵtextInterpolate(p_r5.Description);
16
+ } }
17
+ function ConversationModePickerComponent_Conditional_0_Conditional_5_For_4_Template(rf, ctx) { if (rf & 1) {
18
+ const _r4 = i0.ɵɵgetCurrentView();
19
+ i0.ɵɵelementStart(0, "button", 9);
20
+ i0.ɵɵlistener("click", function ConversationModePickerComponent_Conditional_0_Conditional_5_For_4_Template_button_click_0_listener() { const p_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.PickPreset(p_r5)); });
21
+ i0.ɵɵelementStart(1, "div", 10)(2, "span", 11);
22
+ i0.ɵɵtext(3);
23
+ i0.ɵɵelementEnd();
24
+ i0.ɵɵconditionalCreate(4, ConversationModePickerComponent_Conditional_0_Conditional_5_For_4_Conditional_4_Template, 2, 1, "span", 12);
25
+ i0.ɵɵelementEnd()();
26
+ } if (rf & 2) {
27
+ const p_r5 = ctx.$implicit;
28
+ const ctx_r1 = i0.ɵɵnextContext(3);
29
+ i0.ɵɵclassProp("mj-cv-mode-picker__item--selected", ctx_r1.IsSelected(p_r5));
30
+ i0.ɵɵproperty("title", p_r5.Description || p_r5.Name);
31
+ i0.ɵɵadvance(3);
32
+ i0.ɵɵtextInterpolate(p_r5.DisplayName || p_r5.Name);
33
+ i0.ɵɵadvance();
34
+ i0.ɵɵconditional(p_r5.Description ? 4 : -1);
35
+ } }
36
+ function ConversationModePickerComponent_Conditional_0_Conditional_5_Template(rf, ctx) { if (rf & 1) {
37
+ const _r3 = i0.ɵɵgetCurrentView();
38
+ i0.ɵɵelementStart(0, "div", 6);
39
+ i0.ɵɵlistener("click", function ConversationModePickerComponent_Conditional_0_Conditional_5_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r3); return i0.ɵɵresetView($event.stopPropagation()); });
40
+ i0.ɵɵelementStart(1, "div", 7);
41
+ i0.ɵɵtext(2, "Mode for the next message");
42
+ i0.ɵɵelementEnd();
43
+ i0.ɵɵrepeaterCreate(3, ConversationModePickerComponent_Conditional_0_Conditional_5_For_4_Template, 5, 5, "button", 8, _forTrack0);
44
+ i0.ɵɵelementEnd();
45
+ } if (rf & 2) {
46
+ const ctx_r1 = i0.ɵɵnextContext(2);
47
+ i0.ɵɵadvance(3);
48
+ i0.ɵɵrepeater(ctx_r1.Presets);
49
+ } }
50
+ function ConversationModePickerComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
51
+ const _r1 = i0.ɵɵgetCurrentView();
52
+ i0.ɵɵelementStart(0, "div", 1)(1, "button", 2);
53
+ i0.ɵɵlistener("click", function ConversationModePickerComponent_Conditional_0_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Toggle($event)); });
54
+ i0.ɵɵelementStart(2, "span", 3);
55
+ i0.ɵɵtext(3);
56
+ i0.ɵɵelementEnd();
57
+ i0.ɵɵelement(4, "i", 4);
58
+ i0.ɵɵelementEnd();
59
+ i0.ɵɵconditionalCreate(5, ConversationModePickerComponent_Conditional_0_Conditional_5_Template, 5, 0, "div", 5);
60
+ i0.ɵɵelementEnd();
61
+ } if (rf & 2) {
62
+ const ctx_r1 = i0.ɵɵnextContext();
63
+ i0.ɵɵclassProp("mj-cv-mode-picker--open", ctx_r1.IsOpen);
64
+ i0.ɵɵadvance();
65
+ i0.ɵɵproperty("title", ctx_r1.ButtonTitle)("disabled", ctx_r1.Disabled);
66
+ i0.ɵɵadvance(2);
67
+ i0.ɵɵtextInterpolate(ctx_r1.CurrentLabel);
68
+ i0.ɵɵadvance(2);
69
+ i0.ɵɵconditional(ctx_r1.IsOpen ? 5 : -1);
70
+ } }
71
+ /**
72
+ * Per-agent quality/speed mode picker. Sits next to the agent picker in
73
+ * the chat-area header. Lists the **active agent's** configured
74
+ * presets (e.g. Draft / Standard / High) from
75
+ * `AIEngineBase.Instance.GetAgentConfigurationPresets(agentId)` and lets
76
+ * the user pick the one applied to all SUBSEQUENT requests in this
77
+ * conversation. Past messages are not retroactively re-routed.
78
+ *
79
+ * Choice persists per-user, per-agent via `UserInfoEngine` (key
80
+ * `mj.agentMode.<agentId>` = preset name). Cross-device, cross-browser
81
+ * — same model the form-variant preference uses. No DB schema changes.
82
+ *
83
+ * Auto-hides when the active agent has fewer than 2 presets — a
84
+ * single-mode agent doesn't need a switcher.
85
+ */
86
+ export class ConversationModePickerComponent {
87
+ /**
88
+ * The agent the picker should show presets for. When this changes,
89
+ * the picker re-resolves the available presets and the user's saved
90
+ * choice for that agent. Null hides the picker entirely.
91
+ */
92
+ set AgentID(value) {
93
+ if (value === this._agentID)
94
+ return;
95
+ this._agentID = value;
96
+ this.refresh();
97
+ }
98
+ get AgentID() { return this._agentID; }
99
+ /** Disable interactions (e.g. during agent execution). */
100
+ Disabled = false;
101
+ /**
102
+ * Emitted whenever the user picks a preset. Payload is the
103
+ * `MJ: AI Agent Configurations.ID` — exactly what
104
+ * `MessageInputComponent` forwards as `agentConfigurationPresetId`
105
+ * on the next message route. Null when the picker is cleared or
106
+ * the active agent has no presets.
107
+ */
108
+ PresetChanged = new EventEmitter();
109
+ Presets = [];
110
+ CurrentPreset = null;
111
+ IsOpen = false;
112
+ _agentID = null;
113
+ cdr = inject(ChangeDetectorRef);
114
+ async ngOnInit() {
115
+ await this.refresh();
116
+ }
117
+ get CurrentLabel() {
118
+ return this.CurrentPreset?.DisplayName ?? this.CurrentPreset?.Name ?? 'Mode';
119
+ }
120
+ get ButtonTitle() {
121
+ if (!this.CurrentPreset)
122
+ return 'Pick a mode';
123
+ const base = `Mode: ${this.CurrentLabel}`;
124
+ const desc = this.CurrentPreset.Description ?? '';
125
+ return desc ? `${base} — ${desc}\n\nClick to change. Applies to the NEXT message.` : `${base} — click to change`;
126
+ }
127
+ IsSelected(p) {
128
+ return !!this.CurrentPreset && UUIDsEqual(p.ID, this.CurrentPreset.ID);
129
+ }
130
+ Toggle(event) {
131
+ event.stopPropagation();
132
+ if (this.Disabled || this.Presets.length < 2)
133
+ return;
134
+ this.IsOpen = !this.IsOpen;
135
+ this.cdr.markForCheck();
136
+ }
137
+ PickPreset(p) {
138
+ this.IsOpen = false;
139
+ if (this.CurrentPreset && UUIDsEqual(p.ID, this.CurrentPreset.ID)) {
140
+ this.cdr.markForCheck();
141
+ return;
142
+ }
143
+ this.CurrentPreset = p;
144
+ // Persist by NAME (not ID) so the preference survives a
145
+ // metadata refresh that re-stamps preset IDs. Resolution back to
146
+ // the actual config row on read happens via
147
+ // GetAgentConfigurationPresetByName at refresh time.
148
+ if (this._agentID) {
149
+ UserInfoEngine.Instance.SetSettingDebounced(this.storageKey(this._agentID), p.Name);
150
+ }
151
+ this.PresetChanged.emit(p.ID);
152
+ this.cdr.markForCheck();
153
+ }
154
+ /** Re-load presets for the active agent and apply the saved choice. */
155
+ async refresh() {
156
+ if (!this._agentID) {
157
+ this.Presets = [];
158
+ this.CurrentPreset = null;
159
+ this.PresetChanged.emit(null);
160
+ this.cdr.markForCheck();
161
+ return;
162
+ }
163
+ try {
164
+ await AIEngineBase.Instance.Config(false);
165
+ this.Presets = AIEngineBase.Instance.GetAgentConfigurationPresets(this._agentID, true) ?? [];
166
+ this.CurrentPreset = this.resolveSavedOrDefault();
167
+ this.PresetChanged.emit(this.CurrentPreset?.ID ?? null);
168
+ this.cdr.markForCheck();
169
+ }
170
+ catch (err) {
171
+ LogError(`ConversationModePicker.refresh: ${err instanceof Error ? err.message : String(err)}`);
172
+ }
173
+ }
174
+ /** User's saved pick (by Name) → preset, or the agent's IsDefault row. */
175
+ resolveSavedOrDefault() {
176
+ if (!this._agentID || this.Presets.length === 0)
177
+ return null;
178
+ const savedName = UserInfoEngine.Instance.GetSetting(this.storageKey(this._agentID));
179
+ if (savedName) {
180
+ const match = AIEngineBase.Instance.GetAgentConfigurationPresetByName(this._agentID, savedName);
181
+ if (match)
182
+ return match;
183
+ }
184
+ return this.Presets.find(p => p.IsDefault) ?? this.Presets[0];
185
+ }
186
+ storageKey(agentID) {
187
+ return `mj.agentMode.${agentID.toLowerCase()}`;
188
+ }
189
+ OnDocumentClick(_event) {
190
+ if (this.IsOpen) {
191
+ this.IsOpen = false;
192
+ this.cdr.markForCheck();
193
+ }
194
+ }
195
+ static ɵfac = function ConversationModePickerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ConversationModePickerComponent)(); };
196
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ConversationModePickerComponent, selectors: [["mj-conversation-mode-picker"]], hostBindings: function ConversationModePickerComponent_HostBindings(rf, ctx) { if (rf & 1) {
197
+ i0.ɵɵlistener("click", function ConversationModePickerComponent_click_HostBindingHandler($event) { return ctx.OnDocumentClick($event); }, i0.ɵɵresolveDocument);
198
+ } }, inputs: { AgentID: "AgentID", Disabled: "Disabled" }, outputs: { PresetChanged: "PresetChanged" }, standalone: false, decls: 1, vars: 1, consts: [[1, "mj-cv-mode-picker", 3, "mj-cv-mode-picker--open"], [1, "mj-cv-mode-picker"], ["type", "button", 1, "mj-cv-mode-picker__trigger", 3, "click", "title", "disabled"], [1, "mj-cv-mode-picker__label"], [1, "fa-solid", "fa-caret-down", "mj-cv-mode-picker__caret"], [1, "mj-cv-mode-picker__menu"], [1, "mj-cv-mode-picker__menu", 3, "click"], [1, "mj-cv-mode-picker__menu-header"], ["type", "button", 1, "mj-cv-mode-picker__item", 3, "mj-cv-mode-picker__item--selected", "title"], ["type", "button", 1, "mj-cv-mode-picker__item", 3, "click", "title"], [1, "mj-cv-mode-picker__item-text"], [1, "mj-cv-mode-picker__item-name"], [1, "mj-cv-mode-picker__item-desc"]], template: function ConversationModePickerComponent_Template(rf, ctx) { if (rf & 1) {
199
+ i0.ɵɵconditionalCreate(0, ConversationModePickerComponent_Conditional_0_Template, 6, 6, "div", 0);
200
+ } if (rf & 2) {
201
+ i0.ɵɵconditional(ctx.Presets.length >= 2 ? 0 : -1);
202
+ } }, styles: [".mj-cv-mode-picker[_ngcontent-%COMP%] { position: relative; display: inline-flex; align-items: center; }\n .mj-cv-mode-picker__trigger[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center; gap: 6px;\n padding: 6px 12px; min-height: 32px; box-sizing: border-box;\n background: var(--mj-bg-surface-card); border: 1px solid var(--mj-border-default);\n border-radius: 4px; cursor: pointer;\n color: var(--mj-text-primary); font-size: 0.8125rem; line-height: 1.5;\n transition: background 120ms, border-color 120ms;\n }\n .mj-cv-mode-picker__trigger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover); border-color: var(--mj-border-strong);\n }\n .mj-cv-mode-picker__trigger[_ngcontent-%COMP%]:disabled { opacity: 0.5; cursor: not-allowed; }\n .mj-cv-mode-picker--open[_ngcontent-%COMP%] .mj-cv-mode-picker__trigger[_ngcontent-%COMP%] { border-color: var(--mj-border-focus); }\n .mj-cv-mode-picker__label[_ngcontent-%COMP%] { max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .mj-cv-mode-picker__caret[_ngcontent-%COMP%] { font-size: 10px; opacity: 0.7; }\n .mj-cv-mode-picker__menu[_ngcontent-%COMP%] {\n position: absolute; top: calc(100% + 4px); right: 0; z-index: 50;\n min-width: 280px; max-height: 360px; overflow-y: auto;\n background: var(--mj-bg-surface-elevated); border: 1px solid var(--mj-border-default);\n border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.12);\n padding: 4px 0;\n }\n .mj-cv-mode-picker__menu-header[_ngcontent-%COMP%] {\n padding: 6px 12px 4px; font-size: 11px; text-transform: uppercase;\n letter-spacing: 0.04em; color: var(--mj-text-muted);\n }\n .mj-cv-mode-picker__item[_ngcontent-%COMP%] {\n display: flex; align-items: flex-start; gap: 10px; width: 100%;\n padding: 8px 12px; background: transparent; border: none; cursor: pointer;\n color: var(--mj-text-primary); font-size: 13px; text-align: left;\n }\n .mj-cv-mode-picker__item[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n .mj-cv-mode-picker__item--selected[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent); }\n .mj-cv-mode-picker__item-text[_ngcontent-%COMP%] { flex: 1; display: flex; flex-direction: column; gap: 2px; }\n .mj-cv-mode-picker__item-name[_ngcontent-%COMP%] { font-weight: 600; }\n .mj-cv-mode-picker__item-desc[_ngcontent-%COMP%] { font-size: 11px; color: var(--mj-text-muted); }"], changeDetection: 0 });
203
+ }
204
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ConversationModePickerComponent, [{
205
+ type: Component,
206
+ args: [{ standalone: false, selector: 'mj-conversation-mode-picker', changeDetection: ChangeDetectionStrategy.OnPush, template: `
207
+ @if (Presets.length >= 2) {
208
+ <div class="mj-cv-mode-picker" [class.mj-cv-mode-picker--open]="IsOpen">
209
+ <button
210
+ type="button"
211
+ class="mj-cv-mode-picker__trigger"
212
+ [title]="ButtonTitle"
213
+ [disabled]="Disabled"
214
+ (click)="Toggle($event)">
215
+ <span class="mj-cv-mode-picker__label">{{ CurrentLabel }}</span>
216
+ <i class="fa-solid fa-caret-down mj-cv-mode-picker__caret"></i>
217
+ </button>
218
+ @if (IsOpen) {
219
+ <div class="mj-cv-mode-picker__menu" (click)="$event.stopPropagation()">
220
+ <div class="mj-cv-mode-picker__menu-header">Mode for the next message</div>
221
+ @for (p of Presets; track p.ID) {
222
+ <button
223
+ type="button"
224
+ class="mj-cv-mode-picker__item"
225
+ [class.mj-cv-mode-picker__item--selected]="IsSelected(p)"
226
+ [title]="p.Description || p.Name"
227
+ (click)="PickPreset(p)">
228
+ <div class="mj-cv-mode-picker__item-text">
229
+ <span class="mj-cv-mode-picker__item-name">{{ p.DisplayName || p.Name }}</span>
230
+ @if (p.Description) {
231
+ <span class="mj-cv-mode-picker__item-desc">{{ p.Description }}</span>
232
+ }
233
+ </div>
234
+ </button>
235
+ }
236
+ </div>
237
+ }
238
+ </div>
239
+ }
240
+ `, styles: ["\n .mj-cv-mode-picker { position: relative; display: inline-flex; align-items: center; }\n .mj-cv-mode-picker__trigger {\n display: inline-flex; align-items: center; gap: 6px;\n padding: 6px 12px; min-height: 32px; box-sizing: border-box;\n background: var(--mj-bg-surface-card); border: 1px solid var(--mj-border-default);\n border-radius: 4px; cursor: pointer;\n color: var(--mj-text-primary); font-size: 0.8125rem; line-height: 1.5;\n transition: background 120ms, border-color 120ms;\n }\n .mj-cv-mode-picker__trigger:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover); border-color: var(--mj-border-strong);\n }\n .mj-cv-mode-picker__trigger:disabled { opacity: 0.5; cursor: not-allowed; }\n .mj-cv-mode-picker--open .mj-cv-mode-picker__trigger { border-color: var(--mj-border-focus); }\n .mj-cv-mode-picker__label { max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .mj-cv-mode-picker__caret { font-size: 10px; opacity: 0.7; }\n .mj-cv-mode-picker__menu {\n position: absolute; top: calc(100% + 4px); right: 0; z-index: 50;\n min-width: 280px; max-height: 360px; overflow-y: auto;\n background: var(--mj-bg-surface-elevated); border: 1px solid var(--mj-border-default);\n border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.12);\n padding: 4px 0;\n }\n .mj-cv-mode-picker__menu-header {\n padding: 6px 12px 4px; font-size: 11px; text-transform: uppercase;\n letter-spacing: 0.04em; color: var(--mj-text-muted);\n }\n .mj-cv-mode-picker__item {\n display: flex; align-items: flex-start; gap: 10px; width: 100%;\n padding: 8px 12px; background: transparent; border: none; cursor: pointer;\n color: var(--mj-text-primary); font-size: 13px; text-align: left;\n }\n .mj-cv-mode-picker__item:hover { background: var(--mj-bg-surface-hover); }\n .mj-cv-mode-picker__item--selected { background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent); }\n .mj-cv-mode-picker__item-text { flex: 1; display: flex; flex-direction: column; gap: 2px; }\n .mj-cv-mode-picker__item-name { font-weight: 600; }\n .mj-cv-mode-picker__item-desc { font-size: 11px; color: var(--mj-text-muted); }\n "] }]
241
+ }], null, { AgentID: [{
242
+ type: Input
243
+ }], Disabled: [{
244
+ type: Input
245
+ }], PresetChanged: [{
246
+ type: Output
247
+ }], OnDocumentClick: [{
248
+ type: HostListener,
249
+ args: ['document:click', ['$event']]
250
+ }] }); })();
251
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConversationModePickerComponent, { className: "ConversationModePickerComponent", filePath: "src/lib/components/conversation/conversation-mode-picker.component.ts", lineNumber: 112 }); })();
252
+ //# sourceMappingURL=conversation-mode-picker.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-mode-picker.component.js","sourceRoot":"","sources":["../../../../src/lib/components/conversation/conversation-mode-picker.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n HostListener,\n Input,\n OnInit,\n Output,\n inject,\n} from '@angular/core';\nimport { LogError } from '@memberjunction/core';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport type { MJAIAgentConfigurationEntity } from '@memberjunction/core-entities';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Per-agent quality/speed mode picker. Sits next to the agent picker in\n * the chat-area header. Lists the **active agent's** configured\n * presets (e.g. Draft / Standard / High) from\n * `AIEngineBase.Instance.GetAgentConfigurationPresets(agentId)` and lets\n * the user pick the one applied to all SUBSEQUENT requests in this\n * conversation. Past messages are not retroactively re-routed.\n *\n * Choice persists per-user, per-agent via `UserInfoEngine` (key\n * `mj.agentMode.<agentId>` = preset name). Cross-device, cross-browser\n * — same model the form-variant preference uses. No DB schema changes.\n *\n * Auto-hides when the active agent has fewer than 2 presets — a\n * single-mode agent doesn't need a switcher.\n */\n@Component({\n standalone: false,\n selector: 'mj-conversation-mode-picker',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n @if (Presets.length >= 2) {\n <div class=\"mj-cv-mode-picker\" [class.mj-cv-mode-picker--open]=\"IsOpen\">\n <button\n type=\"button\"\n class=\"mj-cv-mode-picker__trigger\"\n [title]=\"ButtonTitle\"\n [disabled]=\"Disabled\"\n (click)=\"Toggle($event)\">\n <span class=\"mj-cv-mode-picker__label\">{{ CurrentLabel }}</span>\n <i class=\"fa-solid fa-caret-down mj-cv-mode-picker__caret\"></i>\n </button>\n @if (IsOpen) {\n <div class=\"mj-cv-mode-picker__menu\" (click)=\"$event.stopPropagation()\">\n <div class=\"mj-cv-mode-picker__menu-header\">Mode for the next message</div>\n @for (p of Presets; track p.ID) {\n <button\n type=\"button\"\n class=\"mj-cv-mode-picker__item\"\n [class.mj-cv-mode-picker__item--selected]=\"IsSelected(p)\"\n [title]=\"p.Description || p.Name\"\n (click)=\"PickPreset(p)\">\n <div class=\"mj-cv-mode-picker__item-text\">\n <span class=\"mj-cv-mode-picker__item-name\">{{ p.DisplayName || p.Name }}</span>\n @if (p.Description) {\n <span class=\"mj-cv-mode-picker__item-desc\">{{ p.Description }}</span>\n }\n </div>\n </button>\n }\n </div>\n }\n </div>\n }\n `,\n styles: [`\n .mj-cv-mode-picker { position: relative; display: inline-flex; align-items: center; }\n .mj-cv-mode-picker__trigger {\n display: inline-flex; align-items: center; gap: 6px;\n padding: 6px 12px; min-height: 32px; box-sizing: border-box;\n background: var(--mj-bg-surface-card); border: 1px solid var(--mj-border-default);\n border-radius: 4px; cursor: pointer;\n color: var(--mj-text-primary); font-size: 0.8125rem; line-height: 1.5;\n transition: background 120ms, border-color 120ms;\n }\n .mj-cv-mode-picker__trigger:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover); border-color: var(--mj-border-strong);\n }\n .mj-cv-mode-picker__trigger:disabled { opacity: 0.5; cursor: not-allowed; }\n .mj-cv-mode-picker--open .mj-cv-mode-picker__trigger { border-color: var(--mj-border-focus); }\n .mj-cv-mode-picker__label { max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .mj-cv-mode-picker__caret { font-size: 10px; opacity: 0.7; }\n .mj-cv-mode-picker__menu {\n position: absolute; top: calc(100% + 4px); right: 0; z-index: 50;\n min-width: 280px; max-height: 360px; overflow-y: auto;\n background: var(--mj-bg-surface-elevated); border: 1px solid var(--mj-border-default);\n border-radius: 6px; box-shadow: 0 4px 16px rgba(0,0,0,0.12);\n padding: 4px 0;\n }\n .mj-cv-mode-picker__menu-header {\n padding: 6px 12px 4px; font-size: 11px; text-transform: uppercase;\n letter-spacing: 0.04em; color: var(--mj-text-muted);\n }\n .mj-cv-mode-picker__item {\n display: flex; align-items: flex-start; gap: 10px; width: 100%;\n padding: 8px 12px; background: transparent; border: none; cursor: pointer;\n color: var(--mj-text-primary); font-size: 13px; text-align: left;\n }\n .mj-cv-mode-picker__item:hover { background: var(--mj-bg-surface-hover); }\n .mj-cv-mode-picker__item--selected { background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent); }\n .mj-cv-mode-picker__item-text { flex: 1; display: flex; flex-direction: column; gap: 2px; }\n .mj-cv-mode-picker__item-name { font-weight: 600; }\n .mj-cv-mode-picker__item-desc { font-size: 11px; color: var(--mj-text-muted); }\n `]\n})\nexport class ConversationModePickerComponent implements OnInit {\n /**\n * The agent the picker should show presets for. When this changes,\n * the picker re-resolves the available presets and the user's saved\n * choice for that agent. Null hides the picker entirely.\n */\n @Input()\n public set AgentID(value: string | null) {\n if (value === this._agentID) return;\n this._agentID = value;\n this.refresh();\n }\n public get AgentID(): string | null { return this._agentID; }\n\n /** Disable interactions (e.g. during agent execution). */\n @Input() Disabled: boolean = false;\n\n /**\n * Emitted whenever the user picks a preset. Payload is the\n * `MJ: AI Agent Configurations.ID` — exactly what\n * `MessageInputComponent` forwards as `agentConfigurationPresetId`\n * on the next message route. Null when the picker is cleared or\n * the active agent has no presets.\n */\n @Output() PresetChanged = new EventEmitter<string | null>();\n\n public Presets: MJAIAgentConfigurationEntity[] = [];\n public CurrentPreset: MJAIAgentConfigurationEntity | null = null;\n public IsOpen = false;\n\n private _agentID: string | null = null;\n private readonly cdr = inject(ChangeDetectorRef);\n\n public async ngOnInit(): Promise<void> {\n await this.refresh();\n }\n\n public get CurrentLabel(): string {\n return this.CurrentPreset?.DisplayName ?? this.CurrentPreset?.Name ?? 'Mode';\n }\n\n public get ButtonTitle(): string {\n if (!this.CurrentPreset) return 'Pick a mode';\n const base = `Mode: ${this.CurrentLabel}`;\n const desc = this.CurrentPreset.Description ?? '';\n return desc ? `${base} — ${desc}\\n\\nClick to change. Applies to the NEXT message.` : `${base} — click to change`;\n }\n\n public IsSelected(p: MJAIAgentConfigurationEntity): boolean {\n return !!this.CurrentPreset && UUIDsEqual(p.ID, this.CurrentPreset.ID);\n }\n\n public Toggle(event: MouseEvent): void {\n event.stopPropagation();\n if (this.Disabled || this.Presets.length < 2) return;\n this.IsOpen = !this.IsOpen;\n this.cdr.markForCheck();\n }\n\n public PickPreset(p: MJAIAgentConfigurationEntity): void {\n this.IsOpen = false;\n if (this.CurrentPreset && UUIDsEqual(p.ID, this.CurrentPreset.ID)) {\n this.cdr.markForCheck();\n return;\n }\n this.CurrentPreset = p;\n // Persist by NAME (not ID) so the preference survives a\n // metadata refresh that re-stamps preset IDs. Resolution back to\n // the actual config row on read happens via\n // GetAgentConfigurationPresetByName at refresh time.\n if (this._agentID) {\n UserInfoEngine.Instance.SetSettingDebounced(this.storageKey(this._agentID), p.Name);\n }\n this.PresetChanged.emit(p.ID);\n this.cdr.markForCheck();\n }\n\n /** Re-load presets for the active agent and apply the saved choice. */\n private async refresh(): Promise<void> {\n if (!this._agentID) {\n this.Presets = [];\n this.CurrentPreset = null;\n this.PresetChanged.emit(null);\n this.cdr.markForCheck();\n return;\n }\n try {\n await AIEngineBase.Instance.Config(false);\n this.Presets = AIEngineBase.Instance.GetAgentConfigurationPresets(this._agentID, true) ?? [];\n this.CurrentPreset = this.resolveSavedOrDefault();\n this.PresetChanged.emit(this.CurrentPreset?.ID ?? null);\n this.cdr.markForCheck();\n } catch (err) {\n LogError(`ConversationModePicker.refresh: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n /** User's saved pick (by Name) → preset, or the agent's IsDefault row. */\n private resolveSavedOrDefault(): MJAIAgentConfigurationEntity | null {\n if (!this._agentID || this.Presets.length === 0) return null;\n const savedName = UserInfoEngine.Instance.GetSetting(this.storageKey(this._agentID));\n if (savedName) {\n const match = AIEngineBase.Instance.GetAgentConfigurationPresetByName(this._agentID, savedName);\n if (match) return match;\n }\n return this.Presets.find(p => p.IsDefault) ?? this.Presets[0];\n }\n\n private storageKey(agentID: string): string {\n return `mj.agentMode.${agentID.toLowerCase()}`;\n }\n\n @HostListener('document:click', ['$event'])\n public OnDocumentClick(_event: MouseEvent): void {\n if (this.IsOpen) {\n this.IsOpen = false;\n this.cdr.markForCheck();\n }\n }\n}\n"]}