@progress/kendo-angular-conversational-ui 21.1.1-develop.2 → 21.2.0-develop.2

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.
@@ -7,7 +7,7 @@ import { ChatItem } from './chat-item';
7
7
  import { MessageContentTemplateDirective } from './templates/message-content-template.directive';
8
8
  import { IntlService } from '@progress/kendo-angular-intl';
9
9
  import { KENDO_BUTTONS } from '@progress/kendo-angular-buttons';
10
- import { NgClass, NgFor, NgIf, NgTemplateOutlet } from '@angular/common';
10
+ import { NgClass, NgTemplateOutlet } from '@angular/common';
11
11
  import { IconWrapperComponent } from '@progress/kendo-angular-icons';
12
12
  import { ToolBarButtonComponent, ToolBarComponent } from '@progress/kendo-angular-toolbar';
13
13
  import { chevronDownIcon, chevronUpIcon, downloadIcon } from '@progress/kendo-svg-icons';
@@ -330,178 +330,192 @@ export class MessageComponent extends ChatItem {
330
330
  return transformActions(actions);
331
331
  }
332
332
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageComponent, deps: [{ token: i0.ElementRef }, { token: i1.IntlService }, { token: i2.ChatService }, { token: i3.LocalizationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
333
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: MessageComponent, isStandalone: true, selector: "kendo-chat-message", inputs: { message: "message", tabbable: "tabbable", authorMessageContentTemplate: "authorMessageContentTemplate", receiverMessageContentTemplate: "receiverMessageContentTemplate", messageContentTemplate: "messageContentTemplate", authorMessageTemplate: "authorMessageTemplate", receiverMessageTemplate: "receiverMessageTemplate", messageTemplate: "messageTemplate", statusTemplate: "statusTemplate", showMessageTime: "showMessageTime", authorId: "authorId" }, host: { listeners: { "keydown": "onKeyDown($event)" }, properties: { "class.k-message": "this.cssClass", "class.k-message-removed": "this.removedClass", "attr.tabIndex": "this.tabIndex" } }, providers: [
333
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: MessageComponent, isStandalone: true, selector: "kendo-chat-message", inputs: { message: "message", tabbable: "tabbable", authorMessageContentTemplate: "authorMessageContentTemplate", receiverMessageContentTemplate: "receiverMessageContentTemplate", messageContentTemplate: "messageContentTemplate", authorMessageTemplate: "authorMessageTemplate", receiverMessageTemplate: "receiverMessageTemplate", messageTemplate: "messageTemplate", statusTemplate: "statusTemplate", showMessageTime: "showMessageTime", authorId: "authorId" }, host: { listeners: { "keydown": "onKeyDown($event)" }, properties: { "class.k-message": "this.cssClass", "class.k-message-removed": "this.removedClass", "attr.tabIndex": "this.tabIndex" } }, providers: [
334
334
  {
335
335
  provide: ChatItem,
336
336
  useExisting: forwardRef(() => MessageComponent)
337
337
  }
338
338
  ], usesInheritance: true, ngImport: i0, template: `
339
- <ng-container *ngIf="useCustomBubbleTemplate">
340
- <ng-container *ngTemplateOutlet="getActiveBubbleTemplate()?.templateRef; context: { $implicit: message };"></ng-container>
341
- </ng-container>
339
+ @if (useCustomBubbleTemplate) {
340
+ <ng-container *ngTemplateOutlet="getActiveBubbleTemplate()?.templateRef; context: { $implicit: message };"></ng-container>
341
+ }
342
342
 
343
- <ng-container *ngIf="!useCustomBubbleTemplate">
343
+ @if (!useCustomBubbleTemplate) {
344
+ @if (chatService.timestampVisibility === 'focus' && message.timestamp) {
344
345
  <time
345
- [attr.aria-hidden]="!selected"
346
- class="k-message-time"
347
- *ngIf="chatService.timestampVisibility === 'focus' && message.timestamp"
348
- >
349
- {{ formatTimeStamp(message.timestamp) }}
346
+ [attr.aria-hidden]="!selected"
347
+ class="k-message-time"
348
+ >
349
+ {{ formatTimeStamp(message.timestamp) }}
350
350
  </time>
351
-
352
- <ng-container *ngIf="message.typing">
353
- <div class="k-chat-bubble k-bubble">
354
- <div class="k-typing-indicator" [attr.tabindex]="'-1'">
355
- <span></span>
356
- <span></span>
357
- <span></span>
358
- </div>
359
- </div>
360
- </ng-container>
361
-
362
- <ng-container *ngIf="!message.typing">
363
- <div
364
- class="k-chat-bubble k-bubble"
365
- *ngIf="useCustomContentTemplate"
366
- [attr.tabindex]="0"
351
+ }
352
+ @if (message.typing) {
353
+ <div class="k-chat-bubble k-bubble">
354
+ <div class="k-typing-indicator" [attr.tabindex]="'-1'">
355
+ <span></span>
356
+ <span></span>
357
+ <span></span>
358
+ </div>
359
+ </div>
360
+ }
361
+ @if (!message.typing) {
362
+ @if (useCustomContentTemplate) {
363
+ <div
364
+ class="k-chat-bubble k-bubble"
365
+ [attr.tabindex]="0"
367
366
  [ngClass]="{
368
- 'k-bubble-expandable': isMessageExpandable,
367
+ 'k-bubble-expandable': isMessageExpandable,
369
368
  'k-expanded': isMessageExpanded,
370
- 'k-selected': selected,
369
+ 'k-selected': selected,
371
370
  'k-focus': selected,
372
371
  'k-active': isActiveMessage
373
372
  }"
374
373
  >
375
- <div class="k-bubble-content">
376
- <ng-container *ngTemplateOutlet="getActiveContentTemplate()?.templateRef; context: { $implicit: message };"></ng-container>
377
- </div>
378
- <span
379
- class="k-bubble-expandable-indicator"
380
- *ngIf="isMessageExpandable && showExpandCollapseIcon"
381
- [attr.tabindex]="'0'"
382
- [attr.role]="'button'"
383
- [attr.title]="isMessageExpanded ? textFor('collapseTitle') : textFor('expandTitle')"
384
- (mousedown)="chatService.toggleMessageState = true"
385
- (click)="toggleMessageState($event)"
386
- >
387
- <kendo-icon-wrapper
388
- [name]="isMessageExpanded ? 'chevron-up' : 'chevron-down'"
389
- [svgIcon]="isMessageExpanded ? collapseIcon : expandIcon"
390
- >
391
- </kendo-icon-wrapper>
392
- </span>
374
+ <div class="k-bubble-content">
375
+ <ng-container *ngTemplateOutlet="getActiveContentTemplate()?.templateRef; context: { $implicit: message };"></ng-container>
393
376
  </div>
394
-
395
- <div
396
- class="k-chat-bubble k-bubble"
397
- *ngIf="!useCustomContentTemplate && hasMessageContent"
398
- [attr.tabindex]="0"
377
+ @if (isMessageExpandable && showExpandCollapseIcon) {
378
+ <span
379
+ class="k-bubble-expandable-indicator"
380
+ [attr.tabindex]="'0'"
381
+ [attr.role]="'button'"
382
+ [attr.title]="isMessageExpanded ? textFor('collapseTitle') : textFor('expandTitle')"
383
+ (mousedown)="chatService.toggleMessageState = true"
384
+ (click)="toggleMessageState($event)"
385
+ >
386
+ <kendo-icon-wrapper
387
+ [name]="isMessageExpanded ? 'chevron-up' : 'chevron-down'"
388
+ [svgIcon]="isMessageExpanded ? collapseIcon : expandIcon"
389
+ >
390
+ </kendo-icon-wrapper>
391
+ </span>
392
+ }
393
+ </div>
394
+ }
395
+ @if (!useCustomContentTemplate && hasMessageContent) {
396
+ <div
397
+ class="k-chat-bubble k-bubble"
398
+ [attr.tabindex]="0"
399
399
  [ngClass]="{
400
- 'k-bubble-expandable': isMessageExpandable,
401
- 'k-expanded': isMessageExpanded,
402
- 'k-selected': selected,
400
+ 'k-bubble-expandable': isMessageExpandable,
401
+ 'k-expanded': isMessageExpanded,
402
+ 'k-selected': selected,
403
403
  'k-focus': selected,
404
404
  'k-active': isActiveMessage
405
405
  }"
406
406
  >
407
- <div class="k-bubble-content">
408
- <ng-container *ngIf="message.text || message.isDeleted">
409
- <div
410
- class="k-message-reference k-message-reference-receiver"
411
- *ngIf="message.replyToId && !message.isDeleted"
412
- (click)="onReplyReferenceClick($event, message.replyToId)"
413
- >
414
- <chat-message-reference-content [message]="getMessageById(message.replyToId)"></chat-message-reference-content>
415
- </div>
416
-
417
- <span class="k-chat-bubble-text" *ngIf="message.isDeleted">
418
- {{ getDeletedMessageText() }}
419
- </span>
420
-
421
- <span class="k-chat-bubble-text" *ngIf="!message.isDeleted && parts.length > 0">
422
- <ng-container *ngFor="let part of parts">
423
- <ng-container *ngIf="part.type === 'text'">{{part.content}}</ng-container>
424
- <a *ngIf="part.type === 'link'" [href]="part.href" target="_blank">{{part.content}}</a>
425
- </ng-container>
426
- </span>
427
- </ng-container>
428
-
429
- <ul
430
- class="k-chat-file-wrapper"
431
- *ngIf="hasFiles && !message.isDeleted"
407
+ <div class="k-bubble-content">
408
+ @if (message.text || message.isDeleted) {
409
+ @if (message.replyToId && !message.isDeleted) {
410
+ <div
411
+ class="k-message-reference k-message-reference-receiver"
412
+ (click)="onReplyReferenceClick($event, message.replyToId)"
413
+ >
414
+ <chat-message-reference-content [message]="getMessageById(message.replyToId)"></chat-message-reference-content>
415
+ </div>
416
+ }
417
+ @if (message.isDeleted) {
418
+ <span class="k-chat-bubble-text">
419
+ {{ getDeletedMessageText() }}
420
+ </span>
421
+ }
422
+ @if (!message.isDeleted && parts.length > 0) {
423
+ <span class="k-chat-bubble-text">
424
+ @for (part of parts; track part) {
425
+ @if (part.type === 'text') {
426
+ {{part.content}}
427
+ }
428
+ @if (part.type === 'link') {
429
+ <a [href]="part.href" target="_blank">{{part.content}}</a>
430
+ }
431
+ }
432
+ </span>
433
+ }
434
+ }
435
+ @if (hasFiles && !message.isDeleted) {
436
+ <ul
437
+ class="k-chat-file-wrapper"
432
438
  [ngClass]="{
433
- 'k-chat-files-wrap': chatService.messageFilesLayout === 'wrap',
439
+ 'k-chat-files-wrap': chatService.messageFilesLayout === 'wrap',
434
440
  'k-chat-files-horizontal': chatService.messageFilesLayout === 'horizontal'
435
441
  }"
436
- >
437
- <li
438
- *ngFor="let file of message.files"
439
- class="k-chat-file"
440
- [chatFile]="file"
441
- [fileActions]="fileActions"
442
- (actionClick)="onFileAction($event, file)"
443
- (actionsToggle)="onActionPopupChange($event)"
444
- (actionButtonClick)="onActionButtonClick($event)"
445
- ></li>
446
- </ul>
447
-
448
- <div class="k-chat-download-button-wrapper" *ngIf="hasMultipleFiles && !message.isDeleted">
449
- <button
450
- kendoButton
451
- class="k-chat-download-button"
452
- fillMode="flat"
453
- icon="download"
454
- [svgIcon]="downloadIcon"
455
- [attr.title]="textFor('downloadAllFilesText')"
456
- (click)="onDownloadAll()"
457
- >{{ textFor('downloadAllFilesText') }}</button>
458
- </div>
442
+ >
443
+ @for (file of message.files; track file) {
444
+ <li
445
+ class="k-chat-file"
446
+ [chatFile]="file"
447
+ [fileActions]="fileActions"
448
+ (actionClick)="onFileAction($event, file)"
449
+ (actionsToggle)="onActionPopupChange($event)"
450
+ (actionButtonClick)="onActionButtonClick($event)"
451
+ ></li>
452
+ }
453
+ </ul>
454
+ }
455
+ @if (hasMultipleFiles && !message.isDeleted) {
456
+ <div class="k-chat-download-button-wrapper">
457
+ <button
458
+ kendoButton
459
+ class="k-chat-download-button"
460
+ fillMode="flat"
461
+ icon="download"
462
+ [svgIcon]="downloadIcon"
463
+ [attr.title]="textFor('downloadAllFilesText')"
464
+ (click)="onDownloadAll()"
465
+ >{{ textFor('downloadAllFilesText') }}</button>
459
466
  </div>
460
-
461
- <span
462
- class="k-bubble-expandable-indicator"
463
- *ngIf="isMessageExpandable && showExpandCollapseIcon"
464
- [attr.tabindex]="'0'"
465
- [attr.role]="'button'"
466
- [attr.title]="isMessageExpanded ? textFor('collapseTitle') : textFor('expandTitle')"
467
- (mousedown)="chatService.toggleMessageState = true"
468
- (click)="toggleMessageState($event)"
469
- >
470
- <kendo-icon-wrapper
471
- [name]="isMessageExpanded ? 'chevron-up' : 'chevron-down'"
472
- [svgIcon]="isMessageExpanded ? collapseIcon : expandIcon"
473
- >
474
- </kendo-icon-wrapper>
475
- </span>
467
+ }
476
468
  </div>
477
- </ng-container>
478
-
479
- <span class="k-message-status" *ngIf="message.status">
480
- <ng-container *ngIf="statusTemplate?.templateRef">
481
- <ng-template
482
- [ngTemplateOutlet]="statusTemplate.templateRef"
483
- [ngTemplateOutletContext]="{ $implicit: message.status, message }"
469
+ @if (isMessageExpandable && showExpandCollapseIcon) {
470
+ <span
471
+ class="k-bubble-expandable-indicator"
472
+ [attr.tabindex]="'0'"
473
+ [attr.role]="'button'"
474
+ [attr.title]="isMessageExpanded ? textFor('collapseTitle') : textFor('expandTitle')"
475
+ (mousedown)="chatService.toggleMessageState = true"
476
+ (click)="toggleMessageState($event)"
484
477
  >
485
- </ng-template>
486
- </ng-container>
487
- <ng-container *ngIf="!statusTemplate?.templateRef">
488
- {{ message.status }}
489
- </ng-container>
478
+ <kendo-icon-wrapper
479
+ [name]="isMessageExpanded ? 'chevron-up' : 'chevron-down'"
480
+ [svgIcon]="isMessageExpanded ? collapseIcon : expandIcon"
481
+ >
482
+ </kendo-icon-wrapper>
483
+ </span>
484
+ }
485
+ </div>
486
+ }
487
+ }
488
+ @if (message.status) {
489
+ <span class="k-message-status">
490
+ @if (statusTemplate?.templateRef) {
491
+ <ng-template
492
+ [ngTemplateOutlet]="statusTemplate.templateRef"
493
+ [ngTemplateOutletContext]="{ $implicit: message.status, message }"
494
+ >
495
+ </ng-template>
496
+ }
497
+ @if (!statusTemplate?.templateRef) {
498
+ {{ message.status }}
499
+ }
490
500
  </span>
491
- </ng-container>
492
- <kendo-toolbar *ngIf="showToolbar" class="k-chat-message-toolbar" fillMode="flat">
493
- <kendo-toolbar-button
494
- *ngFor="let action of toolbarActions"
501
+ }
502
+ }
503
+ @if (showToolbar) {
504
+ <kendo-toolbar class="k-chat-message-toolbar" fillMode="flat">
505
+ @for (action of toolbarActions; track action) {
506
+ <kendo-toolbar-button
495
507
  fillMode="flat"
496
508
  [icon]="action.icon"
497
509
  [svgIcon]="action.svgIcon"
498
510
  [disabled]="action.disabled"
499
511
  [title]="action.label"
500
512
  (click)="onToolbarAction($event, action, message)"
501
- >
502
- </kendo-toolbar-button>
503
- </kendo-toolbar>
504
- `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "component", type: i4.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "component", type: ChatFileComponent, selector: "li[chatFile]", inputs: ["chatFile", "removable", "fileActions"], outputs: ["remove", "actionClick", "actionsToggle", "actionButtonClick"] }, { kind: "component", type: ToolBarComponent, selector: "kendo-toolbar", inputs: ["overflow", "resizable", "popupSettings", "fillMode", "tabindex", "size", "tabIndex", "showIcon", "showText"], outputs: ["open", "close"], exportAs: ["kendoToolBar"] }, { kind: "component", type: ToolBarButtonComponent, selector: "kendo-toolbar-button", inputs: ["showText", "showIcon", "text", "style", "className", "title", "disabled", "toggleable", "look", "togglable", "selected", "fillMode", "rounded", "themeColor", "icon", "iconClass", "svgIcon", "imageUrl"], outputs: ["click", "pointerdown", "selectedChange"], exportAs: ["kendoToolBarButton"] }, { kind: "component", type: MessageReferenceComponent, selector: "chat-message-reference-content", inputs: ["message"] }] });
513
+ >
514
+ </kendo-toolbar-button>
515
+ }
516
+ </kendo-toolbar>
517
+ }
518
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "component", type: i4.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "component", type: ChatFileComponent, selector: "li[chatFile]", inputs: ["chatFile", "removable", "fileActions"], outputs: ["remove", "actionClick", "actionsToggle", "actionButtonClick"] }, { kind: "component", type: ToolBarComponent, selector: "kendo-toolbar", inputs: ["overflow", "resizable", "popupSettings", "fillMode", "tabindex", "size", "tabIndex", "showIcon", "showText"], outputs: ["open", "close"], exportAs: ["kendoToolBar"] }, { kind: "component", type: ToolBarButtonComponent, selector: "kendo-toolbar-button", inputs: ["showText", "showIcon", "text", "style", "className", "title", "disabled", "toggleable", "look", "togglable", "selected", "fillMode", "rounded", "themeColor", "icon", "iconClass", "svgIcon", "imageUrl"], outputs: ["click", "pointerdown", "selectedChange"], exportAs: ["kendoToolBarButton"] }, { kind: "component", type: MessageReferenceComponent, selector: "chat-message-reference-content", inputs: ["message"] }] });
505
519
  }
506
520
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageComponent, decorators: [{
507
521
  type: Component,
@@ -514,174 +528,188 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
514
528
  }
515
529
  ],
516
530
  template: `
517
- <ng-container *ngIf="useCustomBubbleTemplate">
518
- <ng-container *ngTemplateOutlet="getActiveBubbleTemplate()?.templateRef; context: { $implicit: message };"></ng-container>
519
- </ng-container>
531
+ @if (useCustomBubbleTemplate) {
532
+ <ng-container *ngTemplateOutlet="getActiveBubbleTemplate()?.templateRef; context: { $implicit: message };"></ng-container>
533
+ }
520
534
 
521
- <ng-container *ngIf="!useCustomBubbleTemplate">
535
+ @if (!useCustomBubbleTemplate) {
536
+ @if (chatService.timestampVisibility === 'focus' && message.timestamp) {
522
537
  <time
523
- [attr.aria-hidden]="!selected"
524
- class="k-message-time"
525
- *ngIf="chatService.timestampVisibility === 'focus' && message.timestamp"
526
- >
527
- {{ formatTimeStamp(message.timestamp) }}
538
+ [attr.aria-hidden]="!selected"
539
+ class="k-message-time"
540
+ >
541
+ {{ formatTimeStamp(message.timestamp) }}
528
542
  </time>
529
-
530
- <ng-container *ngIf="message.typing">
531
- <div class="k-chat-bubble k-bubble">
532
- <div class="k-typing-indicator" [attr.tabindex]="'-1'">
533
- <span></span>
534
- <span></span>
535
- <span></span>
536
- </div>
537
- </div>
538
- </ng-container>
539
-
540
- <ng-container *ngIf="!message.typing">
541
- <div
542
- class="k-chat-bubble k-bubble"
543
- *ngIf="useCustomContentTemplate"
544
- [attr.tabindex]="0"
543
+ }
544
+ @if (message.typing) {
545
+ <div class="k-chat-bubble k-bubble">
546
+ <div class="k-typing-indicator" [attr.tabindex]="'-1'">
547
+ <span></span>
548
+ <span></span>
549
+ <span></span>
550
+ </div>
551
+ </div>
552
+ }
553
+ @if (!message.typing) {
554
+ @if (useCustomContentTemplate) {
555
+ <div
556
+ class="k-chat-bubble k-bubble"
557
+ [attr.tabindex]="0"
545
558
  [ngClass]="{
546
- 'k-bubble-expandable': isMessageExpandable,
559
+ 'k-bubble-expandable': isMessageExpandable,
547
560
  'k-expanded': isMessageExpanded,
548
- 'k-selected': selected,
561
+ 'k-selected': selected,
549
562
  'k-focus': selected,
550
563
  'k-active': isActiveMessage
551
564
  }"
552
565
  >
553
- <div class="k-bubble-content">
554
- <ng-container *ngTemplateOutlet="getActiveContentTemplate()?.templateRef; context: { $implicit: message };"></ng-container>
555
- </div>
556
- <span
557
- class="k-bubble-expandable-indicator"
558
- *ngIf="isMessageExpandable && showExpandCollapseIcon"
559
- [attr.tabindex]="'0'"
560
- [attr.role]="'button'"
561
- [attr.title]="isMessageExpanded ? textFor('collapseTitle') : textFor('expandTitle')"
562
- (mousedown)="chatService.toggleMessageState = true"
563
- (click)="toggleMessageState($event)"
564
- >
565
- <kendo-icon-wrapper
566
- [name]="isMessageExpanded ? 'chevron-up' : 'chevron-down'"
567
- [svgIcon]="isMessageExpanded ? collapseIcon : expandIcon"
568
- >
569
- </kendo-icon-wrapper>
570
- </span>
566
+ <div class="k-bubble-content">
567
+ <ng-container *ngTemplateOutlet="getActiveContentTemplate()?.templateRef; context: { $implicit: message };"></ng-container>
571
568
  </div>
572
-
573
- <div
574
- class="k-chat-bubble k-bubble"
575
- *ngIf="!useCustomContentTemplate && hasMessageContent"
576
- [attr.tabindex]="0"
569
+ @if (isMessageExpandable && showExpandCollapseIcon) {
570
+ <span
571
+ class="k-bubble-expandable-indicator"
572
+ [attr.tabindex]="'0'"
573
+ [attr.role]="'button'"
574
+ [attr.title]="isMessageExpanded ? textFor('collapseTitle') : textFor('expandTitle')"
575
+ (mousedown)="chatService.toggleMessageState = true"
576
+ (click)="toggleMessageState($event)"
577
+ >
578
+ <kendo-icon-wrapper
579
+ [name]="isMessageExpanded ? 'chevron-up' : 'chevron-down'"
580
+ [svgIcon]="isMessageExpanded ? collapseIcon : expandIcon"
581
+ >
582
+ </kendo-icon-wrapper>
583
+ </span>
584
+ }
585
+ </div>
586
+ }
587
+ @if (!useCustomContentTemplate && hasMessageContent) {
588
+ <div
589
+ class="k-chat-bubble k-bubble"
590
+ [attr.tabindex]="0"
577
591
  [ngClass]="{
578
- 'k-bubble-expandable': isMessageExpandable,
579
- 'k-expanded': isMessageExpanded,
580
- 'k-selected': selected,
592
+ 'k-bubble-expandable': isMessageExpandable,
593
+ 'k-expanded': isMessageExpanded,
594
+ 'k-selected': selected,
581
595
  'k-focus': selected,
582
596
  'k-active': isActiveMessage
583
597
  }"
584
598
  >
585
- <div class="k-bubble-content">
586
- <ng-container *ngIf="message.text || message.isDeleted">
587
- <div
588
- class="k-message-reference k-message-reference-receiver"
589
- *ngIf="message.replyToId && !message.isDeleted"
590
- (click)="onReplyReferenceClick($event, message.replyToId)"
591
- >
592
- <chat-message-reference-content [message]="getMessageById(message.replyToId)"></chat-message-reference-content>
593
- </div>
594
-
595
- <span class="k-chat-bubble-text" *ngIf="message.isDeleted">
596
- {{ getDeletedMessageText() }}
597
- </span>
598
-
599
- <span class="k-chat-bubble-text" *ngIf="!message.isDeleted && parts.length > 0">
600
- <ng-container *ngFor="let part of parts">
601
- <ng-container *ngIf="part.type === 'text'">{{part.content}}</ng-container>
602
- <a *ngIf="part.type === 'link'" [href]="part.href" target="_blank">{{part.content}}</a>
603
- </ng-container>
604
- </span>
605
- </ng-container>
606
-
607
- <ul
608
- class="k-chat-file-wrapper"
609
- *ngIf="hasFiles && !message.isDeleted"
599
+ <div class="k-bubble-content">
600
+ @if (message.text || message.isDeleted) {
601
+ @if (message.replyToId && !message.isDeleted) {
602
+ <div
603
+ class="k-message-reference k-message-reference-receiver"
604
+ (click)="onReplyReferenceClick($event, message.replyToId)"
605
+ >
606
+ <chat-message-reference-content [message]="getMessageById(message.replyToId)"></chat-message-reference-content>
607
+ </div>
608
+ }
609
+ @if (message.isDeleted) {
610
+ <span class="k-chat-bubble-text">
611
+ {{ getDeletedMessageText() }}
612
+ </span>
613
+ }
614
+ @if (!message.isDeleted && parts.length > 0) {
615
+ <span class="k-chat-bubble-text">
616
+ @for (part of parts; track part) {
617
+ @if (part.type === 'text') {
618
+ {{part.content}}
619
+ }
620
+ @if (part.type === 'link') {
621
+ <a [href]="part.href" target="_blank">{{part.content}}</a>
622
+ }
623
+ }
624
+ </span>
625
+ }
626
+ }
627
+ @if (hasFiles && !message.isDeleted) {
628
+ <ul
629
+ class="k-chat-file-wrapper"
610
630
  [ngClass]="{
611
- 'k-chat-files-wrap': chatService.messageFilesLayout === 'wrap',
631
+ 'k-chat-files-wrap': chatService.messageFilesLayout === 'wrap',
612
632
  'k-chat-files-horizontal': chatService.messageFilesLayout === 'horizontal'
613
633
  }"
614
- >
615
- <li
616
- *ngFor="let file of message.files"
617
- class="k-chat-file"
618
- [chatFile]="file"
619
- [fileActions]="fileActions"
620
- (actionClick)="onFileAction($event, file)"
621
- (actionsToggle)="onActionPopupChange($event)"
622
- (actionButtonClick)="onActionButtonClick($event)"
623
- ></li>
624
- </ul>
625
-
626
- <div class="k-chat-download-button-wrapper" *ngIf="hasMultipleFiles && !message.isDeleted">
627
- <button
628
- kendoButton
629
- class="k-chat-download-button"
630
- fillMode="flat"
631
- icon="download"
632
- [svgIcon]="downloadIcon"
633
- [attr.title]="textFor('downloadAllFilesText')"
634
- (click)="onDownloadAll()"
635
- >{{ textFor('downloadAllFilesText') }}</button>
636
- </div>
634
+ >
635
+ @for (file of message.files; track file) {
636
+ <li
637
+ class="k-chat-file"
638
+ [chatFile]="file"
639
+ [fileActions]="fileActions"
640
+ (actionClick)="onFileAction($event, file)"
641
+ (actionsToggle)="onActionPopupChange($event)"
642
+ (actionButtonClick)="onActionButtonClick($event)"
643
+ ></li>
644
+ }
645
+ </ul>
646
+ }
647
+ @if (hasMultipleFiles && !message.isDeleted) {
648
+ <div class="k-chat-download-button-wrapper">
649
+ <button
650
+ kendoButton
651
+ class="k-chat-download-button"
652
+ fillMode="flat"
653
+ icon="download"
654
+ [svgIcon]="downloadIcon"
655
+ [attr.title]="textFor('downloadAllFilesText')"
656
+ (click)="onDownloadAll()"
657
+ >{{ textFor('downloadAllFilesText') }}</button>
637
658
  </div>
638
-
639
- <span
640
- class="k-bubble-expandable-indicator"
641
- *ngIf="isMessageExpandable && showExpandCollapseIcon"
642
- [attr.tabindex]="'0'"
643
- [attr.role]="'button'"
644
- [attr.title]="isMessageExpanded ? textFor('collapseTitle') : textFor('expandTitle')"
645
- (mousedown)="chatService.toggleMessageState = true"
646
- (click)="toggleMessageState($event)"
647
- >
648
- <kendo-icon-wrapper
649
- [name]="isMessageExpanded ? 'chevron-up' : 'chevron-down'"
650
- [svgIcon]="isMessageExpanded ? collapseIcon : expandIcon"
651
- >
652
- </kendo-icon-wrapper>
653
- </span>
659
+ }
654
660
  </div>
655
- </ng-container>
656
-
657
- <span class="k-message-status" *ngIf="message.status">
658
- <ng-container *ngIf="statusTemplate?.templateRef">
659
- <ng-template
660
- [ngTemplateOutlet]="statusTemplate.templateRef"
661
- [ngTemplateOutletContext]="{ $implicit: message.status, message }"
661
+ @if (isMessageExpandable && showExpandCollapseIcon) {
662
+ <span
663
+ class="k-bubble-expandable-indicator"
664
+ [attr.tabindex]="'0'"
665
+ [attr.role]="'button'"
666
+ [attr.title]="isMessageExpanded ? textFor('collapseTitle') : textFor('expandTitle')"
667
+ (mousedown)="chatService.toggleMessageState = true"
668
+ (click)="toggleMessageState($event)"
662
669
  >
663
- </ng-template>
664
- </ng-container>
665
- <ng-container *ngIf="!statusTemplate?.templateRef">
666
- {{ message.status }}
667
- </ng-container>
670
+ <kendo-icon-wrapper
671
+ [name]="isMessageExpanded ? 'chevron-up' : 'chevron-down'"
672
+ [svgIcon]="isMessageExpanded ? collapseIcon : expandIcon"
673
+ >
674
+ </kendo-icon-wrapper>
675
+ </span>
676
+ }
677
+ </div>
678
+ }
679
+ }
680
+ @if (message.status) {
681
+ <span class="k-message-status">
682
+ @if (statusTemplate?.templateRef) {
683
+ <ng-template
684
+ [ngTemplateOutlet]="statusTemplate.templateRef"
685
+ [ngTemplateOutletContext]="{ $implicit: message.status, message }"
686
+ >
687
+ </ng-template>
688
+ }
689
+ @if (!statusTemplate?.templateRef) {
690
+ {{ message.status }}
691
+ }
668
692
  </span>
669
- </ng-container>
670
- <kendo-toolbar *ngIf="showToolbar" class="k-chat-message-toolbar" fillMode="flat">
671
- <kendo-toolbar-button
672
- *ngFor="let action of toolbarActions"
693
+ }
694
+ }
695
+ @if (showToolbar) {
696
+ <kendo-toolbar class="k-chat-message-toolbar" fillMode="flat">
697
+ @for (action of toolbarActions; track action) {
698
+ <kendo-toolbar-button
673
699
  fillMode="flat"
674
700
  [icon]="action.icon"
675
701
  [svgIcon]="action.svgIcon"
676
702
  [disabled]="action.disabled"
677
703
  [title]="action.label"
678
704
  (click)="onToolbarAction($event, action, message)"
679
- >
680
- </kendo-toolbar-button>
681
- </kendo-toolbar>
682
- `,
705
+ >
706
+ </kendo-toolbar-button>
707
+ }
708
+ </kendo-toolbar>
709
+ }
710
+ `,
683
711
  standalone: true,
684
- imports: [NgIf, NgClass, NgFor, NgTemplateOutlet, IconWrapperComponent, KENDO_BUTTONS, ChatFileComponent, ToolBarComponent, ToolBarButtonComponent, MessageReferenceComponent],
712
+ imports: [NgClass, NgTemplateOutlet, IconWrapperComponent, KENDO_BUTTONS, ChatFileComponent, ToolBarComponent, ToolBarButtonComponent, MessageReferenceComponent],
685
713
  }]
686
714
  }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.IntlService }, { type: i2.ChatService }, { type: i3.LocalizationService }, { type: i0.ChangeDetectorRef }], propDecorators: { message: [{
687
715
  type: Input