@progress/kendo-angular-conversational-ui 21.0.0-develop.8 → 21.0.0-develop.9

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 (62) hide show
  1. package/chat/api/files-layout.d.ts +12 -0
  2. package/chat/api/index.d.ts +3 -1
  3. package/chat/api/message-settings.interface.d.ts +33 -0
  4. package/chat/api/message.interface.d.ts +5 -1
  5. package/chat/api/suggestions-layout.d.ts +20 -0
  6. package/chat/chat.component.d.ts +92 -34
  7. package/chat/chat.directives.d.ts +18 -0
  8. package/chat/chat.module.d.ts +15 -8
  9. package/chat/common/chat.service.d.ts +32 -3
  10. package/chat/common/models/model-fields.d.ts +0 -6
  11. package/chat/common/scroll-button.component.d.ts +32 -0
  12. package/chat/common/scroll.service.d.ts +39 -0
  13. package/chat/common/utils.d.ts +13 -1
  14. package/chat/l10n/messages.d.ts +9 -1
  15. package/chat/message-list.component.d.ts +20 -3
  16. package/chat/message.component.d.ts +40 -16
  17. package/chat/suggested-actions.component.d.ts +30 -5
  18. package/chat/templates/author-message-content-template.directive.d.ts +28 -0
  19. package/chat/templates/author-message-template.directive.d.ts +28 -0
  20. package/chat/templates/message-content-template.directive.d.ts +28 -0
  21. package/chat/templates/message-template.directive.d.ts +1 -1
  22. package/chat/templates/no-data-template.directive.d.ts +27 -0
  23. package/chat/templates/receiver-message-content-template.directive.d.ts +28 -0
  24. package/chat/templates/receiver-message-template.directive.d.ts +28 -0
  25. package/chat/templates/user-status-template.directive.d.ts +27 -0
  26. package/conversational-ui.module.d.ts +18 -11
  27. package/directives.d.ts +9 -2
  28. package/esm2022/chat/api/index.mjs +3 -1
  29. package/{chat/api/message-toolbar-visibility.d.ts → esm2022/chat/api/message-settings.interface.mjs} +1 -4
  30. package/esm2022/chat/api/suggestions-layout.mjs +5 -0
  31. package/esm2022/chat/builtin-actions.mjs +2 -0
  32. package/esm2022/chat/chat-file.component.mjs +2 -2
  33. package/esm2022/chat/chat.component.mjs +265 -71
  34. package/esm2022/chat/chat.directives.mjs +18 -0
  35. package/esm2022/chat/chat.module.mjs +16 -9
  36. package/esm2022/chat/common/chat.service.mjs +83 -4
  37. package/esm2022/chat/common/models/default-model-fields.mjs +0 -1
  38. package/esm2022/chat/common/scroll-button.component.mjs +81 -0
  39. package/esm2022/chat/common/scroll.service.mjs +110 -0
  40. package/esm2022/chat/common/utils.mjs +22 -3
  41. package/esm2022/chat/l10n/messages.mjs +13 -1
  42. package/esm2022/chat/message-attachments.component.mjs +2 -2
  43. package/esm2022/chat/message-box.component.mjs +5 -2
  44. package/esm2022/chat/message-list.component.mjs +165 -19
  45. package/esm2022/chat/message.component.mjs +487 -326
  46. package/esm2022/chat/suggested-actions.component.mjs +298 -80
  47. package/esm2022/chat/templates/author-message-content-template.directive.mjs +39 -0
  48. package/esm2022/chat/templates/author-message-template.directive.mjs +39 -0
  49. package/esm2022/chat/templates/message-content-template.directive.mjs +39 -0
  50. package/esm2022/chat/templates/message-template.directive.mjs +1 -1
  51. package/esm2022/chat/templates/no-data-template.directive.mjs +38 -0
  52. package/esm2022/chat/templates/receiver-message-content-template.directive.mjs +39 -0
  53. package/esm2022/chat/templates/receiver-message-template.directive.mjs +39 -0
  54. package/esm2022/chat/templates/user-status-template.directive.mjs +38 -0
  55. package/esm2022/conversational-ui.module.mjs +19 -12
  56. package/esm2022/directives.mjs +15 -1
  57. package/esm2022/index.mjs +7 -0
  58. package/esm2022/package-metadata.mjs +2 -2
  59. package/fesm2022/progress-kendo-angular-conversational-ui.mjs +1771 -547
  60. package/index.d.ts +7 -0
  61. package/package.json +14 -14
  62. /package/esm2022/chat/api/{message-toolbar-visibility.mjs → files-layout.mjs} +0 -0
@@ -4,28 +4,79 @@
4
4
  *-------------------------------------------------------------------------------------------*/
5
5
  /* eslint-disable @typescript-eslint/no-explicit-any */
6
6
  /* eslint-disable @typescript-eslint/no-empty-function */
7
- import { Component, EventEmitter, forwardRef, HostBinding, Input, Output, QueryList, ViewChildren } from '@angular/core';
7
+ import { Component, ElementRef, EventEmitter, forwardRef, HostBinding, Input, Output, QueryList, ViewChildren, ViewChild, NgZone, Renderer2 } from '@angular/core';
8
8
  import { NgFor, NgIf, NgTemplateOutlet } from '@angular/common';
9
+ import { Subscription } from 'rxjs';
10
+ import { take } from 'rxjs/operators';
9
11
  import { Keys, normalizeNumpadKeys } from '@progress/kendo-angular-common';
10
12
  import { ChatItem } from './chat-item';
11
13
  import { ChatSuggestionTemplateDirective } from './templates/suggestion-template.directive';
14
+ import { ChatService } from './common/chat.service';
15
+ import { ChatScrollableButtonComponent } from './common/scroll-button.component';
16
+ import { LocalizationService } from '@progress/kendo-angular-l10n';
17
+ import { SuggestionsScrollService } from './common/scroll.service';
12
18
  import * as i0 from "@angular/core";
19
+ import * as i1 from "./common/chat.service";
20
+ import * as i2 from "@progress/kendo-angular-l10n";
21
+ import * as i3 from "./common/scroll.service";
13
22
  /**
14
23
  * @hidden
15
24
  */
16
25
  export class SuggestedActionsComponent extends ChatItem {
26
+ chatService;
27
+ localization;
28
+ scrollService;
29
+ ngZone;
30
+ renderer;
31
+ get defaultClass() {
32
+ if (this.type === 'suggestion') {
33
+ return this.chatService.suggestionsLayout === 'wrap' || this.chatService.suggestionsLayout === 'scroll';
34
+ }
35
+ else if (this.type === 'action') {
36
+ return this.chatService.quickActionsLayout === 'wrap' || this.chatService.quickActionsLayout === 'scroll';
37
+ }
38
+ }
39
+ get scrollableClass() {
40
+ if (this.type === 'suggestion') {
41
+ return this.chatService.suggestionsLayout === 'scroll';
42
+ }
43
+ else if (this.type === 'action') {
44
+ return this.chatService.quickActionsLayout === 'scroll';
45
+ }
46
+ }
47
+ get scrollButtonsClass() {
48
+ if (this.type === 'suggestion') {
49
+ return this.chatService.suggestionsLayout === 'scrollbuttons';
50
+ }
51
+ else if (this.type === 'action') {
52
+ return this.chatService.quickActionsLayout === 'scrollbuttons';
53
+ }
54
+ }
55
+ get role() {
56
+ if (!this.hasScrollButtons) {
57
+ return 'group';
58
+ }
59
+ return null;
60
+ }
17
61
  actions;
18
62
  suggestions;
19
63
  tabbable;
64
+ type;
20
65
  suggestionTemplate;
21
66
  dispatchAction = new EventEmitter();
22
67
  dispatchSuggestion = new EventEmitter();
23
- defaultClass = true;
24
- role = 'group';
25
68
  items;
69
+ suggestionsContainer;
70
+ prevScrollButton;
71
+ nextScrollButton;
26
72
  selectedIndex = 0;
27
73
  activeIndex = -1;
28
74
  active = false;
75
+ get hasScrollButtons() {
76
+ return this.type === 'suggestion' ? this.chatService.suggestionsLayout === 'scrollbuttons' : this.chatService.quickActionsLayout === 'scrollbuttons';
77
+ }
78
+ subscriptions = new Subscription();
79
+ resizeObserver = null;
29
80
  actionKeyHandlers = {
30
81
  [Keys.Tab]: (e) => this.changeSelectedIndex(e),
31
82
  [Keys.Enter]: (_, action) => this.actionClick(action),
@@ -36,6 +87,58 @@ export class SuggestedActionsComponent extends ChatItem {
36
87
  [Keys.Enter]: (_, suggestion) => this.suggestionClick(suggestion),
37
88
  [Keys.Space]: (_, suggestion) => this.suggestionClick(suggestion),
38
89
  };
90
+ constructor(chatService, localization, scrollService, ngZone, renderer) {
91
+ super();
92
+ this.chatService = chatService;
93
+ this.localization = localization;
94
+ this.scrollService = scrollService;
95
+ this.ngZone = ngZone;
96
+ this.renderer = renderer;
97
+ this.scrollService.owner = this;
98
+ }
99
+ ngAfterViewInit() {
100
+ const layoutChangeObservable = this.type === 'suggestion'
101
+ ? this.chatService.suggestionsLayoutChange$
102
+ : this.chatService.quickActionsLayoutChange$;
103
+ this.subscriptions.add(layoutChangeObservable.subscribe((layoutMode) => {
104
+ if (layoutMode === 'scrollbuttons') {
105
+ this.ngZone.onStable.pipe(take(1)).subscribe(() => {
106
+ if (this.suggestionsContainer) {
107
+ this.scrollService.updateScrollPosition(this.suggestionsContainer.nativeElement);
108
+ }
109
+ this.scrollService.toggleScrollButtonsState();
110
+ });
111
+ }
112
+ }));
113
+ this.subscriptions.add(this.scrollService.scrollButtonActiveStateChange.subscribe((change) => {
114
+ this.toggleScrollButtonState(change.buttonType, change.active);
115
+ }));
116
+ if (this.hasScrollButtons && this.suggestionsContainer) {
117
+ this.ngZone.runOutsideAngular(() => {
118
+ this.resizeObserver = new ResizeObserver(() => {
119
+ this.ngZone.run(() => {
120
+ this.scrollService.toggleScrollButtonsState();
121
+ });
122
+ });
123
+ this.resizeObserver.observe(this.suggestionsContainer.nativeElement);
124
+ });
125
+ }
126
+ if (this.hasScrollButtons) {
127
+ this.ngZone.onStable.pipe(take(1)).subscribe(() => {
128
+ this.scrollService.toggleScrollButtonsState();
129
+ });
130
+ if (this.suggestionsContainer) {
131
+ this.scrollService.updateScrollPosition(this.suggestionsContainer.nativeElement);
132
+ }
133
+ }
134
+ }
135
+ ngOnDestroy() {
136
+ this.subscriptions.unsubscribe();
137
+ if (this.resizeObserver) {
138
+ this.resizeObserver.disconnect();
139
+ this.resizeObserver = null;
140
+ }
141
+ }
39
142
  isSelected(index) {
40
143
  return this.selected && this.selectedIndex === index;
41
144
  }
@@ -69,67 +172,130 @@ export class SuggestedActionsComponent extends ChatItem {
69
172
  handler(e, suggestion);
70
173
  }
71
174
  }
175
+ getScrollButtonTitle(direction) {
176
+ let currentButton;
177
+ if (this.localization.rtl) {
178
+ currentButton = direction === 'prev' ? 'nextSuggestionsButtonTitle' : 'previousSuggestionsButtonTitle';
179
+ }
180
+ else {
181
+ currentButton = direction === 'prev' ? 'previousSuggestionsButtonTitle' : 'nextSuggestionsButtonTitle';
182
+ }
183
+ return this.localization.get(currentButton);
184
+ }
185
+ onScroll(event) {
186
+ this.scrollService.onScroll(event);
187
+ }
188
+ scrollSuggestions(direction) {
189
+ this.scrollService.scrollSuggestions(direction);
190
+ }
72
191
  focus() { }
192
+ toggleScrollButtonState(buttonType, active) {
193
+ const button = this[`${buttonType}ScrollButton`];
194
+ if (button?.nativeElement) {
195
+ if (active) {
196
+ this.renderer.removeClass(button.nativeElement, 'k-disabled');
197
+ }
198
+ else {
199
+ this.renderer.addClass(button.nativeElement, 'k-disabled');
200
+ }
201
+ }
202
+ }
73
203
  changeSelectedIndex(e) {
74
204
  const offset = e.shiftKey ? -1 : 1;
75
205
  const prevIndex = this.selectedIndex;
76
206
  this.selectedIndex = Math.max(0, Math.min(prevIndex + offset, this.items.length - 1));
77
207
  }
78
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SuggestedActionsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
79
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SuggestedActionsComponent, isStandalone: true, selector: "kendo-chat-suggested-actions", inputs: { actions: "actions", suggestions: "suggestions", tabbable: "tabbable", suggestionTemplate: "suggestionTemplate" }, outputs: { dispatchAction: "dispatchAction", dispatchSuggestion: "dispatchSuggestion" }, host: { properties: { "class.k-suggestion-group": "this.defaultClass", "attr.role": "this.role" } }, providers: [{
208
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SuggestedActionsComponent, deps: [{ token: i1.ChatService }, { token: i2.LocalizationService }, { token: i3.SuggestionsScrollService }, { token: i0.NgZone }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
209
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SuggestedActionsComponent, isStandalone: true, selector: "kendo-chat-suggested-actions", inputs: { actions: "actions", suggestions: "suggestions", tabbable: "tabbable", type: "type", suggestionTemplate: "suggestionTemplate" }, outputs: { dispatchAction: "dispatchAction", dispatchSuggestion: "dispatchSuggestion" }, host: { properties: { "class.k-suggestion-group": "this.defaultClass", "class.k-suggestion-group-scrollable": "this.scrollableClass", "class.k-suggestion-scrollwrap": "this.scrollButtonsClass", "attr.role": "this.role" } }, providers: [{
80
210
  provide: ChatItem,
81
211
  useExisting: forwardRef(() => SuggestedActionsComponent)
82
- }], viewQueries: [{ propertyName: "items", predicate: ["item"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
83
- <ng-container *ngIf="actions">
84
- <span
85
- #item
86
- *ngFor="let action of actions; index as index; first as first; last as last"
87
- class="k-suggestion k-suggestion-primary"
88
- role="button"
89
- [class.k-selected]="isSelected(index)"
90
- [class.k-focus]="isSelected(index)"
91
- [class.k-active]="isActive(index)"
92
- [attr.tabindex]="0"
93
- (click)="actionClick(action, index)"
94
- (keydown)="actionKeydown($event, action)"
95
- (mousedown)="toggleActiveState(true, index)"
96
- (mouseup)="toggleActiveState(false, index)"
97
- >
98
- {{ action.title || action.value }}
99
- </span>
100
- </ng-container>
212
+ },
213
+ SuggestionsScrollService
214
+ ], viewQueries: [{ propertyName: "suggestionsContainer", first: true, predicate: ["suggestionsContainer"], descendants: true, read: ElementRef }, { propertyName: "prevScrollButton", first: true, predicate: ["prevScrollButton"], descendants: true, read: ElementRef }, { propertyName: "nextScrollButton", first: true, predicate: ["nextScrollButton"], descendants: true, read: ElementRef }, { propertyName: "items", predicate: ["item"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
215
+ <span
216
+ *ngIf="hasScrollButtons"
217
+ #prevScrollButton
218
+ kendoChatScrollableButton
219
+ [prev]="true"
220
+ [title]="getScrollButtonTitle('prev')"
221
+ class="k-button k-button-md k-button-solid k-button-solid-base k-rounded-md k-icon-button"
222
+ (onClick)="scrollSuggestions($event)"
223
+ >
224
+ </span>
225
+ <div class="k-suggestion-group" *ngIf="hasScrollButtons; else noScrollButtons"
226
+ #suggestionsContainer
227
+ role="group"
228
+ (scroll)="onScroll($event)">
229
+ <ng-container *ngTemplateOutlet="suggestionsContent"></ng-container>
230
+ </div>
231
+
232
+ <ng-template #noScrollButtons>
233
+ <ng-container *ngTemplateOutlet="suggestionsContent"></ng-container>
234
+ </ng-template>
101
235
 
102
- <ng-container *ngIf="suggestions">
103
- <ng-container *ngIf="!suggestionTemplate?.templateRef">
236
+ <ng-template #suggestionsContent>
237
+ <ng-container *ngIf="actions">
104
238
  <span
105
239
  #item
106
- *ngFor="let suggestion of suggestions; index as index; first as first; last as last"
107
- class="k-suggestion"
240
+ *ngFor="let action of actions; index as index; first as first; last as last"
241
+ class="k-suggestion k-suggestion-primary"
108
242
  role="button"
109
243
  [class.k-selected]="isSelected(index)"
110
244
  [class.k-focus]="isSelected(index)"
111
245
  [class.k-active]="isActive(index)"
112
246
  [attr.tabindex]="0"
113
- (click)="suggestionClick(suggestion, index)"
114
- (keydown)="suggestionKeydown($event, suggestion)"
247
+ (click)="actionClick(action, index)"
248
+ (keydown)="actionKeydown($event, action)"
115
249
  (mousedown)="toggleActiveState(true, index)"
116
250
  (mouseup)="toggleActiveState(false, index)"
117
251
  >
118
- {{ suggestion.text }}
252
+ {{ action.title || action.value }}
119
253
  </span>
120
254
  </ng-container>
121
255
 
122
- <ng-container *ngIf="suggestionTemplate?.templateRef">
123
- <ng-container *ngFor="let suggestion of suggestions">
124
- <ng-template
125
- [ngTemplateOutlet]="suggestionTemplate.templateRef"
126
- [ngTemplateOutletContext]="{ $implicit: suggestion }"
256
+ <ng-container *ngIf="suggestions">
257
+ <ng-container *ngIf="!suggestionTemplate?.templateRef">
258
+ <span
259
+ #item
260
+ *ngFor="let suggestion of suggestions; index as index; first as first; last as last"
261
+ class="k-suggestion"
262
+ role="button"
263
+ [class.k-selected]="isSelected(index)"
264
+ [class.k-focus]="isSelected(index)"
265
+ [class.k-active]="isActive(index)"
266
+ [attr.tabindex]="0"
267
+ (click)="suggestionClick(suggestion, index)"
268
+ (keydown)="suggestionKeydown($event, suggestion)"
269
+ (mousedown)="toggleActiveState(true, index)"
270
+ (mouseup)="toggleActiveState(false, index)"
127
271
  >
128
- </ng-template>
272
+ {{ suggestion.text }}
273
+ </span>
274
+ </ng-container>
275
+
276
+ <ng-container *ngIf="suggestionTemplate?.templateRef">
277
+ <ng-container *ngFor="let suggestion of suggestions">
278
+ <ng-template
279
+ [ngTemplateOutlet]="suggestionTemplate.templateRef"
280
+ [ngTemplateOutletContext]="{ $implicit: suggestion }"
281
+ >
282
+ </ng-template>
283
+ </ng-container>
129
284
  </ng-container>
130
285
  </ng-container>
131
- </ng-container>
132
- `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
286
+ </ng-template>
287
+
288
+ <span
289
+ *ngIf="hasScrollButtons"
290
+ #nextScrollButton
291
+ kendoChatScrollableButton
292
+ [prev]="false"
293
+ [title]="getScrollButtonTitle('next')"
294
+ class="k-button k-button-md k-button-solid k-button-solid-base k-rounded-md k-icon-button"
295
+ (onClick)="scrollSuggestions($event)"
296
+ >
297
+ </span>
298
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ChatScrollableButtonComponent, selector: "[kendoChatScrollableButton]", inputs: ["prev"], outputs: ["onClick"] }] });
133
299
  }
134
300
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SuggestedActionsComponent, decorators: [{
135
301
  type: Component,
@@ -138,80 +304,132 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
138
304
  providers: [{
139
305
  provide: ChatItem,
140
306
  useExisting: forwardRef(() => SuggestedActionsComponent)
141
- }],
307
+ },
308
+ SuggestionsScrollService],
142
309
  template: `
143
- <ng-container *ngIf="actions">
144
- <span
145
- #item
146
- *ngFor="let action of actions; index as index; first as first; last as last"
147
- class="k-suggestion k-suggestion-primary"
148
- role="button"
149
- [class.k-selected]="isSelected(index)"
150
- [class.k-focus]="isSelected(index)"
151
- [class.k-active]="isActive(index)"
152
- [attr.tabindex]="0"
153
- (click)="actionClick(action, index)"
154
- (keydown)="actionKeydown($event, action)"
155
- (mousedown)="toggleActiveState(true, index)"
156
- (mouseup)="toggleActiveState(false, index)"
157
- >
158
- {{ action.title || action.value }}
159
- </span>
160
- </ng-container>
310
+ <span
311
+ *ngIf="hasScrollButtons"
312
+ #prevScrollButton
313
+ kendoChatScrollableButton
314
+ [prev]="true"
315
+ [title]="getScrollButtonTitle('prev')"
316
+ class="k-button k-button-md k-button-solid k-button-solid-base k-rounded-md k-icon-button"
317
+ (onClick)="scrollSuggestions($event)"
318
+ >
319
+ </span>
320
+ <div class="k-suggestion-group" *ngIf="hasScrollButtons; else noScrollButtons"
321
+ #suggestionsContainer
322
+ role="group"
323
+ (scroll)="onScroll($event)">
324
+ <ng-container *ngTemplateOutlet="suggestionsContent"></ng-container>
325
+ </div>
161
326
 
162
- <ng-container *ngIf="suggestions">
163
- <ng-container *ngIf="!suggestionTemplate?.templateRef">
327
+ <ng-template #noScrollButtons>
328
+ <ng-container *ngTemplateOutlet="suggestionsContent"></ng-container>
329
+ </ng-template>
330
+
331
+ <ng-template #suggestionsContent>
332
+ <ng-container *ngIf="actions">
164
333
  <span
165
334
  #item
166
- *ngFor="let suggestion of suggestions; index as index; first as first; last as last"
167
- class="k-suggestion"
335
+ *ngFor="let action of actions; index as index; first as first; last as last"
336
+ class="k-suggestion k-suggestion-primary"
168
337
  role="button"
169
338
  [class.k-selected]="isSelected(index)"
170
339
  [class.k-focus]="isSelected(index)"
171
340
  [class.k-active]="isActive(index)"
172
341
  [attr.tabindex]="0"
173
- (click)="suggestionClick(suggestion, index)"
174
- (keydown)="suggestionKeydown($event, suggestion)"
342
+ (click)="actionClick(action, index)"
343
+ (keydown)="actionKeydown($event, action)"
175
344
  (mousedown)="toggleActiveState(true, index)"
176
345
  (mouseup)="toggleActiveState(false, index)"
177
346
  >
178
- {{ suggestion.text }}
347
+ {{ action.title || action.value }}
179
348
  </span>
180
349
  </ng-container>
181
350
 
182
- <ng-container *ngIf="suggestionTemplate?.templateRef">
183
- <ng-container *ngFor="let suggestion of suggestions">
184
- <ng-template
185
- [ngTemplateOutlet]="suggestionTemplate.templateRef"
186
- [ngTemplateOutletContext]="{ $implicit: suggestion }"
351
+ <ng-container *ngIf="suggestions">
352
+ <ng-container *ngIf="!suggestionTemplate?.templateRef">
353
+ <span
354
+ #item
355
+ *ngFor="let suggestion of suggestions; index as index; first as first; last as last"
356
+ class="k-suggestion"
357
+ role="button"
358
+ [class.k-selected]="isSelected(index)"
359
+ [class.k-focus]="isSelected(index)"
360
+ [class.k-active]="isActive(index)"
361
+ [attr.tabindex]="0"
362
+ (click)="suggestionClick(suggestion, index)"
363
+ (keydown)="suggestionKeydown($event, suggestion)"
364
+ (mousedown)="toggleActiveState(true, index)"
365
+ (mouseup)="toggleActiveState(false, index)"
187
366
  >
188
- </ng-template>
367
+ {{ suggestion.text }}
368
+ </span>
369
+ </ng-container>
370
+
371
+ <ng-container *ngIf="suggestionTemplate?.templateRef">
372
+ <ng-container *ngFor="let suggestion of suggestions">
373
+ <ng-template
374
+ [ngTemplateOutlet]="suggestionTemplate.templateRef"
375
+ [ngTemplateOutletContext]="{ $implicit: suggestion }"
376
+ >
377
+ </ng-template>
378
+ </ng-container>
189
379
  </ng-container>
190
380
  </ng-container>
191
- </ng-container>
381
+ </ng-template>
382
+
383
+ <span
384
+ *ngIf="hasScrollButtons"
385
+ #nextScrollButton
386
+ kendoChatScrollableButton
387
+ [prev]="false"
388
+ [title]="getScrollButtonTitle('next')"
389
+ class="k-button k-button-md k-button-solid k-button-solid-base k-rounded-md k-icon-button"
390
+ (onClick)="scrollSuggestions($event)"
391
+ >
392
+ </span>
192
393
  `,
193
394
  standalone: true,
194
- imports: [NgFor, NgIf, NgTemplateOutlet]
395
+ imports: [NgFor, NgIf, NgTemplateOutlet, ChatScrollableButtonComponent]
195
396
  }]
196
- }], propDecorators: { actions: [{
397
+ }], ctorParameters: () => [{ type: i1.ChatService }, { type: i2.LocalizationService }, { type: i3.SuggestionsScrollService }, { type: i0.NgZone }, { type: i0.Renderer2 }], propDecorators: { defaultClass: [{
398
+ type: HostBinding,
399
+ args: ['class.k-suggestion-group']
400
+ }], scrollableClass: [{
401
+ type: HostBinding,
402
+ args: ['class.k-suggestion-group-scrollable']
403
+ }], scrollButtonsClass: [{
404
+ type: HostBinding,
405
+ args: ['class.k-suggestion-scrollwrap']
406
+ }], role: [{
407
+ type: HostBinding,
408
+ args: ['attr.role']
409
+ }], actions: [{
197
410
  type: Input
198
411
  }], suggestions: [{
199
412
  type: Input
200
413
  }], tabbable: [{
201
414
  type: Input
415
+ }], type: [{
416
+ type: Input
202
417
  }], suggestionTemplate: [{
203
418
  type: Input
204
419
  }], dispatchAction: [{
205
420
  type: Output
206
421
  }], dispatchSuggestion: [{
207
422
  type: Output
208
- }], defaultClass: [{
209
- type: HostBinding,
210
- args: ['class.k-suggestion-group']
211
- }], role: [{
212
- type: HostBinding,
213
- args: ['attr.role']
214
423
  }], items: [{
215
424
  type: ViewChildren,
216
425
  args: ['item']
426
+ }], suggestionsContainer: [{
427
+ type: ViewChild,
428
+ args: ['suggestionsContainer', { read: ElementRef, static: false }]
429
+ }], prevScrollButton: [{
430
+ type: ViewChild,
431
+ args: ['prevScrollButton', { read: ElementRef }]
432
+ }], nextScrollButton: [{
433
+ type: ViewChild,
434
+ args: ['nextScrollButton', { read: ElementRef }]
217
435
  }] } });
@@ -0,0 +1,39 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Directive, Optional, TemplateRef } from "@angular/core";
6
+ import * as i0 from "@angular/core";
7
+ /**
8
+ * Defines a template for displaying custom content inside the current user's messages in the Chat.
9
+ *
10
+ * To define a message template, nest an `<ng-template>` tag with the `kendoChatAuthorMessageContentTemplate` directive inside the `<kendo-chat>` component.
11
+ * The template context is set to the `message` instance.
12
+ * For more information, refer to the article on [message templates](slug:message_templates_chat).
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <kendo-chat>
17
+ * <ng-template kendoChatAuthorMessageContentTemplate let-message>
18
+ * <div>Message: {{ message.text }}</div>
19
+ * </ng-template>
20
+ * </kendo-chat>
21
+ * ```
22
+ */
23
+ export class AuthorMessageContentTemplateDirective {
24
+ templateRef;
25
+ constructor(templateRef) {
26
+ this.templateRef = templateRef;
27
+ }
28
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthorMessageContentTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
29
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: AuthorMessageContentTemplateDirective, isStandalone: true, selector: "[kendoChatAuthorMessageContentTemplate]", ngImport: i0 });
30
+ }
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthorMessageContentTemplateDirective, decorators: [{
32
+ type: Directive,
33
+ args: [{
34
+ selector: '[kendoChatAuthorMessageContentTemplate]',
35
+ standalone: true
36
+ }]
37
+ }], ctorParameters: () => [{ type: i0.TemplateRef, decorators: [{
38
+ type: Optional
39
+ }] }] });
@@ -0,0 +1,39 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Directive, Optional, TemplateRef } from "@angular/core";
6
+ import * as i0 from "@angular/core";
7
+ /**
8
+ * Defines a template for displaying fully custom Chat message bubbles for the current user.
9
+ *
10
+ * To define a message template, nest an `<ng-template>` tag with the `kendoChatAuthorMessageTemplate` directive inside the `<kendo-chat>` component.
11
+ * The template context is set to the `message` instance.
12
+ * For more information, refer to the article on [message templates](slug:message_templates_chat).
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <kendo-chat>
17
+ * <ng-template kendoChatAuthorMessageTemplate let-message>
18
+ * <div>Message: {{ message.text }}</div>
19
+ * </ng-template>
20
+ * </kendo-chat>
21
+ * ```
22
+ */
23
+ export class AuthorMessageTemplateDirective {
24
+ templateRef;
25
+ constructor(templateRef) {
26
+ this.templateRef = templateRef;
27
+ }
28
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthorMessageTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
29
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: AuthorMessageTemplateDirective, isStandalone: true, selector: "[kendoChatAuthorMessageTemplate]", ngImport: i0 });
30
+ }
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthorMessageTemplateDirective, decorators: [{
32
+ type: Directive,
33
+ args: [{
34
+ selector: '[kendoChatAuthorMessageTemplate]',
35
+ standalone: true
36
+ }]
37
+ }], ctorParameters: () => [{ type: i0.TemplateRef, decorators: [{
38
+ type: Optional
39
+ }] }] });
@@ -0,0 +1,39 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Directive, Optional, TemplateRef } from "@angular/core";
6
+ import * as i0 from "@angular/core";
7
+ /**
8
+ * Defines a template for displaying custom content inside the Chat messages.
9
+ *
10
+ * To define a message template, nest an `<ng-template>` tag with the `kendoChatMessageContentTemplate` directive inside the `<kendo-chat>` component.
11
+ * The template context is set to the `message` instance.
12
+ * For more information, refer to the article on [message templates](slug:message_templates_chat).
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <kendo-chat>
17
+ * <ng-template kendoChatMessageContentTemplate let-message>
18
+ * <div>Message: {{ message.text }}</div>
19
+ * </ng-template>
20
+ * </kendo-chat>
21
+ * ```
22
+ */
23
+ export class MessageContentTemplateDirective {
24
+ templateRef;
25
+ constructor(templateRef) {
26
+ this.templateRef = templateRef;
27
+ }
28
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageContentTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
29
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: MessageContentTemplateDirective, isStandalone: true, selector: "[kendoChatMessageContentTemplate]", ngImport: i0 });
30
+ }
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageContentTemplateDirective, decorators: [{
32
+ type: Directive,
33
+ args: [{
34
+ selector: '[kendoChatMessageContentTemplate]',
35
+ standalone: true
36
+ }]
37
+ }], ctorParameters: () => [{ type: i0.TemplateRef, decorators: [{
38
+ type: Optional
39
+ }] }] });
@@ -5,7 +5,7 @@
5
5
  import { Directive, Optional, TemplateRef } from "@angular/core";
6
6
  import * as i0 from "@angular/core";
7
7
  /**
8
- * Defines a template for displaying Chat messages.
8
+ * Defines a template for displaying fully custom Chat message bubbles.
9
9
  *
10
10
  * To define a message template, nest an `<ng-template>` tag with the `kendoChatMessageTemplate` directive inside the `<kendo-chat>` component.
11
11
  * The template context is set to the `message` instance.
@@ -0,0 +1,38 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Directive, Optional, TemplateRef } from "@angular/core";
6
+ import * as i0 from "@angular/core";
7
+ /**
8
+ * Defines a template for displaying custom content when there are no messages in the Chat.
9
+ *
10
+ * To define an empty Chat template, nest an `<ng-template>` tag with the `kendoChatNoDataTemplate` directive inside the `<kendo-chat>` component.
11
+ * For more information, refer to the article on [message templates](slug:message_templates_chat).
12
+ *
13
+ * @example
14
+ * ```html
15
+ * <kendo-chat>
16
+ * <ng-template kendoChatNoDataTemplate>
17
+ * <div>No messages.</div>
18
+ * </ng-template>
19
+ * </kendo-chat>
20
+ * ```
21
+ */
22
+ export class NoDataTemplateDirective {
23
+ templateRef;
24
+ constructor(templateRef) {
25
+ this.templateRef = templateRef;
26
+ }
27
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NoDataTemplateDirective, deps: [{ token: i0.TemplateRef, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
28
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: NoDataTemplateDirective, isStandalone: true, selector: "[kendoChatNoDataTemplate]", ngImport: i0 });
29
+ }
30
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NoDataTemplateDirective, decorators: [{
31
+ type: Directive,
32
+ args: [{
33
+ selector: '[kendoChatNoDataTemplate]',
34
+ standalone: true
35
+ }]
36
+ }], ctorParameters: () => [{ type: i0.TemplateRef, decorators: [{
37
+ type: Optional
38
+ }] }] });