@memberjunction/ng-conversations 5.37.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 (56) 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 +148 -11
  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 +498 -261
  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/message/message-input.component.d.ts +51 -3
  19. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  20. package/dist/lib/components/message/message-input.component.js +107 -18
  21. package/dist/lib/components/message/message-input.component.js.map +1 -1
  22. package/dist/lib/components/message/message-item.component.d.ts +0 -13
  23. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  24. package/dist/lib/components/message/message-item.component.js +124 -150
  25. package/dist/lib/components/message/message-item.component.js.map +1 -1
  26. package/dist/lib/components/overlay/chat-overlay.component.d.ts +15 -0
  27. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  28. package/dist/lib/components/overlay/chat-overlay.component.js +123 -46
  29. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  30. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +11 -0
  31. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  32. package/dist/lib/components/workspace/conversation-workspace.component.js +13 -3
  33. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  34. package/dist/lib/conversations.module.d.ts +59 -58
  35. package/dist/lib/conversations.module.d.ts.map +1 -1
  36. package/dist/lib/conversations.module.js +8 -4
  37. package/dist/lib/conversations.module.js.map +1 -1
  38. package/dist/lib/models/conversation-state.model.d.ts +0 -27
  39. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  40. package/dist/lib/models/conversation-state.model.js.map +1 -1
  41. package/dist/lib/services/conversation-agent.service.d.ts +1 -9
  42. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  43. package/dist/lib/services/conversation-agent.service.js +22 -121
  44. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  45. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -1
  46. package/dist/lib/services/conversation-attachment.service.js +5 -26
  47. package/dist/lib/services/conversation-attachment.service.js.map +1 -1
  48. package/dist/lib/services/conversation-bridge.service.d.ts +13 -0
  49. package/dist/lib/services/conversation-bridge.service.d.ts.map +1 -1
  50. package/dist/lib/services/conversation-bridge.service.js +15 -0
  51. package/dist/lib/services/conversation-bridge.service.js.map +1 -1
  52. package/package.json +23 -22
  53. package/dist/lib/components/message/suggested-responses.component.d.ts +0 -55
  54. package/dist/lib/components/message/suggested-responses.component.d.ts.map +0 -1
  55. package/dist/lib/components/message/suggested-responses.component.js +0 -207
  56. package/dist/lib/components/message/suggested-responses.component.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-conversations",
3
- "version": "5.37.0",
3
+ "version": "5.38.0",
4
4
  "description": "MemberJunction: Conversation, Collection, and Artifact management components for any Angular application",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -29,29 +29,30 @@
29
29
  "@angular/router": "21.1.3"
30
30
  },
31
31
  "dependencies": {
32
- "@memberjunction/ng-ui-components": "5.37.0",
33
32
  "@angular/animations": "21.1.3",
34
33
  "@angular/cdk": "21.1.3",
35
- "@memberjunction/ai": "5.37.0",
36
- "@memberjunction/ai-agent-client": "5.37.0",
37
- "@memberjunction/ai-core-plus": "5.37.0",
38
- "@memberjunction/ai-engine-base": "5.37.0",
39
- "@memberjunction/ng-agent-client": "5.37.0",
40
- "@memberjunction/core": "5.37.0",
41
- "@memberjunction/core-entities": "5.37.0",
42
- "@memberjunction/global": "5.37.0",
43
- "@memberjunction/graphql-dataprovider": "5.37.0",
44
- "@memberjunction/ng-artifacts": "5.37.0",
45
- "@memberjunction/ng-base-types": "5.37.0",
46
- "@memberjunction/ng-code-editor": "5.37.0",
47
- "@memberjunction/ng-container-directives": "5.37.0",
48
- "@memberjunction/ng-forms": "5.37.0",
49
- "@memberjunction/ng-markdown": "5.37.0",
50
- "@memberjunction/ng-notifications": "5.37.0",
51
- "@memberjunction/ng-resource-permissions": "5.37.0",
52
- "@memberjunction/ng-shared-generic": "5.37.0",
53
- "@memberjunction/ng-tasks": "5.37.0",
54
- "@memberjunction/ng-testing": "5.37.0",
34
+ "@memberjunction/ai": "5.38.0",
35
+ "@memberjunction/ai-agent-client": "5.38.0",
36
+ "@memberjunction/ai-core-plus": "5.38.0",
37
+ "@memberjunction/ai-engine-base": "5.38.0",
38
+ "@memberjunction/core": "5.38.0",
39
+ "@memberjunction/core-entities": "5.38.0",
40
+ "@memberjunction/global": "5.38.0",
41
+ "@memberjunction/graphql-dataprovider": "5.38.0",
42
+ "@memberjunction/interactive-component-types": "5.38.0",
43
+ "@memberjunction/ng-agent-client": "5.38.0",
44
+ "@memberjunction/ng-artifacts": "5.38.0",
45
+ "@memberjunction/ng-base-types": "5.38.0",
46
+ "@memberjunction/ng-code-editor": "5.38.0",
47
+ "@memberjunction/ng-container-directives": "5.38.0",
48
+ "@memberjunction/ng-forms": "5.38.0",
49
+ "@memberjunction/ng-markdown": "5.38.0",
50
+ "@memberjunction/ng-notifications": "5.38.0",
51
+ "@memberjunction/ng-resource-permissions": "5.38.0",
52
+ "@memberjunction/ng-shared-generic": "5.38.0",
53
+ "@memberjunction/ng-tasks": "5.38.0",
54
+ "@memberjunction/ng-testing": "5.38.0",
55
+ "@memberjunction/ng-ui-components": "5.38.0",
55
56
  "rxjs": "^7.8.2",
56
57
  "tslib": "^2.8.1"
57
58
  },
@@ -1,55 +0,0 @@
1
- import { EventEmitter, ElementRef, ChangeDetectorRef, OnInit, AfterViewInit } from '@angular/core';
2
- import { SuggestedResponse } from '../../models/conversation-state.model';
3
- import * as i0 from "@angular/core";
4
- /**
5
- * Component for displaying suggested response options below AI messages
6
- * Provides quick reply buttons and optional text input for streamlined conversation flow
7
- */
8
- export declare class SuggestedResponsesComponent implements OnInit, AfterViewInit {
9
- private cdr;
10
- suggestedResponses: SuggestedResponse[];
11
- disabled: boolean;
12
- isLastMessage: boolean;
13
- isConversationOwner: boolean;
14
- responseSelected: EventEmitter<{
15
- text: string;
16
- customInput?: string;
17
- }>;
18
- inputField?: ElementRef<HTMLInputElement>;
19
- customInputValue: string;
20
- constructor(cdr: ChangeDetectorRef);
21
- ngOnInit(): void;
22
- ngAfterViewInit(): void;
23
- /**
24
- * Get all regular button responses (not input fields)
25
- */
26
- get regularResponses(): SuggestedResponse[];
27
- /**
28
- * Get the input response option (if any)
29
- * Only supports one input option per message
30
- */
31
- get inputResponse(): SuggestedResponse | null;
32
- /**
33
- * Check if component should be visible
34
- */
35
- get isVisible(): boolean;
36
- /**
37
- * Handle regular button click
38
- */
39
- onResponseClick(response: SuggestedResponse): void;
40
- /**
41
- * Handle input submission (Enter key or submit button click)
42
- */
43
- onInputSubmit(): void;
44
- /**
45
- * Handle Enter key in input field
46
- */
47
- onInputKeydown(event: KeyboardEvent): void;
48
- /**
49
- * Track by function for ngFor to help Angular track items
50
- */
51
- trackByIndex(index: number): number;
52
- static ɵfac: i0.ɵɵFactoryDeclaration<SuggestedResponsesComponent, never>;
53
- static ɵcmp: i0.ɵɵComponentDeclaration<SuggestedResponsesComponent, "mj-suggested-responses", never, { "suggestedResponses": { "alias": "suggestedResponses"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "isLastMessage": { "alias": "isLastMessage"; "required": false; }; "isConversationOwner": { "alias": "isConversationOwner"; "required": false; }; }, { "responseSelected": "responseSelected"; }, never, never, false, never>;
54
- }
55
- //# sourceMappingURL=suggested-responses.component.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"suggested-responses.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/message/suggested-responses.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAa,UAAU,EAAE,iBAAiB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxI,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;;AAE1E;;;GAGG;AACH,qBAMa,2BAA4B,YAAW,MAAM,EAAE,aAAa;IAY3D,OAAO,CAAC,GAAG;IAXd,kBAAkB,EAAE,iBAAiB,EAAE,CAAM;IAC7C,QAAQ,EAAE,OAAO,CAAS;IAC1B,aAAa,EAAE,OAAO,CAAS;IAC/B,mBAAmB,EAAE,OAAO,CAAS;IAEpC,gBAAgB;cAA2B,MAAM;sBAAgB,MAAM;OAAK;IAE7D,UAAU,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAE5D,gBAAgB,EAAE,MAAM,CAAM;gBAEjB,GAAG,EAAE,iBAAiB;IAI1C,QAAQ;IAYR,eAAe;IAIf;;OAEG;IACH,IAAW,gBAAgB,IAAI,iBAAiB,EAAE,CAEjD;IAED;;;OAGG;IACH,IAAW,aAAa,IAAI,iBAAiB,GAAG,IAAI,CAEnD;IAED;;OAEG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;OAEG;IACI,eAAe,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAgBzD;;OAEG;IACI,aAAa,IAAI,IAAI;IAmB5B;;OAEG;IACI,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAOjD;;OAEG;IACI,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;yCA5G/B,2BAA2B;2CAA3B,2BAA2B;CA+GvC"}
@@ -1,207 +0,0 @@
1
- import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
2
- import * as i0 from "@angular/core";
3
- import * as i1 from "@angular/forms";
4
- const _c0 = ["inputField"];
5
- function SuggestedResponsesComponent_Conditional_0_For_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
6
- i0.ɵɵelement(0, "i");
7
- } if (rf & 2) {
8
- const response_r2 = i0.ɵɵnextContext().$implicit;
9
- i0.ɵɵclassMap("fas " + response_r2.iconClass);
10
- } }
11
- function SuggestedResponsesComponent_Conditional_0_For_7_Template(rf, ctx) { if (rf & 1) {
12
- const _r1 = i0.ɵɵgetCurrentView();
13
- i0.ɵɵelementStart(0, "button", 7);
14
- i0.ɵɵlistener("click", function SuggestedResponsesComponent_Conditional_0_For_7_Template_button_click_0_listener() { const response_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onResponseClick(response_r2)); });
15
- i0.ɵɵconditionalCreate(1, SuggestedResponsesComponent_Conditional_0_For_7_Conditional_1_Template, 1, 2, "i", 8);
16
- i0.ɵɵelementStart(2, "span");
17
- i0.ɵɵtext(3);
18
- i0.ɵɵelementEnd()();
19
- } if (rf & 2) {
20
- const response_r2 = ctx.$implicit;
21
- const ctx_r2 = i0.ɵɵnextContext(2);
22
- i0.ɵɵproperty("disabled", ctx_r2.disabled)("title", response_r2.text);
23
- i0.ɵɵadvance();
24
- i0.ɵɵconditional(response_r2.iconClass ? 1 : -1);
25
- i0.ɵɵadvance(2);
26
- i0.ɵɵtextInterpolate(response_r2.text);
27
- } }
28
- function SuggestedResponsesComponent_Conditional_0_Conditional_8_Conditional_1_Template(rf, ctx) { if (rf & 1) {
29
- i0.ɵɵelement(0, "i", 13);
30
- } if (rf & 2) {
31
- const ctx_r2 = i0.ɵɵnextContext(3);
32
- i0.ɵɵclassMap("fas " + ctx_r2.inputResponse.iconClass);
33
- } }
34
- function SuggestedResponsesComponent_Conditional_0_Conditional_8_Template(rf, ctx) { if (rf & 1) {
35
- const _r4 = i0.ɵɵgetCurrentView();
36
- i0.ɵɵelementStart(0, "div", 6);
37
- i0.ɵɵconditionalCreate(1, SuggestedResponsesComponent_Conditional_0_Conditional_8_Conditional_1_Template, 1, 2, "i", 9);
38
- i0.ɵɵelementStart(2, "input", 10, 0);
39
- i0.ɵɵtwoWayListener("ngModelChange", function SuggestedResponsesComponent_Conditional_0_Conditional_8_Template_input_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.customInputValue, $event) || (ctx_r2.customInputValue = $event); return i0.ɵɵresetView($event); });
40
- i0.ɵɵlistener("keydown", function SuggestedResponsesComponent_Conditional_0_Conditional_8_Template_input_keydown_2_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onInputKeydown($event)); });
41
- i0.ɵɵelementEnd();
42
- i0.ɵɵelementStart(4, "button", 11);
43
- i0.ɵɵlistener("click", function SuggestedResponsesComponent_Conditional_0_Conditional_8_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onInputSubmit()); });
44
- i0.ɵɵelement(5, "i", 12);
45
- i0.ɵɵelementEnd()();
46
- } if (rf & 2) {
47
- const ctx_r2 = i0.ɵɵnextContext(2);
48
- i0.ɵɵadvance();
49
- i0.ɵɵconditional(ctx_r2.inputResponse.iconClass ? 1 : -1);
50
- i0.ɵɵadvance();
51
- i0.ɵɵproperty("placeholder", ctx_r2.inputResponse.text);
52
- i0.ɵɵtwoWayProperty("ngModel", ctx_r2.customInputValue);
53
- i0.ɵɵproperty("disabled", ctx_r2.disabled);
54
- i0.ɵɵadvance(2);
55
- i0.ɵɵproperty("disabled", ctx_r2.disabled || !ctx_r2.customInputValue || !ctx_r2.customInputValue.trim());
56
- } }
57
- function SuggestedResponsesComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
58
- i0.ɵɵelementStart(0, "div", 1)(1, "div", 2);
59
- i0.ɵɵelement(2, "i", 3);
60
- i0.ɵɵelementStart(3, "span");
61
- i0.ɵɵtext(4, "Quick replies");
62
- i0.ɵɵelementEnd()();
63
- i0.ɵɵelementStart(5, "div", 4);
64
- i0.ɵɵrepeaterCreate(6, SuggestedResponsesComponent_Conditional_0_For_7_Template, 4, 4, "button", 5, i0.ɵɵrepeaterTrackByIndex);
65
- i0.ɵɵconditionalCreate(8, SuggestedResponsesComponent_Conditional_0_Conditional_8_Template, 6, 5, "div", 6);
66
- i0.ɵɵelementEnd()();
67
- } if (rf & 2) {
68
- const ctx_r2 = i0.ɵɵnextContext();
69
- i0.ɵɵadvance(6);
70
- i0.ɵɵrepeater(ctx_r2.regularResponses);
71
- i0.ɵɵadvance(2);
72
- i0.ɵɵconditional(ctx_r2.inputResponse ? 8 : -1);
73
- } }
74
- /**
75
- * Component for displaying suggested response options below AI messages
76
- * Provides quick reply buttons and optional text input for streamlined conversation flow
77
- */
78
- export class SuggestedResponsesComponent {
79
- cdr;
80
- suggestedResponses = [];
81
- disabled = false;
82
- isLastMessage = false;
83
- isConversationOwner = false;
84
- responseSelected = new EventEmitter();
85
- inputField;
86
- customInputValue = '';
87
- constructor(cdr) {
88
- this.cdr = cdr;
89
- console.log('🏗️ SuggestedResponsesComponent constructed');
90
- }
91
- ngOnInit() {
92
- console.log('🎬 SuggestedResponsesComponent.ngOnInit', {
93
- suggestedResponses: this.suggestedResponses,
94
- disabled: this.disabled,
95
- isLastMessage: this.isLastMessage,
96
- isConversationOwner: this.isConversationOwner,
97
- isVisible: this.isVisible,
98
- regularResponses: this.regularResponses,
99
- regularResponsesLength: this.regularResponses.length
100
- });
101
- }
102
- ngAfterViewInit() {
103
- console.log('👁️ SuggestedResponsesComponent.ngAfterViewInit - component rendered');
104
- }
105
- /**
106
- * Get all regular button responses (not input fields)
107
- */
108
- get regularResponses() {
109
- return this.suggestedResponses.filter(r => !r.allowInput);
110
- }
111
- /**
112
- * Get the input response option (if any)
113
- * Only supports one input option per message
114
- */
115
- get inputResponse() {
116
- return this.suggestedResponses.find(r => r.allowInput) || null;
117
- }
118
- /**
119
- * Check if component should be visible
120
- */
121
- get isVisible() {
122
- return this.isLastMessage && this.isConversationOwner && this.suggestedResponses.length > 0;
123
- }
124
- /**
125
- * Handle regular button click
126
- */
127
- onResponseClick(response) {
128
- console.log('🖱️ BUTTON CLICKED!', {
129
- response,
130
- disabled: this.disabled,
131
- willEmit: !this.disabled
132
- });
133
- if (!this.disabled) {
134
- console.log('📤 Emitting responseSelected event');
135
- this.responseSelected.emit({ text: response.text });
136
- console.log('✅ Event emitted');
137
- }
138
- else {
139
- console.warn('⚠️ Button is disabled, not emitting');
140
- }
141
- }
142
- /**
143
- * Handle input submission (Enter key or submit button click)
144
- */
145
- onInputSubmit() {
146
- const trimmedValue = this.customInputValue?.trim();
147
- if (!this.disabled && trimmedValue && this.inputResponse) {
148
- this.responseSelected.emit({
149
- text: this.inputResponse.text,
150
- customInput: trimmedValue
151
- });
152
- this.customInputValue = '';
153
- // Clear input field and trigger change detection
154
- Promise.resolve().then(() => {
155
- if (this.inputField) {
156
- this.inputField.nativeElement.value = '';
157
- }
158
- this.cdr.detectChanges();
159
- });
160
- }
161
- }
162
- /**
163
- * Handle Enter key in input field
164
- */
165
- onInputKeydown(event) {
166
- if (event.key === 'Enter' && !event.shiftKey) {
167
- event.preventDefault();
168
- this.onInputSubmit();
169
- }
170
- }
171
- /**
172
- * Track by function for ngFor to help Angular track items
173
- */
174
- trackByIndex(index) {
175
- return index;
176
- }
177
- static ɵfac = function SuggestedResponsesComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SuggestedResponsesComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
178
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SuggestedResponsesComponent, selectors: [["mj-suggested-responses"]], viewQuery: function SuggestedResponsesComponent_Query(rf, ctx) { if (rf & 1) {
179
- i0.ɵɵviewQuery(_c0, 5);
180
- } if (rf & 2) {
181
- let _t;
182
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.inputField = _t.first);
183
- } }, inputs: { suggestedResponses: "suggestedResponses", disabled: "disabled", isLastMessage: "isLastMessage", isConversationOwner: "isConversationOwner" }, outputs: { responseSelected: "responseSelected" }, standalone: false, decls: 1, vars: 1, consts: [["inputField", ""], [1, "suggested-responses"], [1, "suggested-responses-header"], [1, "fa", "fa-lightbulb"], [1, "suggested-responses-buttons"], ["type", "button", 1, "suggested-response-btn", 3, "disabled", "title"], [1, "suggested-response-input-container"], ["type", "button", 1, "suggested-response-btn", 3, "click", "disabled", "title"], [3, "class"], [1, "input-icon", 3, "class"], ["type", "text", "autocomplete", "off", 1, "suggested-response-input", 3, "ngModelChange", "keydown", "placeholder", "ngModel", "disabled"], ["title", "Submit", 1, "suggested-response-submit", 3, "click", "disabled"], [1, "fa", "fa-paper-plane"], [1, "input-icon"]], template: function SuggestedResponsesComponent_Template(rf, ctx) { if (rf & 1) {
184
- i0.ɵɵconditionalCreate(0, SuggestedResponsesComponent_Conditional_0_Template, 9, 1, "div", 1);
185
- } if (rf & 2) {
186
- i0.ɵɵconditional(ctx.isVisible ? 0 : -1);
187
- } }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel], styles: [".suggested-responses[_ngcontent-%COMP%] {\n margin-top: 16px;\n padding: 14px 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-text-primary) 4%, transparent);\n}\n\n.suggested-responses-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 10px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.suggested-responses-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-status-warning);\n}\n\n.suggested-responses-buttons[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n}\n\n.suggested-response-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n color: var(--mj-text-primary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 5%, transparent);\n}\n\n.suggested-response-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.suggested-response-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n\n.suggested-response-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n background: var(--mj-bg-surface-sunken);\n}\n\n.suggested-response-input-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 250px;\n max-width: 500px;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 6px 8px 6px 12px;\n transition: all 0.2s ease;\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 5%, transparent);\n}\n\n.suggested-response-input-container[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.suggested-response-input-container[_ngcontent-%COMP%] .input-icon[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.suggested-response-input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n font-size: 14px;\n padding: 6px 8px;\n background: transparent;\n color: var(--mj-text-primary);\n}\n\n.suggested-response-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-muted);\n font-style: italic;\n opacity: 1;\n}\n\n.suggested-response-input[_ngcontent-%COMP%]:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.suggested-response-submit[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px 14px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.suggested-response-submit[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.suggested-response-submit[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.suggested-response-submit[_ngcontent-%COMP%]:active:not(:disabled) {\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n.suggested-response-submit[_ngcontent-%COMP%]:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n background: var(--mj-text-muted);\n box-shadow: none;\n}\n\n\n\n@media (max-width: 768px) {\n .suggested-responses-buttons[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n }\n\n .suggested-response-btn[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n .suggested-response-input-container[_ngcontent-%COMP%] {\n max-width: 100%;\n }\n}"] });
188
- }
189
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SuggestedResponsesComponent, [{
190
- type: Component,
191
- args: [{ standalone: false, selector: 'mj-suggested-responses', template: "@if (isVisible) {\n <div class=\"suggested-responses\">\n <div class=\"suggested-responses-header\">\n <i class=\"fa fa-lightbulb\"></i>\n <span>Quick replies</span>\n </div>\n <div class=\"suggested-responses-buttons\">\n <!-- TEST: Native onclick\n <button type=\"button\" onclick=\"alert('Native onclick works!');\" style=\"background: red; color: white;\">TEST</button>\n -->\n <!-- Regular button responses (allowInput: false) -->\n @for (response of regularResponses; track $index) {\n <button\n type=\"button\"\n class=\"suggested-response-btn\"\n [disabled]=\"disabled\"\n (click)=\"onResponseClick(response)\"\n [title]=\"response.text\">\n @if (response.iconClass) {\n <i [class]=\"'fas ' + response.iconClass\"></i>\n }\n <span>{{ response.text }}</span>\n </button>\n }\n <!-- Input option (allowInput: true) -->\n @if (inputResponse) {\n <div class=\"suggested-response-input-container\">\n @if (inputResponse.iconClass) {\n <i [class]=\"'fas ' + inputResponse.iconClass\" class=\"input-icon\"></i>\n }\n <input\n type=\"text\"\n class=\"suggested-response-input\"\n [placeholder]=\"inputResponse.text\"\n [(ngModel)]=\"customInputValue\"\n [disabled]=\"disabled\"\n (keydown)=\"onInputKeydown($event)\"\n #inputField\n autocomplete=\"off\">\n <button\n class=\"suggested-response-submit\"\n [disabled]=\"disabled || !customInputValue || !customInputValue.trim()\"\n (click)=\"onInputSubmit()\"\n title=\"Submit\">\n <i class=\"fa fa-paper-plane\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n}\n", styles: [".suggested-responses {\n margin-top: 16px;\n padding: 14px 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n box-shadow: 0 2px 4px color-mix(in srgb, var(--mj-text-primary) 4%, transparent);\n}\n\n.suggested-responses-header {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 10px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.suggested-responses-header i {\n font-size: 13px;\n color: var(--mj-status-warning);\n}\n\n.suggested-responses-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n}\n\n.suggested-response-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n color: var(--mj-text-primary);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 5%, transparent);\n}\n\n.suggested-response-btn i {\n font-size: 14px;\n}\n\n.suggested-response-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n\n.suggested-response-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n background: var(--mj-bg-surface-sunken);\n}\n\n.suggested-response-input-container {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 250px;\n max-width: 500px;\n background: var(--mj-bg-surface-card);\n border: 2px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 6px 8px 6px 12px;\n transition: all 0.2s ease;\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 5%, transparent);\n}\n\n.suggested-response-input-container:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n}\n\n.suggested-response-input-container .input-icon {\n font-size: 16px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n.suggested-response-input {\n flex: 1;\n border: none;\n outline: none;\n font-size: 14px;\n padding: 6px 8px;\n background: transparent;\n color: var(--mj-text-primary);\n}\n\n.suggested-response-input::placeholder {\n color: var(--mj-text-muted);\n font-style: italic;\n opacity: 1;\n}\n\n.suggested-response-input:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.suggested-response-submit {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px 14px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.suggested-response-submit i {\n font-size: 14px;\n}\n\n.suggested-response-submit:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.suggested-response-submit:active:not(:disabled) {\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n}\n\n.suggested-response-submit:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n background: var(--mj-text-muted);\n box-shadow: none;\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n .suggested-responses-buttons {\n flex-direction: column;\n align-items: stretch;\n }\n\n .suggested-response-btn {\n justify-content: center;\n }\n\n .suggested-response-input-container {\n max-width: 100%;\n }\n}\n"] }]
192
- }], () => [{ type: i0.ChangeDetectorRef }], { suggestedResponses: [{
193
- type: Input
194
- }], disabled: [{
195
- type: Input
196
- }], isLastMessage: [{
197
- type: Input
198
- }], isConversationOwner: [{
199
- type: Input
200
- }], responseSelected: [{
201
- type: Output
202
- }], inputField: [{
203
- type: ViewChild,
204
- args: ['inputField']
205
- }] }); })();
206
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SuggestedResponsesComponent, { className: "SuggestedResponsesComponent", filePath: "src/lib/components/message/suggested-responses.component.ts", lineNumber: 14 }); })();
207
- //# sourceMappingURL=suggested-responses.component.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"suggested-responses.component.js","sourceRoot":"","sources":["../../../../src/lib/components/message/suggested-responses.component.ts","../../../../src/lib/components/message/suggested-responses.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, ChangeDetectorRef, OnInit, AfterViewInit } from '@angular/core';\nimport { SuggestedResponse } from '../../models/conversation-state.model';\n\n/**\n * Component for displaying suggested response options below AI messages\n * Provides quick reply buttons and optional text input for streamlined conversation flow\n */\n@Component({\n standalone: false,\n selector: 'mj-suggested-responses',\n templateUrl: './suggested-responses.component.html',\n styleUrls: ['./suggested-responses.component.css']\n})\nexport class SuggestedResponsesComponent implements OnInit, AfterViewInit {\n @Input() suggestedResponses: SuggestedResponse[] = [];\n @Input() disabled: boolean = false;\n @Input() isLastMessage: boolean = false;\n @Input() isConversationOwner: boolean = false;\n\n @Output() responseSelected = new EventEmitter<{text: string; customInput?: string}>();\n\n @ViewChild('inputField') inputField?: ElementRef<HTMLInputElement>;\n\n public customInputValue: string = '';\n\n constructor(private cdr: ChangeDetectorRef) {\n console.log('🏗️ SuggestedResponsesComponent constructed');\n }\n\n ngOnInit() {\n console.log('🎬 SuggestedResponsesComponent.ngOnInit', {\n suggestedResponses: this.suggestedResponses,\n disabled: this.disabled,\n isLastMessage: this.isLastMessage,\n isConversationOwner: this.isConversationOwner,\n isVisible: this.isVisible,\n regularResponses: this.regularResponses,\n regularResponsesLength: this.regularResponses.length\n });\n }\n\n ngAfterViewInit() {\n console.log('👁️ SuggestedResponsesComponent.ngAfterViewInit - component rendered');\n }\n\n /**\n * Get all regular button responses (not input fields)\n */\n public get regularResponses(): SuggestedResponse[] {\n return this.suggestedResponses.filter(r => !r.allowInput);\n }\n\n /**\n * Get the input response option (if any)\n * Only supports one input option per message\n */\n public get inputResponse(): SuggestedResponse | null {\n return this.suggestedResponses.find(r => r.allowInput) || null;\n }\n\n /**\n * Check if component should be visible\n */\n public get isVisible(): boolean {\n return this.isLastMessage && this.isConversationOwner && this.suggestedResponses.length > 0;\n }\n\n /**\n * Handle regular button click\n */\n public onResponseClick(response: SuggestedResponse): void {\n console.log('🖱️ BUTTON CLICKED!', {\n response,\n disabled: this.disabled,\n willEmit: !this.disabled\n });\n\n if (!this.disabled) {\n console.log('📤 Emitting responseSelected event');\n this.responseSelected.emit({ text: response.text });\n console.log('✅ Event emitted');\n } else {\n console.warn('⚠️ Button is disabled, not emitting');\n }\n }\n\n /**\n * Handle input submission (Enter key or submit button click)\n */\n public onInputSubmit(): void {\n const trimmedValue = this.customInputValue?.trim();\n if (!this.disabled && trimmedValue && this.inputResponse) {\n this.responseSelected.emit({\n text: this.inputResponse.text,\n customInput: trimmedValue\n });\n this.customInputValue = '';\n\n // Clear input field and trigger change detection\n Promise.resolve().then(() => {\n if (this.inputField) {\n this.inputField.nativeElement.value = '';\n }\n this.cdr.detectChanges();\n });\n }\n }\n\n /**\n * Handle Enter key in input field\n */\n public onInputKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n this.onInputSubmit();\n }\n }\n\n /**\n * Track by function for ngFor to help Angular track items\n */\n public trackByIndex(index: number): number {\n return index;\n }\n}\n","@if (isVisible) {\n <div class=\"suggested-responses\">\n <div class=\"suggested-responses-header\">\n <i class=\"fa fa-lightbulb\"></i>\n <span>Quick replies</span>\n </div>\n <div class=\"suggested-responses-buttons\">\n <!-- TEST: Native onclick\n <button type=\"button\" onclick=\"alert('Native onclick works!');\" style=\"background: red; color: white;\">TEST</button>\n -->\n <!-- Regular button responses (allowInput: false) -->\n @for (response of regularResponses; track $index) {\n <button\n type=\"button\"\n class=\"suggested-response-btn\"\n [disabled]=\"disabled\"\n (click)=\"onResponseClick(response)\"\n [title]=\"response.text\">\n @if (response.iconClass) {\n <i [class]=\"'fas ' + response.iconClass\"></i>\n }\n <span>{{ response.text }}</span>\n </button>\n }\n <!-- Input option (allowInput: true) -->\n @if (inputResponse) {\n <div class=\"suggested-response-input-container\">\n @if (inputResponse.iconClass) {\n <i [class]=\"'fas ' + inputResponse.iconClass\" class=\"input-icon\"></i>\n }\n <input\n type=\"text\"\n class=\"suggested-response-input\"\n [placeholder]=\"inputResponse.text\"\n [(ngModel)]=\"customInputValue\"\n [disabled]=\"disabled\"\n (keydown)=\"onInputKeydown($event)\"\n #inputField\n autocomplete=\"off\">\n <button\n class=\"suggested-response-submit\"\n [disabled]=\"disabled || !customInputValue || !customInputValue.trim()\"\n (click)=\"onInputSubmit()\"\n title=\"Submit\">\n <i class=\"fa fa-paper-plane\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n}\n"]}