@progress/kendo-angular-conversational-ui 21.0.0-develop.2 → 21.0.0-develop.21

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 (69) hide show
  1. package/chat/api/files-layout.d.ts +12 -0
  2. package/chat/api/index.d.ts +4 -1
  3. package/chat/api/message-settings.interface.d.ts +41 -0
  4. package/chat/api/message-width-mode.d.ts +1 -1
  5. package/chat/api/message.interface.d.ts +5 -1
  6. package/chat/api/suggestions-layout.d.ts +20 -0
  7. package/chat/api/timestamp-visibility.d.ts +10 -0
  8. package/chat/chat.component.d.ts +111 -34
  9. package/chat/chat.directives.d.ts +18 -0
  10. package/chat/chat.module.d.ts +15 -8
  11. package/chat/common/chat.service.d.ts +36 -3
  12. package/chat/common/models/model-fields.d.ts +0 -6
  13. package/chat/common/scroll-button.component.d.ts +32 -0
  14. package/chat/common/scroll.service.d.ts +39 -0
  15. package/chat/common/utils.d.ts +13 -1
  16. package/chat/l10n/messages.d.ts +9 -1
  17. package/chat/message-list.component.d.ts +22 -3
  18. package/chat/message.component.d.ts +40 -16
  19. package/chat/suggested-actions.component.d.ts +30 -5
  20. package/chat/templates/author-message-content-template.directive.d.ts +28 -0
  21. package/chat/templates/author-message-template.directive.d.ts +28 -0
  22. package/chat/templates/message-content-template.directive.d.ts +28 -0
  23. package/chat/templates/message-template.directive.d.ts +1 -1
  24. package/chat/templates/no-data-template.directive.d.ts +27 -0
  25. package/chat/templates/receiver-message-content-template.directive.d.ts +28 -0
  26. package/chat/templates/receiver-message-template.directive.d.ts +28 -0
  27. package/chat/templates/user-status-template.directive.d.ts +27 -0
  28. package/codemods/utils.js +477 -375
  29. package/codemods/v20/chat-user.js +7 -5
  30. package/codemods/v21/chat-messagetoolbarvisibility.js +53 -0
  31. package/codemods/v21/chat-pinnedbyfield.js +19 -0
  32. package/conversational-ui.module.d.ts +18 -11
  33. package/directives.d.ts +9 -2
  34. package/esm2022/chat/api/index.mjs +4 -1
  35. package/{chat/api/message-toolbar-visibility.d.ts → esm2022/chat/api/message-settings.interface.mjs} +1 -4
  36. package/esm2022/chat/api/suggestions-layout.mjs +5 -0
  37. package/esm2022/chat/api/timestamp-visibility.mjs +5 -0
  38. package/esm2022/chat/builtin-actions.mjs +2 -0
  39. package/esm2022/chat/chat-file.component.mjs +2 -2
  40. package/esm2022/chat/chat.component.mjs +295 -71
  41. package/esm2022/chat/chat.directives.mjs +18 -0
  42. package/esm2022/chat/chat.module.mjs +16 -9
  43. package/esm2022/chat/common/chat.service.mjs +86 -4
  44. package/esm2022/chat/common/models/default-model-fields.mjs +0 -1
  45. package/esm2022/chat/common/scroll-button.component.mjs +81 -0
  46. package/esm2022/chat/common/scroll.service.mjs +110 -0
  47. package/esm2022/chat/common/utils.mjs +22 -3
  48. package/esm2022/chat/l10n/messages.mjs +13 -1
  49. package/esm2022/chat/message-attachments.component.mjs +2 -2
  50. package/esm2022/chat/message-box.component.mjs +5 -2
  51. package/esm2022/chat/message-list.component.mjs +184 -40
  52. package/esm2022/chat/message.component.mjs +487 -326
  53. package/esm2022/chat/suggested-actions.component.mjs +298 -80
  54. package/esm2022/chat/templates/author-message-content-template.directive.mjs +39 -0
  55. package/esm2022/chat/templates/author-message-template.directive.mjs +39 -0
  56. package/esm2022/chat/templates/message-content-template.directive.mjs +39 -0
  57. package/esm2022/chat/templates/message-template.directive.mjs +1 -1
  58. package/esm2022/chat/templates/no-data-template.directive.mjs +38 -0
  59. package/esm2022/chat/templates/receiver-message-content-template.directive.mjs +39 -0
  60. package/esm2022/chat/templates/receiver-message-template.directive.mjs +39 -0
  61. package/esm2022/chat/templates/user-status-template.directive.mjs +38 -0
  62. package/esm2022/conversational-ui.module.mjs +19 -12
  63. package/esm2022/directives.mjs +15 -1
  64. package/esm2022/index.mjs +7 -0
  65. package/esm2022/package-metadata.mjs +2 -2
  66. package/fesm2022/progress-kendo-angular-conversational-ui.mjs +1822 -567
  67. package/index.d.ts +7 -0
  68. package/package.json +26 -14
  69. /package/esm2022/chat/api/{message-toolbar-visibility.mjs → files-layout.mjs} +0 -0
@@ -7,14 +7,14 @@
7
7
  import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, Input, Output, QueryList, Renderer2, ViewChildren } from '@angular/core';
8
8
  import { NgFor, NgSwitch, NgSwitchCase, NgIf, NgTemplateOutlet } from '@angular/common';
9
9
  import { ExecuteActionEvent } from './api';
10
- import { Keys, normalizeNumpadKeys, ResizeSensorComponent } from '@progress/kendo-angular-common';
10
+ import { isPresent, Keys, normalizeNumpadKeys, ResizeSensorComponent } from '@progress/kendo-angular-common';
11
11
  import { IntlService } from '@progress/kendo-angular-intl';
12
12
  import { LocalizationService } from '@progress/kendo-angular-l10n';
13
13
  import { closest, DOWNLOAD_ALL_SELECTOR, FILE_ACTION_BTN_SELECTOR } from './common/utils';
14
14
  import { ChatItem } from './chat-item';
15
15
  import { chatView, isAuthor } from './chat-view';
16
16
  import { AttachmentTemplateDirective } from './templates/attachment-template.directive';
17
- import { MessageTemplateDirective } from './templates/message-template.directive';
17
+ import { MessageContentTemplateDirective } from './templates/message-content-template.directive';
18
18
  import { ChatTimestampTemplateDirective } from './templates/timestamp-template.directive';
19
19
  import { Subscription } from 'rxjs';
20
20
  import { SuggestedActionsComponent } from './suggested-actions.component';
@@ -23,6 +23,12 @@ import { MessageAttachmentsComponent } from './message-attachments.component';
23
23
  import { AttachmentComponent } from './attachment.component';
24
24
  import { ChatService } from './common/chat.service';
25
25
  import { ChatStatusTemplateDirective } from './templates/status-template.directive';
26
+ import { ChatUserStatusTemplateDirective } from './templates/user-status-template.directive';
27
+ import { MessageTemplateDirective } from './templates/message-template.directive';
28
+ import { AuthorMessageContentTemplateDirective } from './templates/author-message-content-template.directive';
29
+ import { ReceiverMessageContentTemplateDirective } from './templates/receiver-message-content-template.directive';
30
+ import { AuthorMessageTemplateDirective } from './templates/author-message-template.directive';
31
+ import { ReceiverMessageTemplateDirective } from './templates/receiver-message-template.directive';
26
32
  import * as i0 from "@angular/core";
27
33
  import * as i1 from "@progress/kendo-angular-intl";
28
34
  import * as i2 from "./common/chat.service";
@@ -44,9 +50,15 @@ export class MessageListComponent {
44
50
  return this._messages;
45
51
  }
46
52
  attachmentTemplate;
53
+ authorMessageContentTemplate;
54
+ receiverMessageContentTemplate;
55
+ messageContentTemplate;
56
+ authorMessageTemplate;
57
+ receiverMessageTemplate;
47
58
  messageTemplate;
48
59
  timestampTemplate;
49
60
  statusTemplate;
61
+ userStatusTemplate;
50
62
  localization;
51
63
  authorId;
52
64
  executeAction = new EventEmitter();
@@ -64,6 +76,7 @@ export class MessageListComponent {
64
76
  [Keys.ArrowUp]: (e) => this.navigateTo(e, -1),
65
77
  [Keys.ArrowDown]: (e) => this.navigateTo(e, 1),
66
78
  [Keys.Tab]: (e) => this.onTabKeyDown(e),
79
+ [Keys.F10]: (e) => e.shiftKey && this.openContextMenu(e),
67
80
  };
68
81
  constructor(element, intl, renderer, chatService, cdr) {
69
82
  this.element = element;
@@ -76,9 +89,25 @@ export class MessageListComponent {
76
89
  const elRef = this.element.nativeElement;
77
90
  this.subs.add(this.renderer.listen(elRef, 'keydown', event => this.onKeydown(event)));
78
91
  this.subs.add(this.renderer.listen(elRef, 'focusout', event => this.onBlur(event)));
92
+ this.subs.add(this.renderer.listen(elRef, 'click', event => {
93
+ const messageComponent = this.findMessageComponentFromEvent(event);
94
+ if (messageComponent) {
95
+ this.select(messageComponent, event);
96
+ }
97
+ }));
98
+ this.subs.add(this.renderer.listen(elRef, 'contextmenu', event => {
99
+ event.preventDefault();
100
+ const messageComponent = this.findMessageComponentFromEvent(event);
101
+ if (messageComponent) {
102
+ this.onContextMenuClick(messageComponent.message, event, messageComponent);
103
+ }
104
+ }));
79
105
  this.subs.add(this.chatService.replyReferenceClick$.subscribe((messageId) => {
80
106
  this.scrollToAndSelectMessage(messageId);
81
107
  }));
108
+ this.subs.add(this.chatService.contextMenuVisibilityChange$.subscribe((isVisible) => {
109
+ this.handleMenuClose(isVisible);
110
+ }));
82
111
  }
83
112
  ngAfterViewInit() {
84
113
  this.selectedItem = this.items.last;
@@ -92,9 +121,45 @@ export class MessageListComponent {
92
121
  onClick(message, event) {
93
122
  this.select(message, event);
94
123
  }
124
+ showGroupAuthor(group) {
125
+ const messageSettings = this.isOwnMessage(group.messages[0]) ? this.chatService.authorMessageSettings : this.chatService.receiverMessageSettings;
126
+ if (isPresent(messageSettings?.showUsername)) {
127
+ return messageSettings.showUsername && group.author.name;
128
+ }
129
+ return this.chatService.showUsername && group.author.name;
130
+ }
131
+ showGroupAvatar(group) {
132
+ const messageSettings = this.isOwnMessage(group.messages[0]) ? this.chatService.authorMessageSettings : this.chatService.receiverMessageSettings;
133
+ if (isPresent(messageSettings?.showAvatar)) {
134
+ return messageSettings.showAvatar && group.author.avatarUrl;
135
+ }
136
+ return this.chatService.showAvatar && group.author.avatarUrl;
137
+ }
138
+ onContextMenuClick(message, event, messageElement) {
139
+ this.chatService.calculateContextMenuActions(this.isOwnMessage(message));
140
+ if (this.chatService.calculatedContextMenuActions.length > 0) {
141
+ this.chatService.messagesContextMenu.show({
142
+ left: event.pageX,
143
+ top: event.pageY,
144
+ });
145
+ this.chatService.activeMessageElement = messageElement;
146
+ this.chatService.activeMessage = message;
147
+ this.chatService.active = true;
148
+ this.chatService.selectOnMenuClose = this.chatService.activeMessageElement?.selected;
149
+ this.chatService.emit('contextMenuVisibilityChange', true);
150
+ }
151
+ }
95
152
  formatTimeStamp(date) {
96
153
  return this.intl.formatDate(date, { date: 'full' });
97
154
  }
155
+ calculateMessageWidthMode(message) {
156
+ const isOwn = this.isOwnMessage(message);
157
+ const messageSettings = isOwn ? this.chatService.authorMessageSettings : this.chatService.receiverMessageSettings;
158
+ if (messageSettings?.messageWidthMode) {
159
+ return messageSettings.messageWidthMode === 'full';
160
+ }
161
+ return this.chatService.messageWidthMode === 'full';
162
+ }
98
163
  onKeydown(e) {
99
164
  // On some keyboards Numpad keys are used for Home/End/PageUp/PageDown.
100
165
  const code = normalizeNumpadKeys(e);
@@ -154,6 +219,9 @@ export class MessageListComponent {
154
219
  this.select(null);
155
220
  }
156
221
  }
222
+ textFor(key) {
223
+ return this.localization.get(key);
224
+ }
157
225
  onHomeOrEndKeyDown(key) {
158
226
  const items = this.items.toArray();
159
227
  if (key === 'home') {
@@ -200,11 +268,49 @@ export class MessageListComponent {
200
268
  this.select(chatItem);
201
269
  }
202
270
  }
203
- textFor(key) {
204
- return this.localization.get(key);
271
+ openContextMenu(event) {
272
+ event.preventDefault();
273
+ const messageComponent = this.findMessageComponentFromActiveElement();
274
+ if (messageComponent) {
275
+ const messageContentElement = messageComponent.element.nativeElement.querySelector('.k-chat-bubble');
276
+ if (messageContentElement) {
277
+ const rect = messageContentElement?.getBoundingClientRect();
278
+ this.onContextMenuClick(messageComponent.message, {
279
+ pageX: rect.left + (rect.width / 2) + window.scrollX,
280
+ pageY: rect.top + (rect.height / 2) + window.scrollY
281
+ }, messageComponent);
282
+ }
283
+ else {
284
+ const messageElement = messageComponent.element.nativeElement;
285
+ const rect = messageElement?.getBoundingClientRect();
286
+ this.onContextMenuClick(messageComponent.message, {
287
+ pageX: rect.left + (rect.width / 2) + window.scrollX,
288
+ pageY: rect.top + (rect.height / 2) + window.scrollY
289
+ }, messageComponent);
290
+ }
291
+ }
292
+ }
293
+ findMessageComponentFromActiveElement() {
294
+ const activeElement = document.activeElement;
295
+ const messageComponents = this.items.filter(item => item instanceof MessageComponent);
296
+ return messageComponents.find(component => {
297
+ const componentElement = component.element?.nativeElement;
298
+ return componentElement && (componentElement === activeElement || componentElement.contains(activeElement));
299
+ });
300
+ }
301
+ findMessageComponentFromEvent(event) {
302
+ const target = event.target;
303
+ const clickedElement = target?.closest('.k-message');
304
+ if (!clickedElement)
305
+ return undefined;
306
+ const messageComponents = this.items.filter(item => item instanceof MessageComponent);
307
+ return messageComponents.find(component => {
308
+ const componentElement = component.element?.nativeElement;
309
+ return componentElement && (componentElement === clickedElement || componentElement.contains(clickedElement));
310
+ });
205
311
  }
206
312
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageListComponent, deps: [{ token: i0.ElementRef }, { token: i1.IntlService }, { token: i0.Renderer2 }, { token: i2.ChatService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
207
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: MessageListComponent, isStandalone: true, selector: "kendo-chat-message-list", inputs: { messages: "messages", attachmentTemplate: "attachmentTemplate", messageTemplate: "messageTemplate", timestampTemplate: "timestampTemplate", statusTemplate: "statusTemplate", localization: "localization", authorId: "authorId" }, outputs: { executeAction: "executeAction", navigate: "navigate", resize: "resize" }, host: { properties: { "class.k-message-list-content": "this.cssClass" } }, viewQueries: [{ propertyName: "items", predicate: ChatItem, descendants: true }], ngImport: i0, template: `
313
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: MessageListComponent, isStandalone: true, selector: "kendo-chat-message-list", inputs: { messages: "messages", attachmentTemplate: "attachmentTemplate", authorMessageContentTemplate: "authorMessageContentTemplate", receiverMessageContentTemplate: "receiverMessageContentTemplate", messageContentTemplate: "messageContentTemplate", authorMessageTemplate: "authorMessageTemplate", receiverMessageTemplate: "receiverMessageTemplate", messageTemplate: "messageTemplate", timestampTemplate: "timestampTemplate", statusTemplate: "statusTemplate", userStatusTemplate: "userStatusTemplate", localization: "localization", authorId: "authorId" }, outputs: { executeAction: "executeAction", navigate: "navigate", resize: "resize" }, host: { properties: { "class.k-message-list-content": "this.cssClass" } }, viewQueries: [{ propertyName: "items", predicate: ChatItem, descendants: true }], ngImport: i0, template: `
208
314
  <ng-container *ngFor="let group of view; last as lastGroup; trackBy: trackGroup">
209
315
  <ng-container [ngSwitch]="group.type">
210
316
  <div
@@ -224,11 +330,11 @@ export class MessageListComponent {
224
330
  class="k-message-group"
225
331
  [class.k-message-group-sender]="isOwnMessage(group.messages[0])"
226
332
  [class.k-message-group-receiver]="!isOwnMessage(group.messages[0])"
227
- [class.k-no-avatar]="!group.author.avatarUrl"
228
- [class.k-message-group-full-width]="chatService.messageWidthMode === 'full'"
333
+ [class.k-no-avatar]="!showGroupAvatar(group)"
334
+ [class.k-message-group-full-width]="calculateMessageWidthMode(group.messages[0])"
229
335
  >
230
336
  <div
231
- *ngIf="group.author.avatarUrl"
337
+ *ngIf="!userStatusTemplate?.templateRef && showGroupAvatar(group)"
232
338
  class="k-avatar k-avatar-md k-avatar-solid k-avatar-solid-primary k-rounded-full"
233
339
  >
234
340
  <span class="k-avatar-image">
@@ -238,29 +344,41 @@ export class MessageListComponent {
238
344
  />
239
345
  </span>
240
346
  </div>
347
+ <div class="k-chat-user-status-wrapper" *ngIf="userStatusTemplate?.templateRef && showGroupAvatar(group)">
348
+ <div
349
+ class="k-avatar k-avatar-md k-avatar-solid k-avatar-solid-primary k-rounded-full"
350
+ >
351
+ <span class="k-avatar-image">
352
+ <img
353
+ [attr.src]="group.author.avatarUrl"
354
+ [alt]="group.author.avatarAltText"
355
+ />
356
+ </span>
357
+ </div>
358
+ <div class="k-chat-user-status" *ngIf="userStatusTemplate?.templateRef">
359
+ <ng-template
360
+ [ngTemplateOutlet]="userStatusTemplate.templateRef"
361
+ [ngTemplateOutletContext]="{ $implicit: group.messages.at(-1) }"
362
+ >
363
+ </ng-template>
364
+ </div>
365
+ </div>
241
366
  <div class="k-message-group-content">
242
- <p *ngIf="group.author.name" class="k-message-author">{{ group.author.name }}</p>
367
+ <p *ngIf="showGroupAuthor(group)" class="k-message-author">{{ group.author.name }}</p>
243
368
  <ng-container
244
369
  *ngFor="let msg of group.messages; first as firstMessage; last as lastMessage"
245
370
  >
246
- <div
247
- *ngIf="msg.user?.avatarUrl"
248
- class="k-avatar k-avatar-md k-avatar-solid k-avatar-solid-primary k-rounded-full"
249
- >
250
- <span class="k-avatar-image">
251
- <img [src]="msg.user?.avatarUrl">
252
- </span>
253
- </div>
254
371
  <kendo-chat-message #message
255
372
  [message]="msg"
256
373
  [tabbable]="lastGroup && lastMessage"
257
- [template]="messageTemplate"
374
+ [authorMessageContentTemplate]="authorMessageContentTemplate"
375
+ [receiverMessageContentTemplate]="receiverMessageContentTemplate"
376
+ [messageContentTemplate]="messageContentTemplate"
377
+ [authorMessageTemplate]="authorMessageTemplate"
378
+ [receiverMessageTemplate]="receiverMessageTemplate"
379
+ [messageTemplate]="messageTemplate"
258
380
  [statusTemplate]="statusTemplate"
259
381
  [authorId]="authorId"
260
- (click)="onClick(message, $event)"
261
- (contextMenuVisibilityChange)="handleMenuClose($event)"
262
- [class.k-first]="group.messages.length > 1 && firstMessage"
263
- [class.k-last]="group.messages.length > 1 && lastMessage"
264
382
  >
265
383
  </kendo-chat-message>
266
384
 
@@ -289,6 +407,7 @@ export class MessageListComponent {
289
407
  <kendo-chat-suggested-actions #actions
290
408
  *ngSwitchCase="'action-group'"
291
409
  [actions]="group.actions"
410
+ type="action"
292
411
  [tabbable]="lastGroup"
293
412
  (dispatchAction)="dispatchAction($event, last(view))"
294
413
  (click)="select(actions, $event)"
@@ -299,7 +418,7 @@ export class MessageListComponent {
299
418
  </ng-container>
300
419
  <kendo-resize-sensor (resize)="onResize()">
301
420
  </kendo-resize-sensor>
302
- `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MessageComponent, selector: "kendo-chat-message", inputs: ["message", "tabbable", "template", "statusTemplate", "showMessageTime", "authorId"], outputs: ["contextMenuVisibilityChange"] }, { kind: "component", type: AttachmentComponent, selector: "kendo-chat-attachment", inputs: ["attachment", "template"] }, { kind: "component", type: MessageAttachmentsComponent, selector: "kendo-chat-message-attachments", inputs: ["attachments", "layout", "tabbable", "template", "localization"] }, { kind: "component", type: SuggestedActionsComponent, selector: "kendo-chat-suggested-actions", inputs: ["actions", "suggestions", "tabbable", "suggestionTemplate"], outputs: ["dispatchAction", "dispatchSuggestion"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }] });
421
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MessageComponent, selector: "kendo-chat-message", inputs: ["message", "tabbable", "authorMessageContentTemplate", "receiverMessageContentTemplate", "messageContentTemplate", "authorMessageTemplate", "receiverMessageTemplate", "messageTemplate", "statusTemplate", "showMessageTime", "authorId"] }, { kind: "component", type: AttachmentComponent, selector: "kendo-chat-attachment", inputs: ["attachment", "template"] }, { kind: "component", type: MessageAttachmentsComponent, selector: "kendo-chat-message-attachments", inputs: ["attachments", "layout", "tabbable", "template", "localization"] }, { kind: "component", type: SuggestedActionsComponent, selector: "kendo-chat-suggested-actions", inputs: ["actions", "suggestions", "tabbable", "type", "suggestionTemplate"], outputs: ["dispatchAction", "dispatchSuggestion"] }, { kind: "component", type: ResizeSensorComponent, selector: "kendo-resize-sensor", inputs: ["rateLimit"], outputs: ["resize"] }] });
303
422
  }
304
423
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageListComponent, decorators: [{
305
424
  type: Component,
@@ -325,11 +444,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
325
444
  class="k-message-group"
326
445
  [class.k-message-group-sender]="isOwnMessage(group.messages[0])"
327
446
  [class.k-message-group-receiver]="!isOwnMessage(group.messages[0])"
328
- [class.k-no-avatar]="!group.author.avatarUrl"
329
- [class.k-message-group-full-width]="chatService.messageWidthMode === 'full'"
447
+ [class.k-no-avatar]="!showGroupAvatar(group)"
448
+ [class.k-message-group-full-width]="calculateMessageWidthMode(group.messages[0])"
330
449
  >
331
450
  <div
332
- *ngIf="group.author.avatarUrl"
451
+ *ngIf="!userStatusTemplate?.templateRef && showGroupAvatar(group)"
333
452
  class="k-avatar k-avatar-md k-avatar-solid k-avatar-solid-primary k-rounded-full"
334
453
  >
335
454
  <span class="k-avatar-image">
@@ -339,29 +458,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
339
458
  />
340
459
  </span>
341
460
  </div>
461
+ <div class="k-chat-user-status-wrapper" *ngIf="userStatusTemplate?.templateRef && showGroupAvatar(group)">
462
+ <div
463
+ class="k-avatar k-avatar-md k-avatar-solid k-avatar-solid-primary k-rounded-full"
464
+ >
465
+ <span class="k-avatar-image">
466
+ <img
467
+ [attr.src]="group.author.avatarUrl"
468
+ [alt]="group.author.avatarAltText"
469
+ />
470
+ </span>
471
+ </div>
472
+ <div class="k-chat-user-status" *ngIf="userStatusTemplate?.templateRef">
473
+ <ng-template
474
+ [ngTemplateOutlet]="userStatusTemplate.templateRef"
475
+ [ngTemplateOutletContext]="{ $implicit: group.messages.at(-1) }"
476
+ >
477
+ </ng-template>
478
+ </div>
479
+ </div>
342
480
  <div class="k-message-group-content">
343
- <p *ngIf="group.author.name" class="k-message-author">{{ group.author.name }}</p>
481
+ <p *ngIf="showGroupAuthor(group)" class="k-message-author">{{ group.author.name }}</p>
344
482
  <ng-container
345
483
  *ngFor="let msg of group.messages; first as firstMessage; last as lastMessage"
346
484
  >
347
- <div
348
- *ngIf="msg.user?.avatarUrl"
349
- class="k-avatar k-avatar-md k-avatar-solid k-avatar-solid-primary k-rounded-full"
350
- >
351
- <span class="k-avatar-image">
352
- <img [src]="msg.user?.avatarUrl">
353
- </span>
354
- </div>
355
485
  <kendo-chat-message #message
356
486
  [message]="msg"
357
487
  [tabbable]="lastGroup && lastMessage"
358
- [template]="messageTemplate"
488
+ [authorMessageContentTemplate]="authorMessageContentTemplate"
489
+ [receiverMessageContentTemplate]="receiverMessageContentTemplate"
490
+ [messageContentTemplate]="messageContentTemplate"
491
+ [authorMessageTemplate]="authorMessageTemplate"
492
+ [receiverMessageTemplate]="receiverMessageTemplate"
493
+ [messageTemplate]="messageTemplate"
359
494
  [statusTemplate]="statusTemplate"
360
495
  [authorId]="authorId"
361
- (click)="onClick(message, $event)"
362
- (contextMenuVisibilityChange)="handleMenuClose($event)"
363
- [class.k-first]="group.messages.length > 1 && firstMessage"
364
- [class.k-last]="group.messages.length > 1 && lastMessage"
365
496
  >
366
497
  </kendo-chat-message>
367
498
 
@@ -390,6 +521,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
390
521
  <kendo-chat-suggested-actions #actions
391
522
  *ngSwitchCase="'action-group'"
392
523
  [actions]="group.actions"
524
+ type="action"
393
525
  [tabbable]="lastGroup"
394
526
  (dispatchAction)="dispatchAction($event, last(view))"
395
527
  (click)="select(actions, $event)"
@@ -408,12 +540,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
408
540
  type: Input
409
541
  }], attachmentTemplate: [{
410
542
  type: Input
543
+ }], authorMessageContentTemplate: [{
544
+ type: Input
545
+ }], receiverMessageContentTemplate: [{
546
+ type: Input
547
+ }], messageContentTemplate: [{
548
+ type: Input
549
+ }], authorMessageTemplate: [{
550
+ type: Input
551
+ }], receiverMessageTemplate: [{
552
+ type: Input
411
553
  }], messageTemplate: [{
412
554
  type: Input
413
555
  }], timestampTemplate: [{
414
556
  type: Input
415
557
  }], statusTemplate: [{
416
558
  type: Input
559
+ }], userStatusTemplate: [{
560
+ type: Input
417
561
  }], localization: [{
418
562
  type: Input
419
563
  }], authorId: [{