@trixwell/ngx-parl 4.2.0 → 5.0.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.
@@ -1,11 +1,13 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, inject, model, computed, effect, ViewChild, Component, Injectable, Pipe, signal, Optional, isDevMode } from '@angular/core';
2
+ import { input, inject, model, computed, effect, ViewChild, Component, Injectable, Pipe, signal, ViewEncapsulation, Optional, isDevMode } from '@angular/core';
3
3
  import { NgClass, NgOptimizedImage, DatePipe } from '@angular/common';
4
+ import { toSignal } from '@angular/core/rxjs-interop';
4
5
  import { FormsModule } from '@angular/forms';
5
6
  import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
6
7
  import * as i2 from '@ngneat/transloco';
7
- import { TranslocoPipe, TranslocoModule, provideTransloco } from '@ngneat/transloco';
8
+ import { TranslocoPipe, TranslocoService, TranslocoModule, provideTransloco } from '@ngneat/transloco';
8
9
  import { FocusTrapFactory } from '@angular/cdk/a11y';
10
+ import { IonButton, IonAlert } from '@ionic/angular/standalone';
9
11
  import * as i1 from '@angular/common/http';
10
12
  import { InfiniteScrollDirective } from 'ngx-infinite-scroll';
11
13
  import * as i3 from '@angular/material/dialog';
@@ -25,6 +27,7 @@ class ChatMessage {
25
27
  avatar;
26
28
  file_path;
27
29
  file_list;
30
+ actions;
28
31
  checked;
29
32
  edit = false;
30
33
  pending = false;
@@ -42,6 +45,7 @@ class ChatMessage {
42
45
  this.pending = data.pending ?? false;
43
46
  this.file_path = data.file_path ?? null;
44
47
  this.file_list = data.file_list ?? null;
48
+ this.actions = Array.isArray(data.actions) ? data.actions : [];
45
49
  }
46
50
  get dateSimple() {
47
51
  const d = new Date(this.cr_time.replace(' ', 'T'));
@@ -279,6 +283,9 @@ class ChatMessageComponent {
279
283
  closePreviewHandler = () => this.closePreview();
280
284
  requestEdit = model(null, ...(ngDevMode ? [{ debugName: "requestEdit" }] : []));
281
285
  requestDelete = model(null, ...(ngDevMode ? [{ debugName: "requestDelete" }] : []));
286
+ mobileMode = input(false, ...(ngDevMode ? [{ debugName: "mobileMode" }] : []));
287
+ quickActions = input([], ...(ngDevMode ? [{ debugName: "quickActions" }] : []));
288
+ quickActionClick = model(null, ...(ngDevMode ? [{ debugName: "quickActionClick" }] : []));
282
289
  constructor(utils) {
283
290
  this.utils = utils;
284
291
  }
@@ -321,7 +328,27 @@ class ChatMessageComponent {
321
328
  : 'assets/ngx-parl/icons/avatar_manager.svg';
322
329
  return message.avatar || fallback;
323
330
  }, ...(ngDevMode ? [{ debugName: "avatarSrc" }] : []));
331
+ showAvatar = computed(() => {
332
+ const isMobile = this.mobileMode();
333
+ const isOutgoing = this.currentMessage().type === this.messageType.Outgoing;
334
+ return !(isMobile && isOutgoing);
335
+ }, ...(ngDevMode ? [{ debugName: "showAvatar" }] : []));
336
+ showQuickActions = computed(() => {
337
+ const isOutgoing = this.currentMessage().type === this.messageType.Outgoing;
338
+ return isOutgoing && this.quickActions().length > 0;
339
+ }, ...(ngDevMode ? [{ debugName: "showQuickActions" }] : []));
340
+ showMessageBubble = computed(() => !this.showQuickActions(), ...(ngDevMode ? [{ debugName: "showMessageBubble" }] : []));
341
+ showMessageBody = computed(() => this.showMessageBubble() || this.attachments().length > 0, ...(ngDevMode ? [{ debugName: "showMessageBody" }] : []));
342
+ canOpenContextMenu = computed(() => {
343
+ const message = this.currentMessage();
344
+ const isOutgoing = message.type === this.messageType.Outgoing;
345
+ const isSent = message.pending !== true;
346
+ return isOutgoing && isSent;
347
+ }, ...(ngDevMode ? [{ debugName: "canOpenContextMenu" }] : []));
324
348
  openContextMenu(event, trigger, triggerElement) {
349
+ if (!this.canOpenContextMenu()) {
350
+ return this;
351
+ }
325
352
  event.preventDefault();
326
353
  event.stopPropagation();
327
354
  if (event instanceof MouseEvent) {
@@ -360,12 +387,22 @@ class ChatMessageComponent {
360
387
  queueMicrotask(() => this.requestDelete.set(null));
361
388
  return this;
362
389
  }
390
+ onQuickAction(action) {
391
+ const messageId = this.currentMessage().id;
392
+ const value = (action.value ?? '').trim();
393
+ if (!value) {
394
+ return this;
395
+ }
396
+ this.quickActionClick.set({ actionId: action.id, messageId, value });
397
+ setTimeout(() => this.quickActionClick.set(null), 0);
398
+ return this;
399
+ }
363
400
  canDelete(message) {
364
401
  return message.type === this.messageType.Outgoing;
365
402
  }
366
403
  messageType = MessageType;
367
404
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ChatMessageComponent, deps: [{ token: UtilsService }], target: i0.ɵɵFactoryTarget.Component });
368
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ChatMessageComponent, isStandalone: true, selector: "lib-chat-message", inputs: { currentMessage: { classPropertyName: "currentMessage", publicName: "currentMessage", isSignal: true, isRequired: true, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null }, previewList: { classPropertyName: "previewList", publicName: "previewList", isSignal: true, isRequired: false, transformFunction: null }, previewIndex: { classPropertyName: "previewIndex", publicName: "previewIndex", isSignal: true, isRequired: false, transformFunction: null }, previewOpener: { classPropertyName: "previewOpener", publicName: "previewOpener", isSignal: true, isRequired: false, transformFunction: null }, requestEdit: { classPropertyName: "requestEdit", publicName: "requestEdit", isSignal: true, isRequired: false, transformFunction: null }, requestDelete: { classPropertyName: "requestDelete", publicName: "requestDelete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { edit: "editChange", previewList: "previewListChange", previewIndex: "previewIndexChange", previewOpener: "previewOpenerChange", requestEdit: "requestEditChange", requestDelete: "requestDeleteChange" }, ngImport: i0, template: "<div class=\"message\"\n [ngClass]=\"{\n 'message--outgoing': currentMessage().type === messageType.Outgoing,\n 'message--incoming': currentMessage().type === messageType.Incoming\n }\">\n <div class=\"message__avatar\">\n <img [ngSrc]=\"avatarSrc()\" width=\"36\" height=\"36\" alt=\"avatar\"/>\n </div>\n\n <div class=\"message__body\"\n [class.message__body--attachments-1]=\"attachments().length === 1\"\n [class.message__body--attachments-2]=\"attachments().length === 2\"\n [class.message__body--attachments-3]=\"attachments().length >= 3\"\n (contextmenu)=\"openContextMenu($event, menuTrigger, menuTriggerEl)\"\n (keydown.shift.F10)=\"$event.preventDefault(); menuTrigger.openMenu()\">\n <button type=\"button\"\n class=\"message__menu-trigger\"\n aria-hidden=\"true\"\n tabindex=\"-1\"\n #menuTrigger=\"matMenuTrigger\"\n #menuTriggerEl\n [matMenuTriggerFor]=\"messageMenu\"\n >\n </button>\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file; let i = $index) {\n <button type=\"button\"\n class=\"message__image-button\"\n (click)=\"openPreview(i, $event)\"\n [attr.aria-label]=\"'chat.photo_preview' | transloco\">\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\n </button>\n }\n </div>\n }\n\n <div class=\"message__bubble\" tabindex=\"0\">\n <div class=\"message__text\">{{ currentMessage().content }}</div>\n\n <div class=\"message__meta\">\n <time class=\"message__time\">\n {{ currentMessage().cr_time | date:'HH:mm' }}\n </time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().pending) {\n <span class=\"message__loading\" aria-label=\"Sending\"></span>\n } @else if (currentMessage().checked) {\n <img ngSrc=\"assets/ngx-parl/icons/checked-message.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\"/>\n } @else {\n <img ngSrc=\"assets/ngx-parl/icons/no-check.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\"/>\n }\n }\n </div>\n </div>\n </div>\n</div>\n<div class=\"message__user\">\n @if (currentMessage().type === messageType.Outgoing) {\n <span class=\"message__user-name\">{{ currentMessage().user }}</span>\n }\n</div>\n\n@if (previewList().length) {\n <lib-preview-file\n [srcList]=\"previewList()\"\n [startIndex]=\"previewIndex()\"\n [openerElement]=\"previewOpener()\"\n [closeHandler]=\"closePreviewHandler\">\n </lib-preview-file>\n}\n\n<mat-menu #messageMenu=\"matMenu\" yPosition=\"below\" xPosition=\"before\" class=\"message__menu\">\n @if (currentMessage().type === messageType.Outgoing) {\n <button mat-menu-item (click)=\"editMessage(currentMessage())\">\n <img ngSrc=\"assets/ngx-parl/icons/icon-edit.svg\"\n class=\"message__icon--menu\"\n width=\"20\" height=\"20\" alt=\"hide\"/>\n <span>{{ 'chat.edit' | transloco }}</span>\n </button>\n }\n @if (canDelete(currentMessage())) {\n <button mat-menu-item (click)=\"deleteMessage(currentMessage())\">\n <img ngSrc=\"assets/ngx-parl/icons/trash.svg\"\n class=\"message__icon--menu\"\n width=\"20\" height=\"20\" alt=\"hide\"/>\n <span>{{ 'chat.remove' | transloco }}</span>\n </button>\n }\n</mat-menu>\n", styles: [".flow-theme-primary ::ng-deep .modal-chat__header{background-color:#5a72d7;color:#fff}.flow-theme-primary ::ng-deep .message--incoming .message__body{background:#e9ecef;color:#343a40}.flow-theme-primary ::ng-deep .message--outgoing .message__body{background:#4656ca;color:#fff}:root{--shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, .05);--shadow-md: 0px 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0px 8px 24px rgba(0, 0, 0, .12);--shadow-soft: 0px 0px 6px 0px rgba(46, 46, 46, .12) }.flow-theme-secondary ::ng-deep .modal-chat__header{background-color:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--incoming .message__body{background:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--outgoing .message__body{background:#efefef;color:#464646}.message{display:flex;gap:8px;align-items:flex-end;max-width:80%;animation:pop .12s ease-out}.message__avatar img{display:block;border-radius:1000px}.message__body{padding:8px 12px;min-width:0;font:400 16px/20px inter,sans-serif;border-radius:16px;position:relative}.message__bubble{display:grid;grid-template-columns:1fr auto;column-gap:8px;align-items:end;max-width:100%;word-break:break-word;white-space:pre-wrap}.message__text{min-width:0}.message__meta{display:inline-flex;align-items:center;gap:4px;-webkit-user-select:none;user-select:none;line-height:1;margin:0}.message__time{font:400 12px/16px inter,sans-serif}.message__attachments{display:grid;gap:8px;justify-content:start;width:100%;margin-bottom:8px}.message__attachments:has(:only-child){grid-template-columns:repeat(1,minmax(0,140px))}.message__attachments:has(:nth-child(2):last-child){grid-template-columns:repeat(2,minmax(0,145px))}.message__attachments:has(:nth-child(3)){grid-template-columns:repeat(3,minmax(0,150px))}.message__body--attachments-1{max-width:164px}.message__body--attachments-2{max-width:312px}.message__body--attachments-3{max-width:460px}.message__body--attachments-1 .message__bubble,.message__body--attachments-2 .message__bubble,.message__body--attachments-3 .message__bubble{grid-template-columns:1fr;row-gap:4px}.message__body--attachments-1 .message__meta,.message__body--attachments-2 .message__meta,.message__body--attachments-3 .message__meta{justify-self:end}.message__image-button{display:block;border:none;padding:0;background:transparent;border-radius:12px;overflow:hidden;cursor:pointer}.message__image-button:focus-visible{outline:2px solid #5A72D7;outline-offset:4px}.message__menu-trigger{position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;pointer-events:none}.message__image{display:block;width:100%;height:140px;object-fit:cover;border-radius:12px;aspect-ratio:1/1}.message__bubble:after{content:\"\";display:block;clear:both}.message__time{font:400 12px/16px inter,sans-serif;min-width:30px}.message__icon{width:14px;height:14px;vertical-align:middle}.message__icon--menu{width:20px;height:20px}.message__loading{display:inline-block;width:10px;height:10px;border:2px solid #E9ECEF;border-top-color:#5a72d7;border-radius:50%;animation:message-loading-spin .8s linear infinite}.message--incoming{margin-right:auto}.message--incoming .message__body{border-bottom-right-radius:16px}.message--incoming .message__bubble{border-top-left-radius:4px}.message--incoming .message__time{color:#adb5bd}.message--outgoing{margin-left:auto;flex-direction:row-reverse}.message--outgoing .message__body{border-bottom-left-radius:16px}.message--outgoing .message__bubble{border-top-right-radius:4px}.message--outgoing .message__time{color:#e9ecef}.message--outgoing .message__menu-trigger{right:auto}.message__user{display:flex;justify-content:flex-end;max-width:80%;margin-left:auto;margin-top:4px;padding-right:46px}.message__user-name{font:400 12px/16px inter,sans-serif;color:#ced4da}@keyframes pop{0%{transform:translateY(2px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes message-loading-spin{to{transform:rotate(360deg)}}::ng-deep .mat-mdc-menu-content{background:#fff;width:160px;border-radius:8px;gap:4px;border:1px solid #E1E7F8;padding:8px 4px;box-shadow:0 2px 4px #0000001a;overflow:hidden;font:400 14px/18px inter,sans-serif}::ng-deep .mat-mdc-menu-item-text{font:400 14px/18px inter,sans-serif!important;font-weight:500!important;color:#343a40!important;display:flex;justify-content:flex-start;align-items:center;gap:4px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: PreviewFile, selector: "lib-preview-file", inputs: ["srcList", "startIndex", "title", "openerElement", "closeHandler", "activeIndex", "viewReady", "userNavigated", "previousListLength"], outputs: ["activeIndexChange", "viewReadyChange", "userNavigatedChange", "previousListLengthChange"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
405
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ChatMessageComponent, isStandalone: true, selector: "lib-chat-message", inputs: { currentMessage: { classPropertyName: "currentMessage", publicName: "currentMessage", isSignal: true, isRequired: true, transformFunction: null }, edit: { classPropertyName: "edit", publicName: "edit", isSignal: true, isRequired: false, transformFunction: null }, previewList: { classPropertyName: "previewList", publicName: "previewList", isSignal: true, isRequired: false, transformFunction: null }, previewIndex: { classPropertyName: "previewIndex", publicName: "previewIndex", isSignal: true, isRequired: false, transformFunction: null }, previewOpener: { classPropertyName: "previewOpener", publicName: "previewOpener", isSignal: true, isRequired: false, transformFunction: null }, requestEdit: { classPropertyName: "requestEdit", publicName: "requestEdit", isSignal: true, isRequired: false, transformFunction: null }, requestDelete: { classPropertyName: "requestDelete", publicName: "requestDelete", isSignal: true, isRequired: false, transformFunction: null }, mobileMode: { classPropertyName: "mobileMode", publicName: "mobileMode", isSignal: true, isRequired: false, transformFunction: null }, quickActions: { classPropertyName: "quickActions", publicName: "quickActions", isSignal: true, isRequired: false, transformFunction: null }, quickActionClick: { classPropertyName: "quickActionClick", publicName: "quickActionClick", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { edit: "editChange", previewList: "previewListChange", previewIndex: "previewIndexChange", previewOpener: "previewOpenerChange", requestEdit: "requestEditChange", requestDelete: "requestDeleteChange", quickActionClick: "quickActionClickChange" }, ngImport: i0, template: "<div class=\"message\"\n [ngClass]=\"{\n 'message--outgoing': currentMessage().type === messageType.Outgoing,\n 'message--incoming': currentMessage().type === messageType.Incoming,\n 'message--mobile': mobileMode()\n }\">\n @if (showAvatar()) {\n <div class=\"message__avatar\">\n <img [ngSrc]=\"avatarSrc()\" width=\"36\" height=\"36\" alt=\"avatar\"/>\n </div>\n }\n\n @if (showMessageBody()) {\n <div class=\"message__body\"\n (contextmenu)=\"openContextMenu($event, menuTrigger, menuTriggerEl)\"\n (keydown.shift.F10)=\"openContextMenu($event, menuTrigger, menuTriggerEl)\">\n <button type=\"button\"\n class=\"message__menu-trigger\"\n aria-hidden=\"true\"\n tabindex=\"-1\"\n #menuTrigger=\"matMenuTrigger\"\n #menuTriggerEl\n [matMenuTriggerFor]=\"messageMenu\">\n </button>\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file; let i = $index) {\n <button type=\"button\"\n class=\"message__image-button\"\n (click)=\"openPreview(i, $event)\"\n [attr.aria-label]=\"'chat.photo_preview' | transloco\">\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\n </button>\n }\n </div>\n }\n\n @if (showMessageBubble()) {\n <div class=\"message__bubble\" tabindex=\"0\">\n <div class=\"message__text\">{{ currentMessage().content }}</div>\n\n <div class=\"message__meta\">\n <time class=\"message__time\">\n {{ currentMessage().cr_time | date:'HH:mm' }}\n </time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().pending) {\n <span class=\"message__loading\" aria-label=\"Sending\"></span>\n } @else if (currentMessage().checked) {\n <img ngSrc=\"assets/ngx-parl/icons/checked-message.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\"/>\n } @else {\n <img ngSrc=\"assets/ngx-parl/icons/no-check.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\"/>\n }\n }\n </div>\n </div>\n }\n\n </div>\n }\n\n @if (showQuickActions()) {\n <div class=\"message__quick-actions-wrap\" role=\"group\" aria-label=\"Quick actions\">\n <div class=\"message__quick-actions\">\n @for (action of quickActions(); track action.id) {\n <ion-button\n class=\"message__quick-action-button\"\n fill=\"outline\"\n expand=\"block\"\n [disabled]=\"action.disabled === true\"\n (click)=\"onQuickAction(action)\">\n {{ action.title }}\n </ion-button>\n }\n </div>\n </div>\n }\n</div>\n@if (!showQuickActions()) {\n <div class=\"message__user\" [ngClass]=\"{'message__user--mobile': mobileMode()}\">\n @if (currentMessage().type === messageType.Outgoing) {\n <span class=\"message__user-name\">{{ currentMessage().user }}</span>\n }\n </div>\n}\n\n@if (previewList().length) {\n <lib-preview-file\n [srcList]=\"previewList()\"\n [startIndex]=\"previewIndex()\"\n [openerElement]=\"previewOpener()\"\n [closeHandler]=\"closePreviewHandler\">\n </lib-preview-file>\n}\n\n<mat-menu #messageMenu=\"matMenu\" yPosition=\"below\" xPosition=\"before\" class=\"message__menu\">\n @if (currentMessage().type === messageType.Outgoing) {\n <button mat-menu-item (click)=\"editMessage(currentMessage())\">\n <img ngSrc=\"assets/ngx-parl/icons/icon-edit.svg\"\n class=\"message__icon--menu\"\n width=\"20\" height=\"20\" alt=\"hide\"/>\n <span>{{ 'chat.edit' | transloco }}</span>\n </button>\n }\n @if (canDelete(currentMessage())) {\n <button mat-menu-item (click)=\"deleteMessage(currentMessage())\">\n <img ngSrc=\"assets/ngx-parl/icons/trash.svg\"\n class=\"message__icon--menu\"\n width=\"20\" height=\"20\" alt=\"hide\"/>\n <span>{{ 'chat.remove' | transloco }}</span>\n </button>\n }\n</mat-menu>\n", styles: [".flow-theme-primary ::ng-deep .modal-chat__header{background-color:#5a72d7;color:#fff}.flow-theme-primary ::ng-deep .message--incoming .message__body{background:#e9ecef;color:#343a40}.flow-theme-primary ::ng-deep .message--outgoing .message__body{background:#4656ca;color:#fff}:root{--shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, .05);--shadow-md: 0px 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0px 8px 24px rgba(0, 0, 0, .12);--shadow-soft: 0px 0px 6px 0px rgba(46, 46, 46, .12) }.flow-theme-secondary ::ng-deep .modal-chat__header{background-color:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--incoming .message__body{background:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--outgoing .message__body{background:#efefef;color:#464646}.message{display:flex;gap:8px;align-items:flex-end;max-width:80%;animation:pop .12s ease-out}.message__avatar img{display:block;border-radius:1000px}.message__body{padding:8px 12px;min-width:0;font:400 16px/20px inter,sans-serif;border-radius:16px;position:relative}.message__bubble{display:grid;grid-template-columns:1fr auto;column-gap:8px;align-items:end;max-width:100%;word-break:break-word;white-space:pre-wrap}.message__quick-actions-wrap{display:flex;margin-top:12px;width:100%;background:transparent}.message__quick-actions{display:grid;gap:8px;width:234px;max-width:100%;background:transparent}.message__quick-action-button{--border-radius: 16px;--border-width: 1px;--border-style: solid;--border-color: #2563EB;--color: #2563EB;--padding-top: tokens.$space-3;--padding-bottom: tokens.$space-3;--padding-start: tokens.$space-6;--padding-end: tokens.$space-6;height:48px;text-transform:none;font:500 14px/18px inter,sans-serif;margin:0}.message__text{min-width:0}.message__meta{display:inline-flex;align-items:center;gap:4px;-webkit-user-select:none;user-select:none;line-height:1;margin:0}.message__time{font:400 12px/16px inter,sans-serif}.message__attachments{display:grid;gap:8px;justify-content:start;width:100%;margin-bottom:8px}.message__attachments:has(:only-child){grid-template-columns:repeat(1,minmax(0,140px))}.message__attachments:has(:nth-child(2):last-child){grid-template-columns:repeat(2,minmax(0,145px))}.message__attachments:has(:nth-child(3)){grid-template-columns:repeat(3,minmax(0,150px))}.message__body--attachments-1{max-width:164px}.message__body--attachments-2{max-width:312px}.message__body--attachments-3{max-width:460px}.message__body--attachments-1 .message__bubble,.message__body--attachments-2 .message__bubble,.message__body--attachments-3 .message__bubble{grid-template-columns:1fr;row-gap:4px}.message__body--attachments-1 .message__meta,.message__body--attachments-2 .message__meta,.message__body--attachments-3 .message__meta{justify-self:end}.message__image-button{display:block;border:none;padding:0;background:transparent;border-radius:12px;overflow:hidden;cursor:pointer}.message__image-button:focus-visible{outline:2px solid #5A72D7;outline-offset:4px}.message__menu-trigger{position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;pointer-events:none}.message__image{display:block;width:100%;height:140px;object-fit:cover;border-radius:12px;aspect-ratio:1/1}.message__bubble:after{content:\"\";display:block;clear:both}.message__time{font:400 12px/16px inter,sans-serif;min-width:30px}.message__icon{width:14px;height:14px;vertical-align:middle}.message__icon--menu{width:20px;height:20px}.message__loading{display:inline-block;width:10px;height:10px;border:2px solid #E9ECEF;border-top-color:#5a72d7;border-radius:50%;animation:message-loading-spin .8s linear infinite}.message--incoming{margin-right:auto}.message--incoming .message__body{border-bottom-right-radius:16px}.message--incoming .message__bubble{border-top-left-radius:4px}.message--incoming .message__time{color:#adb5bd}.message--incoming .message__quick-actions-wrap{justify-content:flex-start}.message--outgoing{margin-left:auto;flex-direction:row-reverse}.message--outgoing .message__body{border-bottom-right-radius:0}.message--outgoing .message__bubble{border-top-right-radius:4px}.message--outgoing .message__time{color:#e9ecef}.message--outgoing .message__menu-trigger{right:auto}.message--outgoing .message__quick-actions-wrap{justify-content:flex-end}.message--mobile .message__user{padding-right:5px!important}.message--mobile.message--outgoing .message__body{border-bottom-right-radius:0}.message__user{display:flex;justify-content:flex-end;max-width:80%;margin-left:auto;margin-top:4px;padding-right:46px}.message__user--mobile{padding-right:5px!important}.message__user-name{font:400 12px/16px inter,sans-serif;color:#ced4da}@keyframes pop{0%{transform:translateY(2px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes message-loading-spin{to{transform:rotate(360deg)}}::ng-deep .mat-mdc-menu-content{background:#fff;width:160px;border-radius:8px;gap:4px;border:1px solid #E1E7F8;padding:8px 4px;box-shadow:0 2px 4px #0000001a;overflow:hidden;font:400 14px/18px inter,sans-serif}::ng-deep .mat-mdc-menu-item-text{font:400 14px/18px inter,sans-serif!important;font-weight:500!important;color:#343a40!important;display:flex;justify-content:flex-start;align-items:center;gap:4px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: PreviewFile, selector: "lib-preview-file", inputs: ["srcList", "startIndex", "title", "openerElement", "closeHandler", "activeIndex", "viewReady", "userNavigated", "previousListLength"], outputs: ["activeIndexChange", "viewReadyChange", "userNavigatedChange", "previousListLengthChange"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
369
406
  }
370
407
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ChatMessageComponent, decorators: [{
371
408
  type: Component,
@@ -378,8 +415,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
378
415
  MatMenuTrigger,
379
416
  TranslocoPipe,
380
417
  PreviewFile,
381
- ], standalone: true, template: "<div class=\"message\"\n [ngClass]=\"{\n 'message--outgoing': currentMessage().type === messageType.Outgoing,\n 'message--incoming': currentMessage().type === messageType.Incoming\n }\">\n <div class=\"message__avatar\">\n <img [ngSrc]=\"avatarSrc()\" width=\"36\" height=\"36\" alt=\"avatar\"/>\n </div>\n\n <div class=\"message__body\"\n [class.message__body--attachments-1]=\"attachments().length === 1\"\n [class.message__body--attachments-2]=\"attachments().length === 2\"\n [class.message__body--attachments-3]=\"attachments().length >= 3\"\n (contextmenu)=\"openContextMenu($event, menuTrigger, menuTriggerEl)\"\n (keydown.shift.F10)=\"$event.preventDefault(); menuTrigger.openMenu()\">\n <button type=\"button\"\n class=\"message__menu-trigger\"\n aria-hidden=\"true\"\n tabindex=\"-1\"\n #menuTrigger=\"matMenuTrigger\"\n #menuTriggerEl\n [matMenuTriggerFor]=\"messageMenu\"\n >\n </button>\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file; let i = $index) {\n <button type=\"button\"\n class=\"message__image-button\"\n (click)=\"openPreview(i, $event)\"\n [attr.aria-label]=\"'chat.photo_preview' | transloco\">\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\n </button>\n }\n </div>\n }\n\n <div class=\"message__bubble\" tabindex=\"0\">\n <div class=\"message__text\">{{ currentMessage().content }}</div>\n\n <div class=\"message__meta\">\n <time class=\"message__time\">\n {{ currentMessage().cr_time | date:'HH:mm' }}\n </time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().pending) {\n <span class=\"message__loading\" aria-label=\"Sending\"></span>\n } @else if (currentMessage().checked) {\n <img ngSrc=\"assets/ngx-parl/icons/checked-message.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\"/>\n } @else {\n <img ngSrc=\"assets/ngx-parl/icons/no-check.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\"/>\n }\n }\n </div>\n </div>\n </div>\n</div>\n<div class=\"message__user\">\n @if (currentMessage().type === messageType.Outgoing) {\n <span class=\"message__user-name\">{{ currentMessage().user }}</span>\n }\n</div>\n\n@if (previewList().length) {\n <lib-preview-file\n [srcList]=\"previewList()\"\n [startIndex]=\"previewIndex()\"\n [openerElement]=\"previewOpener()\"\n [closeHandler]=\"closePreviewHandler\">\n </lib-preview-file>\n}\n\n<mat-menu #messageMenu=\"matMenu\" yPosition=\"below\" xPosition=\"before\" class=\"message__menu\">\n @if (currentMessage().type === messageType.Outgoing) {\n <button mat-menu-item (click)=\"editMessage(currentMessage())\">\n <img ngSrc=\"assets/ngx-parl/icons/icon-edit.svg\"\n class=\"message__icon--menu\"\n width=\"20\" height=\"20\" alt=\"hide\"/>\n <span>{{ 'chat.edit' | transloco }}</span>\n </button>\n }\n @if (canDelete(currentMessage())) {\n <button mat-menu-item (click)=\"deleteMessage(currentMessage())\">\n <img ngSrc=\"assets/ngx-parl/icons/trash.svg\"\n class=\"message__icon--menu\"\n width=\"20\" height=\"20\" alt=\"hide\"/>\n <span>{{ 'chat.remove' | transloco }}</span>\n </button>\n }\n</mat-menu>\n", styles: [".flow-theme-primary ::ng-deep .modal-chat__header{background-color:#5a72d7;color:#fff}.flow-theme-primary ::ng-deep .message--incoming .message__body{background:#e9ecef;color:#343a40}.flow-theme-primary ::ng-deep .message--outgoing .message__body{background:#4656ca;color:#fff}:root{--shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, .05);--shadow-md: 0px 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0px 8px 24px rgba(0, 0, 0, .12);--shadow-soft: 0px 0px 6px 0px rgba(46, 46, 46, .12) }.flow-theme-secondary ::ng-deep .modal-chat__header{background-color:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--incoming .message__body{background:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--outgoing .message__body{background:#efefef;color:#464646}.message{display:flex;gap:8px;align-items:flex-end;max-width:80%;animation:pop .12s ease-out}.message__avatar img{display:block;border-radius:1000px}.message__body{padding:8px 12px;min-width:0;font:400 16px/20px inter,sans-serif;border-radius:16px;position:relative}.message__bubble{display:grid;grid-template-columns:1fr auto;column-gap:8px;align-items:end;max-width:100%;word-break:break-word;white-space:pre-wrap}.message__text{min-width:0}.message__meta{display:inline-flex;align-items:center;gap:4px;-webkit-user-select:none;user-select:none;line-height:1;margin:0}.message__time{font:400 12px/16px inter,sans-serif}.message__attachments{display:grid;gap:8px;justify-content:start;width:100%;margin-bottom:8px}.message__attachments:has(:only-child){grid-template-columns:repeat(1,minmax(0,140px))}.message__attachments:has(:nth-child(2):last-child){grid-template-columns:repeat(2,minmax(0,145px))}.message__attachments:has(:nth-child(3)){grid-template-columns:repeat(3,minmax(0,150px))}.message__body--attachments-1{max-width:164px}.message__body--attachments-2{max-width:312px}.message__body--attachments-3{max-width:460px}.message__body--attachments-1 .message__bubble,.message__body--attachments-2 .message__bubble,.message__body--attachments-3 .message__bubble{grid-template-columns:1fr;row-gap:4px}.message__body--attachments-1 .message__meta,.message__body--attachments-2 .message__meta,.message__body--attachments-3 .message__meta{justify-self:end}.message__image-button{display:block;border:none;padding:0;background:transparent;border-radius:12px;overflow:hidden;cursor:pointer}.message__image-button:focus-visible{outline:2px solid #5A72D7;outline-offset:4px}.message__menu-trigger{position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;pointer-events:none}.message__image{display:block;width:100%;height:140px;object-fit:cover;border-radius:12px;aspect-ratio:1/1}.message__bubble:after{content:\"\";display:block;clear:both}.message__time{font:400 12px/16px inter,sans-serif;min-width:30px}.message__icon{width:14px;height:14px;vertical-align:middle}.message__icon--menu{width:20px;height:20px}.message__loading{display:inline-block;width:10px;height:10px;border:2px solid #E9ECEF;border-top-color:#5a72d7;border-radius:50%;animation:message-loading-spin .8s linear infinite}.message--incoming{margin-right:auto}.message--incoming .message__body{border-bottom-right-radius:16px}.message--incoming .message__bubble{border-top-left-radius:4px}.message--incoming .message__time{color:#adb5bd}.message--outgoing{margin-left:auto;flex-direction:row-reverse}.message--outgoing .message__body{border-bottom-left-radius:16px}.message--outgoing .message__bubble{border-top-right-radius:4px}.message--outgoing .message__time{color:#e9ecef}.message--outgoing .message__menu-trigger{right:auto}.message__user{display:flex;justify-content:flex-end;max-width:80%;margin-left:auto;margin-top:4px;padding-right:46px}.message__user-name{font:400 12px/16px inter,sans-serif;color:#ced4da}@keyframes pop{0%{transform:translateY(2px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes message-loading-spin{to{transform:rotate(360deg)}}::ng-deep .mat-mdc-menu-content{background:#fff;width:160px;border-radius:8px;gap:4px;border:1px solid #E1E7F8;padding:8px 4px;box-shadow:0 2px 4px #0000001a;overflow:hidden;font:400 14px/18px inter,sans-serif}::ng-deep .mat-mdc-menu-item-text{font:400 14px/18px inter,sans-serif!important;font-weight:500!important;color:#343a40!important;display:flex;justify-content:flex-start;align-items:center;gap:4px}\n"] }]
382
- }], ctorParameters: () => [{ type: UtilsService }], propDecorators: { currentMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentMessage", required: true }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }, { type: i0.Output, args: ["editChange"] }], previewList: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewList", required: false }] }, { type: i0.Output, args: ["previewListChange"] }], previewIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewIndex", required: false }] }, { type: i0.Output, args: ["previewIndexChange"] }], previewOpener: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewOpener", required: false }] }, { type: i0.Output, args: ["previewOpenerChange"] }], requestEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestEdit", required: false }] }, { type: i0.Output, args: ["requestEditChange"] }], requestDelete: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestDelete", required: false }] }, { type: i0.Output, args: ["requestDeleteChange"] }] } });
418
+ IonButton,
419
+ ], standalone: true, template: "<div class=\"message\"\n [ngClass]=\"{\n 'message--outgoing': currentMessage().type === messageType.Outgoing,\n 'message--incoming': currentMessage().type === messageType.Incoming,\n 'message--mobile': mobileMode()\n }\">\n @if (showAvatar()) {\n <div class=\"message__avatar\">\n <img [ngSrc]=\"avatarSrc()\" width=\"36\" height=\"36\" alt=\"avatar\"/>\n </div>\n }\n\n @if (showMessageBody()) {\n <div class=\"message__body\"\n (contextmenu)=\"openContextMenu($event, menuTrigger, menuTriggerEl)\"\n (keydown.shift.F10)=\"openContextMenu($event, menuTrigger, menuTriggerEl)\">\n <button type=\"button\"\n class=\"message__menu-trigger\"\n aria-hidden=\"true\"\n tabindex=\"-1\"\n #menuTrigger=\"matMenuTrigger\"\n #menuTriggerEl\n [matMenuTriggerFor]=\"messageMenu\">\n </button>\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file; let i = $index) {\n <button type=\"button\"\n class=\"message__image-button\"\n (click)=\"openPreview(i, $event)\"\n [attr.aria-label]=\"'chat.photo_preview' | transloco\">\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\n </button>\n }\n </div>\n }\n\n @if (showMessageBubble()) {\n <div class=\"message__bubble\" tabindex=\"0\">\n <div class=\"message__text\">{{ currentMessage().content }}</div>\n\n <div class=\"message__meta\">\n <time class=\"message__time\">\n {{ currentMessage().cr_time | date:'HH:mm' }}\n </time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().pending) {\n <span class=\"message__loading\" aria-label=\"Sending\"></span>\n } @else if (currentMessage().checked) {\n <img ngSrc=\"assets/ngx-parl/icons/checked-message.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\"/>\n } @else {\n <img ngSrc=\"assets/ngx-parl/icons/no-check.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\"/>\n }\n }\n </div>\n </div>\n }\n\n </div>\n }\n\n @if (showQuickActions()) {\n <div class=\"message__quick-actions-wrap\" role=\"group\" aria-label=\"Quick actions\">\n <div class=\"message__quick-actions\">\n @for (action of quickActions(); track action.id) {\n <ion-button\n class=\"message__quick-action-button\"\n fill=\"outline\"\n expand=\"block\"\n [disabled]=\"action.disabled === true\"\n (click)=\"onQuickAction(action)\">\n {{ action.title }}\n </ion-button>\n }\n </div>\n </div>\n }\n</div>\n@if (!showQuickActions()) {\n <div class=\"message__user\" [ngClass]=\"{'message__user--mobile': mobileMode()}\">\n @if (currentMessage().type === messageType.Outgoing) {\n <span class=\"message__user-name\">{{ currentMessage().user }}</span>\n }\n </div>\n}\n\n@if (previewList().length) {\n <lib-preview-file\n [srcList]=\"previewList()\"\n [startIndex]=\"previewIndex()\"\n [openerElement]=\"previewOpener()\"\n [closeHandler]=\"closePreviewHandler\">\n </lib-preview-file>\n}\n\n<mat-menu #messageMenu=\"matMenu\" yPosition=\"below\" xPosition=\"before\" class=\"message__menu\">\n @if (currentMessage().type === messageType.Outgoing) {\n <button mat-menu-item (click)=\"editMessage(currentMessage())\">\n <img ngSrc=\"assets/ngx-parl/icons/icon-edit.svg\"\n class=\"message__icon--menu\"\n width=\"20\" height=\"20\" alt=\"hide\"/>\n <span>{{ 'chat.edit' | transloco }}</span>\n </button>\n }\n @if (canDelete(currentMessage())) {\n <button mat-menu-item (click)=\"deleteMessage(currentMessage())\">\n <img ngSrc=\"assets/ngx-parl/icons/trash.svg\"\n class=\"message__icon--menu\"\n width=\"20\" height=\"20\" alt=\"hide\"/>\n <span>{{ 'chat.remove' | transloco }}</span>\n </button>\n }\n</mat-menu>\n", styles: [".flow-theme-primary ::ng-deep .modal-chat__header{background-color:#5a72d7;color:#fff}.flow-theme-primary ::ng-deep .message--incoming .message__body{background:#e9ecef;color:#343a40}.flow-theme-primary ::ng-deep .message--outgoing .message__body{background:#4656ca;color:#fff}:root{--shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, .05);--shadow-md: 0px 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0px 8px 24px rgba(0, 0, 0, .12);--shadow-soft: 0px 0px 6px 0px rgba(46, 46, 46, .12) }.flow-theme-secondary ::ng-deep .modal-chat__header{background-color:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--incoming .message__body{background:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--outgoing .message__body{background:#efefef;color:#464646}.message{display:flex;gap:8px;align-items:flex-end;max-width:80%;animation:pop .12s ease-out}.message__avatar img{display:block;border-radius:1000px}.message__body{padding:8px 12px;min-width:0;font:400 16px/20px inter,sans-serif;border-radius:16px;position:relative}.message__bubble{display:grid;grid-template-columns:1fr auto;column-gap:8px;align-items:end;max-width:100%;word-break:break-word;white-space:pre-wrap}.message__quick-actions-wrap{display:flex;margin-top:12px;width:100%;background:transparent}.message__quick-actions{display:grid;gap:8px;width:234px;max-width:100%;background:transparent}.message__quick-action-button{--border-radius: 16px;--border-width: 1px;--border-style: solid;--border-color: #2563EB;--color: #2563EB;--padding-top: tokens.$space-3;--padding-bottom: tokens.$space-3;--padding-start: tokens.$space-6;--padding-end: tokens.$space-6;height:48px;text-transform:none;font:500 14px/18px inter,sans-serif;margin:0}.message__text{min-width:0}.message__meta{display:inline-flex;align-items:center;gap:4px;-webkit-user-select:none;user-select:none;line-height:1;margin:0}.message__time{font:400 12px/16px inter,sans-serif}.message__attachments{display:grid;gap:8px;justify-content:start;width:100%;margin-bottom:8px}.message__attachments:has(:only-child){grid-template-columns:repeat(1,minmax(0,140px))}.message__attachments:has(:nth-child(2):last-child){grid-template-columns:repeat(2,minmax(0,145px))}.message__attachments:has(:nth-child(3)){grid-template-columns:repeat(3,minmax(0,150px))}.message__body--attachments-1{max-width:164px}.message__body--attachments-2{max-width:312px}.message__body--attachments-3{max-width:460px}.message__body--attachments-1 .message__bubble,.message__body--attachments-2 .message__bubble,.message__body--attachments-3 .message__bubble{grid-template-columns:1fr;row-gap:4px}.message__body--attachments-1 .message__meta,.message__body--attachments-2 .message__meta,.message__body--attachments-3 .message__meta{justify-self:end}.message__image-button{display:block;border:none;padding:0;background:transparent;border-radius:12px;overflow:hidden;cursor:pointer}.message__image-button:focus-visible{outline:2px solid #5A72D7;outline-offset:4px}.message__menu-trigger{position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;pointer-events:none}.message__image{display:block;width:100%;height:140px;object-fit:cover;border-radius:12px;aspect-ratio:1/1}.message__bubble:after{content:\"\";display:block;clear:both}.message__time{font:400 12px/16px inter,sans-serif;min-width:30px}.message__icon{width:14px;height:14px;vertical-align:middle}.message__icon--menu{width:20px;height:20px}.message__loading{display:inline-block;width:10px;height:10px;border:2px solid #E9ECEF;border-top-color:#5a72d7;border-radius:50%;animation:message-loading-spin .8s linear infinite}.message--incoming{margin-right:auto}.message--incoming .message__body{border-bottom-right-radius:16px}.message--incoming .message__bubble{border-top-left-radius:4px}.message--incoming .message__time{color:#adb5bd}.message--incoming .message__quick-actions-wrap{justify-content:flex-start}.message--outgoing{margin-left:auto;flex-direction:row-reverse}.message--outgoing .message__body{border-bottom-right-radius:0}.message--outgoing .message__bubble{border-top-right-radius:4px}.message--outgoing .message__time{color:#e9ecef}.message--outgoing .message__menu-trigger{right:auto}.message--outgoing .message__quick-actions-wrap{justify-content:flex-end}.message--mobile .message__user{padding-right:5px!important}.message--mobile.message--outgoing .message__body{border-bottom-right-radius:0}.message__user{display:flex;justify-content:flex-end;max-width:80%;margin-left:auto;margin-top:4px;padding-right:46px}.message__user--mobile{padding-right:5px!important}.message__user-name{font:400 12px/16px inter,sans-serif;color:#ced4da}@keyframes pop{0%{transform:translateY(2px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes message-loading-spin{to{transform:rotate(360deg)}}::ng-deep .mat-mdc-menu-content{background:#fff;width:160px;border-radius:8px;gap:4px;border:1px solid #E1E7F8;padding:8px 4px;box-shadow:0 2px 4px #0000001a;overflow:hidden;font:400 14px/18px inter,sans-serif}::ng-deep .mat-mdc-menu-item-text{font:400 14px/18px inter,sans-serif!important;font-weight:500!important;color:#343a40!important;display:flex;justify-content:flex-start;align-items:center;gap:4px}\n"] }]
420
+ }], ctorParameters: () => [{ type: UtilsService }], propDecorators: { currentMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentMessage", required: true }] }], edit: [{ type: i0.Input, args: [{ isSignal: true, alias: "edit", required: false }] }, { type: i0.Output, args: ["editChange"] }], previewList: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewList", required: false }] }, { type: i0.Output, args: ["previewListChange"] }], previewIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewIndex", required: false }] }, { type: i0.Output, args: ["previewIndexChange"] }], previewOpener: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewOpener", required: false }] }, { type: i0.Output, args: ["previewOpenerChange"] }], requestEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestEdit", required: false }] }, { type: i0.Output, args: ["requestEditChange"] }], requestDelete: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestDelete", required: false }] }, { type: i0.Output, args: ["requestDeleteChange"] }], mobileMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileMode", required: false }] }], quickActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickActions", required: false }] }], quickActionClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickActionClick", required: false }] }, { type: i0.Output, args: ["quickActionClickChange"] }] } });
383
421
 
384
422
  class ToggleDisplayChatStartDayPipe {
385
423
  utils;
@@ -438,12 +476,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
438
476
 
439
477
  class ChatFlowComponent {
440
478
  flowRef;
479
+ transloco = inject(TranslocoService);
480
+ translocoLang = toSignal(this.transloco.langChanges$, {
481
+ initialValue: this.transloco.getActiveLang(),
482
+ });
441
483
  scrollToBottomTrigger = model(0, ...(ngDevMode ? [{ debugName: "scrollToBottomTrigger" }] : []));
442
484
  loadHistory = model(false, ...(ngDevMode ? [{ debugName: "loadHistory" }] : []));
443
485
  messageListInput = model.required(...(ngDevMode ? [{ debugName: "messageListInput" }] : []));
444
486
  messageList = computed(() => this.messageListInput(), ...(ngDevMode ? [{ debugName: "messageList" }] : []));
445
487
  selectedForEdit = model.required(...(ngDevMode ? [{ debugName: "selectedForEdit" }] : []));
446
488
  requestDelete = model(null, ...(ngDevMode ? [{ debugName: "requestDelete" }] : []));
489
+ mobileMode = input(false, ...(ngDevMode ? [{ debugName: "mobileMode" }] : []));
490
+ quickActionsResolver = input(null, ...(ngDevMode ? [{ debugName: "quickActionsResolver" }] : []));
491
+ quickActionClick = model(null, ...(ngDevMode ? [{ debugName: "quickActionClick" }] : []));
492
+ deleteConfirmOpen = signal(false, ...(ngDevMode ? [{ debugName: "deleteConfirmOpen" }] : []));
493
+ pendingDeleteMessageId = signal(null, ...(ngDevMode ? [{ debugName: "pendingDeleteMessageId" }] : []));
494
+ deleteAlertButtons = computed(() => {
495
+ this.translocoLang();
496
+ return [
497
+ {
498
+ text: this.transloco.translate('chat.cancel'),
499
+ role: 'cancel',
500
+ handler: () => this.closeDeleteConfirm(),
501
+ },
502
+ {
503
+ text: this.transloco.translate('chat.remove'),
504
+ role: 'destructive',
505
+ cssClass: 'chat__delete-alert-destructive',
506
+ handler: () => this.confirmDelete(),
507
+ },
508
+ ];
509
+ }, ...(ngDevMode ? [{ debugName: "deleteAlertButtons" }] : []));
510
+ quickActionsByMessageId = computed(() => {
511
+ const messages = this.messageList();
512
+ const resolver = this.quickActionsResolver();
513
+ const isMobile = this.mobileMode();
514
+ const map = new Map();
515
+ if (!resolver || !isMobile) {
516
+ return map;
517
+ }
518
+ for (const message of messages) {
519
+ const actions = resolver({ message, isMobile });
520
+ if (Array.isArray(actions) && actions.length) {
521
+ map.set(message.id, actions);
522
+ }
523
+ }
524
+ return map;
525
+ }, ...(ngDevMode ? [{ debugName: "quickActionsByMessageId" }] : []));
447
526
  viewInitialized = false;
448
527
  previousMessageCount = 0;
449
528
  previousFirstMessageId = null;
@@ -625,6 +704,26 @@ class ChatFlowComponent {
625
704
  return this;
626
705
  }
627
706
  this.selectedForEdit.set(null);
707
+ if (!this.mobileMode()) {
708
+ this.requestDelete.set(messageId);
709
+ queueMicrotask(() => this.requestDelete.set(null));
710
+ return this;
711
+ }
712
+ this.pendingDeleteMessageId.set(messageId);
713
+ this.deleteConfirmOpen.set(true);
714
+ return this;
715
+ }
716
+ closeDeleteConfirm() {
717
+ this.deleteConfirmOpen.set(false);
718
+ this.pendingDeleteMessageId.set(null);
719
+ return this;
720
+ }
721
+ confirmDelete() {
722
+ const messageId = this.pendingDeleteMessageId();
723
+ if (messageId == null) {
724
+ return this.closeDeleteConfirm();
725
+ }
726
+ this.closeDeleteConfirm();
628
727
  this.requestDelete.set(messageId);
629
728
  queueMicrotask(() => this.requestDelete.set(null));
630
729
  return this;
@@ -634,7 +733,7 @@ class ChatFlowComponent {
634
733
  }
635
734
  Math = Math;
636
735
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ChatFlowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
637
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ChatFlowComponent, isStandalone: true, selector: "app-chat-flow", inputs: { scrollToBottomTrigger: { classPropertyName: "scrollToBottomTrigger", publicName: "scrollToBottomTrigger", isSignal: true, isRequired: false, transformFunction: null }, loadHistory: { classPropertyName: "loadHistory", publicName: "loadHistory", isSignal: true, isRequired: false, transformFunction: null }, messageListInput: { classPropertyName: "messageListInput", publicName: "messageListInput", isSignal: true, isRequired: true, transformFunction: null }, selectedForEdit: { classPropertyName: "selectedForEdit", publicName: "selectedForEdit", isSignal: true, isRequired: true, transformFunction: null }, requestDelete: { classPropertyName: "requestDelete", publicName: "requestDelete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scrollToBottomTrigger: "scrollToBottomTriggerChange", loadHistory: "loadHistoryChange", messageListInput: "messageListInputChange", selectedForEdit: "selectedForEditChange", requestDelete: "requestDeleteChange" }, viewQueries: [{ propertyName: "flowRef", first: true, predicate: ["chatFlowRef"], descendants: true }], ngImport: i0, template: "<div class=\"chat\">\n @if (messageList()) {\n <div #chatFlowRef\n class=\"chat__flow\"\n infiniteScroll\n [scrollWindow]=\"false\"\n [infiniteScrollUpDistance]=\"Math.max(historyLoadThreshold(), 2)\"\n [infiniteScrollThrottle]=\"100\"\n (scrolledUp)=\"onScrollUp()\"\n >\n @for (message of messageList(); track trackByMessageId(i, message); let i = $index) {\n @if (message | toggleDisplayChatStartDay: messageList() : i) {\n <span class=\"chat__start-day\">\n {{ message.cr_time | chatStartDay:'d MMMM' }}\n </span>\n }\n\n <div class=\"chat__message\" [attr.data-message-id]=\"message.id\">\n <lib-chat-message\n [currentMessage]=\"message\"\n [edit]=\"message.edit\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n </div>\n }\n </div>\n\n @if (showScrollToBottom()) {\n <button class=\"chat__scroll-button\"\n type=\"button\"\n (click)=\"scrollToBottomSmooth()\"\n aria-label=\"Scroll to bottom\">\n <img ngSrc=\"assets/ngx-parl/icons/bottom-scroll.svg\"\n alt=\"\"\n width=\"14\"\n height=\"14\"/>\n </button>\n }\n } @else {\n <div class=\"chat__flow__empty\">\n <img ngSrc=\"assets/ngx-parl/icons/lucide_send.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"24\" alt=\"hide\"/>\n\n\n <div class=\"chat__flow__empty--header\">\n <h3 class=\"chat__flow__empty--title\">{{ 'chat.chat_empty_title' | transloco }}</h3>\n <p class=\"chat__flow__empty--subscription\">{{ 'chat.chat_empty_subscription' | transloco }}</p>\n </div>\n </div>\n }\n</div>\n\n", styles: [":host{display:block;height:100%;min-height:0}.chat{background:#fff;height:100%;display:flex;flex-direction:column;min-height:0;width:100%;position:relative}.chat__flow{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px;overscroll-behavior:contain}.chat__flow__empty{display:flex;gap:16px;flex-direction:column;align-items:center;justify-content:center;padding:72px 16px;height:100%}.chat__flow__empty .message__icon{width:56px;height:56px}.chat__flow__empty--header{width:285px;display:flex;gap:12px;flex-direction:column;align-items:center}.chat__flow__empty--title{margin:0;font:600 16px/20px inter,sans-serif;color:#212529}.chat__flow__empty--subscription{margin:0;font:400 16px/20px inter,sans-serif;color:#495057}.chat__start-day{display:flex;justify-content:center;background:#f8f9fa;color:#6c757d;font:400 12px/16px inter,sans-serif;width:80px;height:22px;margin:0 auto;border-radius:1000px;gap:8px;padding:4px 8px}.chat__scroll-button{position:absolute;right:8px;bottom:8px;width:35px;height:35px;display:inline-flex;align-items:center;justify-content:center;padding:8px;border:none;border-radius:1000px;background:#c9d4f4;box-shadow:0 2px 4px #0000001a;opacity:.6;cursor:pointer;transition:background-color .15s ease,opacity .15s ease}.chat__scroll-button:hover,.chat__scroll-button:focus-visible{background:#dee2e6;opacity:1}.chat__scroll-button img{display:block}.chat ::-webkit-scrollbar{width:6px}.chat ::-webkit-scrollbar-track{background:transparent}.chat ::-webkit-scrollbar-thumb{background-color:#e9ecef;border-radius:4px;border:1px solid #E9ECEF}.chat ::-webkit-scrollbar-button{display:none}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: ChatMessageComponent, selector: "lib-chat-message", inputs: ["currentMessage", "edit", "previewList", "previewIndex", "previewOpener", "requestEdit", "requestDelete"], outputs: ["editChange", "previewListChange", "previewIndexChange", "previewOpenerChange", "requestEditChange", "requestDeleteChange"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: ToggleDisplayChatStartDayPipe, name: "toggleDisplayChatStartDay" }, { kind: "pipe", type: ChatStartDayPipe, name: "chatStartDay" }] });
736
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ChatFlowComponent, isStandalone: true, selector: "app-chat-flow", inputs: { scrollToBottomTrigger: { classPropertyName: "scrollToBottomTrigger", publicName: "scrollToBottomTrigger", isSignal: true, isRequired: false, transformFunction: null }, loadHistory: { classPropertyName: "loadHistory", publicName: "loadHistory", isSignal: true, isRequired: false, transformFunction: null }, messageListInput: { classPropertyName: "messageListInput", publicName: "messageListInput", isSignal: true, isRequired: true, transformFunction: null }, selectedForEdit: { classPropertyName: "selectedForEdit", publicName: "selectedForEdit", isSignal: true, isRequired: true, transformFunction: null }, requestDelete: { classPropertyName: "requestDelete", publicName: "requestDelete", isSignal: true, isRequired: false, transformFunction: null }, mobileMode: { classPropertyName: "mobileMode", publicName: "mobileMode", isSignal: true, isRequired: false, transformFunction: null }, quickActionsResolver: { classPropertyName: "quickActionsResolver", publicName: "quickActionsResolver", isSignal: true, isRequired: false, transformFunction: null }, quickActionClick: { classPropertyName: "quickActionClick", publicName: "quickActionClick", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scrollToBottomTrigger: "scrollToBottomTriggerChange", loadHistory: "loadHistoryChange", messageListInput: "messageListInputChange", selectedForEdit: "selectedForEditChange", requestDelete: "requestDeleteChange", quickActionClick: "quickActionClickChange" }, viewQueries: [{ propertyName: "flowRef", first: true, predicate: ["chatFlowRef"], descendants: true }], ngImport: i0, template: "<div class=\"chat\">\n @if (messageList()) {\n <div #chatFlowRef\n class=\"chat__flow\"\n infiniteScroll\n [scrollWindow]=\"false\"\n [infiniteScrollUpDistance]=\"Math.max(historyLoadThreshold(), 2)\"\n [infiniteScrollThrottle]=\"100\"\n (scrolledUp)=\"onScrollUp()\"\n >\n <div class=\"chat__manager-header\" aria-hidden=\"true\">\n <div class=\"chat__manager-icon\">\n <img ngSrc=\"assets/ngx-parl/icons/avatar_manager.svg\"\n alt=\"manager\"\n width=\"72\"\n height=\"72\"/>\n </div>\n </div>\n\n @for (message of messageList(); track trackByMessageId(i, message); let i = $index) {\n @if (message | toggleDisplayChatStartDay: messageList() : i) {\n <span class=\"chat__start-day\">\n {{ message.cr_time | chatStartDay:'d MMMM' }}\n </span>\n }\n\n <div class=\"chat__message\" [attr.data-message-id]=\"message.id\">\n <lib-chat-message\n [currentMessage]=\"message\"\n [edit]=\"message.edit\"\n [mobileMode]=\"mobileMode()\"\n [quickActions]=\"quickActionsByMessageId().get(message.id) ?? []\"\n [(quickActionClick)]=\"quickActionClick\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n </div>\n }\n </div>\n\n @if (mobileMode()) {\n <ion-alert mode=\"md\"\n [header]=\"'chat.delete_message_title' | transloco\"\n cssClass=\"chat__delete-alert\"\n [isOpen]=\"deleteConfirmOpen()\"\n [buttons]=\"deleteAlertButtons()\"\n (didDismiss)=\"closeDeleteConfirm()\"\n [backdropDismiss]=\"false\">\n </ion-alert>\n }\n\n @if (showScrollToBottom()) {\n <button class=\"chat__scroll-button\"\n type=\"button\"\n (click)=\"scrollToBottomSmooth()\"\n aria-label=\"Scroll to bottom\">\n <img ngSrc=\"assets/ngx-parl/icons/bottom-scroll.svg\"\n alt=\"\"\n width=\"14\"\n height=\"14\"/>\n </button>\n }\n } @else {\n <div class=\"chat__flow__empty\">\n <img ngSrc=\"assets/ngx-parl/icons/lucide_send.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"24\" alt=\"hide\"/>\n\n\n <div class=\"chat__flow__empty--header\">\n <h3 class=\"chat__flow__empty--title\">{{ 'chat.chat_empty_title' | transloco }}</h3>\n <p class=\"chat__flow__empty--subscription\">{{ 'chat.chat_empty_subscription' | transloco }}</p>\n </div>\n </div>\n }\n</div>\n\n", styles: [":host{display:block;height:100%;min-height:0}.chat{background:#fff;height:100%;display:flex;flex-direction:column;min-height:0;width:100%;position:relative}.chat__flow{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px;overscroll-behavior:contain}.chat__flow__empty{display:flex;gap:16px;flex-direction:column;align-items:center;justify-content:center;padding:72px 16px;height:100%}.chat__flow__empty .message__icon{width:56px;height:56px}.chat__flow__empty--header{width:285px;display:flex;gap:12px;flex-direction:column;align-items:center}.chat__flow__empty--title{margin:0;font:600 16px/20px inter,sans-serif;color:#212529}.chat__flow__empty--subscription{margin:0;font:400 16px/20px inter,sans-serif;color:#495057}.chat__manager-header{display:flex;justify-content:center;padding:24px 16px 8px}.chat__manager-icon{width:132px;height:132px;border-radius:1000px;display:grid;place-items:center}.chat__manager-icon img{display:block;border-radius:1000px}.chat__start-day{display:flex;justify-content:center;background:#f8f9fa;color:#6c757d;font:400 12px/16px inter,sans-serif;width:92px;height:22px;margin:0 auto;border-radius:1000px;gap:8px;padding:4px 8px}.chat__scroll-button{position:absolute;right:8px;bottom:8px;width:35px;height:35px;display:inline-flex;align-items:center;justify-content:center;padding:8px;border:none;border-radius:1000px;background:#c9d4f4;box-shadow:0 2px 4px #0000001a;opacity:.6;cursor:pointer;transition:background-color .15s ease,opacity .15s ease}.chat__scroll-button:hover,.chat__scroll-button:focus-visible{background:#dee2e6;opacity:1}.chat__scroll-button img{display:block}.chat ::-webkit-scrollbar{width:6px}.chat ::-webkit-scrollbar-track{background:transparent}.chat ::-webkit-scrollbar-thumb{background-color:#e9ecef;border-radius:4px;border:1px solid #E9ECEF}.chat ::-webkit-scrollbar-button{display:none}.chat__delete-alert{--background: #ffffff;--backdrop-opacity: .32;--max-width: 520px}.chat__delete-alert .alert-wrapper{border-radius:16px;box-shadow:0 10px 30px #00000026}.chat__delete-alert .alert-head{padding-top:18px}.chat__delete-alert .alert-title{color:#0f172a;font-weight:500}.chat__delete-alert .alert-button-group{padding:8px 12px 12px}.chat__delete-alert .alert-button{color:#2563eb;font-weight:500}.chat__delete-alert .alert-button-role-destructive,.chat__delete-alert .alert-button-role-destructive .alert-button-inner{color:#dc2626!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: ChatMessageComponent, selector: "lib-chat-message", inputs: ["currentMessage", "edit", "previewList", "previewIndex", "previewOpener", "requestEdit", "requestDelete", "mobileMode", "quickActions", "quickActionClick"], outputs: ["editChange", "previewListChange", "previewIndexChange", "previewOpenerChange", "requestEditChange", "requestDeleteChange", "quickActionClickChange"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "component", type: IonAlert, selector: "ion-alert", inputs: ["animated", "backdropDismiss", "buttons", "cssClass", "enterAnimation", "header", "htmlAttributes", "inputs", "isOpen", "keyboardClose", "leaveAnimation", "message", "mode", "subHeader", "translucent", "trigger"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }, { kind: "pipe", type: ToggleDisplayChatStartDayPipe, name: "toggleDisplayChatStartDay" }, { kind: "pipe", type: ChatStartDayPipe, name: "chatStartDay" }], encapsulation: i0.ViewEncapsulation.None });
638
737
  }
639
738
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ChatFlowComponent, decorators: [{
640
739
  type: Component,
@@ -645,12 +744,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
645
744
  NgOptimizedImage,
646
745
  InfiniteScrollDirective,
647
746
  ToggleDisplayChatStartDayPipe,
648
- ChatStartDayPipe
649
- ], standalone: true, template: "<div class=\"chat\">\n @if (messageList()) {\n <div #chatFlowRef\n class=\"chat__flow\"\n infiniteScroll\n [scrollWindow]=\"false\"\n [infiniteScrollUpDistance]=\"Math.max(historyLoadThreshold(), 2)\"\n [infiniteScrollThrottle]=\"100\"\n (scrolledUp)=\"onScrollUp()\"\n >\n @for (message of messageList(); track trackByMessageId(i, message); let i = $index) {\n @if (message | toggleDisplayChatStartDay: messageList() : i) {\n <span class=\"chat__start-day\">\n {{ message.cr_time | chatStartDay:'d MMMM' }}\n </span>\n }\n\n <div class=\"chat__message\" [attr.data-message-id]=\"message.id\">\n <lib-chat-message\n [currentMessage]=\"message\"\n [edit]=\"message.edit\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n </div>\n }\n </div>\n\n @if (showScrollToBottom()) {\n <button class=\"chat__scroll-button\"\n type=\"button\"\n (click)=\"scrollToBottomSmooth()\"\n aria-label=\"Scroll to bottom\">\n <img ngSrc=\"assets/ngx-parl/icons/bottom-scroll.svg\"\n alt=\"\"\n width=\"14\"\n height=\"14\"/>\n </button>\n }\n } @else {\n <div class=\"chat__flow__empty\">\n <img ngSrc=\"assets/ngx-parl/icons/lucide_send.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"24\" alt=\"hide\"/>\n\n\n <div class=\"chat__flow__empty--header\">\n <h3 class=\"chat__flow__empty--title\">{{ 'chat.chat_empty_title' | transloco }}</h3>\n <p class=\"chat__flow__empty--subscription\">{{ 'chat.chat_empty_subscription' | transloco }}</p>\n </div>\n </div>\n }\n</div>\n\n", styles: [":host{display:block;height:100%;min-height:0}.chat{background:#fff;height:100%;display:flex;flex-direction:column;min-height:0;width:100%;position:relative}.chat__flow{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px;overscroll-behavior:contain}.chat__flow__empty{display:flex;gap:16px;flex-direction:column;align-items:center;justify-content:center;padding:72px 16px;height:100%}.chat__flow__empty .message__icon{width:56px;height:56px}.chat__flow__empty--header{width:285px;display:flex;gap:12px;flex-direction:column;align-items:center}.chat__flow__empty--title{margin:0;font:600 16px/20px inter,sans-serif;color:#212529}.chat__flow__empty--subscription{margin:0;font:400 16px/20px inter,sans-serif;color:#495057}.chat__start-day{display:flex;justify-content:center;background:#f8f9fa;color:#6c757d;font:400 12px/16px inter,sans-serif;width:80px;height:22px;margin:0 auto;border-radius:1000px;gap:8px;padding:4px 8px}.chat__scroll-button{position:absolute;right:8px;bottom:8px;width:35px;height:35px;display:inline-flex;align-items:center;justify-content:center;padding:8px;border:none;border-radius:1000px;background:#c9d4f4;box-shadow:0 2px 4px #0000001a;opacity:.6;cursor:pointer;transition:background-color .15s ease,opacity .15s ease}.chat__scroll-button:hover,.chat__scroll-button:focus-visible{background:#dee2e6;opacity:1}.chat__scroll-button img{display:block}.chat ::-webkit-scrollbar{width:6px}.chat ::-webkit-scrollbar-track{background:transparent}.chat ::-webkit-scrollbar-thumb{background-color:#e9ecef;border-radius:4px;border:1px solid #E9ECEF}.chat ::-webkit-scrollbar-button{display:none}\n"] }]
747
+ ChatStartDayPipe,
748
+ IonAlert,
749
+ ], standalone: true, encapsulation: ViewEncapsulation.None, template: "<div class=\"chat\">\n @if (messageList()) {\n <div #chatFlowRef\n class=\"chat__flow\"\n infiniteScroll\n [scrollWindow]=\"false\"\n [infiniteScrollUpDistance]=\"Math.max(historyLoadThreshold(), 2)\"\n [infiniteScrollThrottle]=\"100\"\n (scrolledUp)=\"onScrollUp()\"\n >\n <div class=\"chat__manager-header\" aria-hidden=\"true\">\n <div class=\"chat__manager-icon\">\n <img ngSrc=\"assets/ngx-parl/icons/avatar_manager.svg\"\n alt=\"manager\"\n width=\"72\"\n height=\"72\"/>\n </div>\n </div>\n\n @for (message of messageList(); track trackByMessageId(i, message); let i = $index) {\n @if (message | toggleDisplayChatStartDay: messageList() : i) {\n <span class=\"chat__start-day\">\n {{ message.cr_time | chatStartDay:'d MMMM' }}\n </span>\n }\n\n <div class=\"chat__message\" [attr.data-message-id]=\"message.id\">\n <lib-chat-message\n [currentMessage]=\"message\"\n [edit]=\"message.edit\"\n [mobileMode]=\"mobileMode()\"\n [quickActions]=\"quickActionsByMessageId().get(message.id) ?? []\"\n [(quickActionClick)]=\"quickActionClick\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n </div>\n }\n </div>\n\n @if (mobileMode()) {\n <ion-alert mode=\"md\"\n [header]=\"'chat.delete_message_title' | transloco\"\n cssClass=\"chat__delete-alert\"\n [isOpen]=\"deleteConfirmOpen()\"\n [buttons]=\"deleteAlertButtons()\"\n (didDismiss)=\"closeDeleteConfirm()\"\n [backdropDismiss]=\"false\">\n </ion-alert>\n }\n\n @if (showScrollToBottom()) {\n <button class=\"chat__scroll-button\"\n type=\"button\"\n (click)=\"scrollToBottomSmooth()\"\n aria-label=\"Scroll to bottom\">\n <img ngSrc=\"assets/ngx-parl/icons/bottom-scroll.svg\"\n alt=\"\"\n width=\"14\"\n height=\"14\"/>\n </button>\n }\n } @else {\n <div class=\"chat__flow__empty\">\n <img ngSrc=\"assets/ngx-parl/icons/lucide_send.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"24\" alt=\"hide\"/>\n\n\n <div class=\"chat__flow__empty--header\">\n <h3 class=\"chat__flow__empty--title\">{{ 'chat.chat_empty_title' | transloco }}</h3>\n <p class=\"chat__flow__empty--subscription\">{{ 'chat.chat_empty_subscription' | transloco }}</p>\n </div>\n </div>\n }\n</div>\n\n", styles: [":host{display:block;height:100%;min-height:0}.chat{background:#fff;height:100%;display:flex;flex-direction:column;min-height:0;width:100%;position:relative}.chat__flow{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px;overscroll-behavior:contain}.chat__flow__empty{display:flex;gap:16px;flex-direction:column;align-items:center;justify-content:center;padding:72px 16px;height:100%}.chat__flow__empty .message__icon{width:56px;height:56px}.chat__flow__empty--header{width:285px;display:flex;gap:12px;flex-direction:column;align-items:center}.chat__flow__empty--title{margin:0;font:600 16px/20px inter,sans-serif;color:#212529}.chat__flow__empty--subscription{margin:0;font:400 16px/20px inter,sans-serif;color:#495057}.chat__manager-header{display:flex;justify-content:center;padding:24px 16px 8px}.chat__manager-icon{width:132px;height:132px;border-radius:1000px;display:grid;place-items:center}.chat__manager-icon img{display:block;border-radius:1000px}.chat__start-day{display:flex;justify-content:center;background:#f8f9fa;color:#6c757d;font:400 12px/16px inter,sans-serif;width:92px;height:22px;margin:0 auto;border-radius:1000px;gap:8px;padding:4px 8px}.chat__scroll-button{position:absolute;right:8px;bottom:8px;width:35px;height:35px;display:inline-flex;align-items:center;justify-content:center;padding:8px;border:none;border-radius:1000px;background:#c9d4f4;box-shadow:0 2px 4px #0000001a;opacity:.6;cursor:pointer;transition:background-color .15s ease,opacity .15s ease}.chat__scroll-button:hover,.chat__scroll-button:focus-visible{background:#dee2e6;opacity:1}.chat__scroll-button img{display:block}.chat ::-webkit-scrollbar{width:6px}.chat ::-webkit-scrollbar-track{background:transparent}.chat ::-webkit-scrollbar-thumb{background-color:#e9ecef;border-radius:4px;border:1px solid #E9ECEF}.chat ::-webkit-scrollbar-button{display:none}.chat__delete-alert{--background: #ffffff;--backdrop-opacity: .32;--max-width: 520px}.chat__delete-alert .alert-wrapper{border-radius:16px;box-shadow:0 10px 30px #00000026}.chat__delete-alert .alert-head{padding-top:18px}.chat__delete-alert .alert-title{color:#0f172a;font-weight:500}.chat__delete-alert .alert-button-group{padding:8px 12px 12px}.chat__delete-alert .alert-button{color:#2563eb;font-weight:500}.chat__delete-alert .alert-button-role-destructive,.chat__delete-alert .alert-button-role-destructive .alert-button-inner{color:#dc2626!important}\n"] }]
650
750
  }], ctorParameters: () => [], propDecorators: { flowRef: [{
651
751
  type: ViewChild,
652
752
  args: ['chatFlowRef']
653
- }], scrollToBottomTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollToBottomTrigger", required: false }] }, { type: i0.Output, args: ["scrollToBottomTriggerChange"] }], loadHistory: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadHistory", required: false }] }, { type: i0.Output, args: ["loadHistoryChange"] }], messageListInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageListInput", required: true }] }, { type: i0.Output, args: ["messageListInputChange"] }], selectedForEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedForEdit", required: true }] }, { type: i0.Output, args: ["selectedForEditChange"] }], requestDelete: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestDelete", required: false }] }, { type: i0.Output, args: ["requestDeleteChange"] }] } });
753
+ }], scrollToBottomTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollToBottomTrigger", required: false }] }, { type: i0.Output, args: ["scrollToBottomTriggerChange"] }], loadHistory: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadHistory", required: false }] }, { type: i0.Output, args: ["loadHistoryChange"] }], messageListInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageListInput", required: true }] }, { type: i0.Output, args: ["messageListInputChange"] }], selectedForEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedForEdit", required: true }] }, { type: i0.Output, args: ["selectedForEditChange"] }], requestDelete: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestDelete", required: false }] }, { type: i0.Output, args: ["requestDeleteChange"] }], mobileMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileMode", required: false }] }], quickActionsResolver: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickActionsResolver", required: false }] }], quickActionClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickActionClick", required: false }] }, { type: i0.Output, args: ["quickActionClickChange"] }] } });
654
754
 
655
755
  class ImageFile {
656
756
  id;
@@ -1064,6 +1164,10 @@ class NgxParlComponent {
1064
1164
  transportType = input('', ...(ngDevMode ? [{ debugName: "transportType" }] : []));
1065
1165
  transportTypeIcon = input('', ...(ngDevMode ? [{ debugName: "transportTypeIcon" }] : []));
1066
1166
  transportTypeIconSrc = computed(() => this.utils.normalizeSourcePath(this.transportTypeIcon()), ...(ngDevMode ? [{ debugName: "transportTypeIconSrc" }] : []));
1167
+ mobileMode = input(false, ...(ngDevMode ? [{ debugName: "mobileMode" }] : []));
1168
+ quickActionsResolver = input(null, ...(ngDevMode ? [{ debugName: "quickActionsResolver" }] : []));
1169
+ quickActionClick = model(null, ...(ngDevMode ? [{ debugName: "quickActionClick" }] : []));
1170
+ quickActionsAutoSend = input(true, ...(ngDevMode ? [{ debugName: "quickActionsAutoSend" }] : []));
1067
1171
  hideHandler = input(null, ...(ngDevMode ? [{ debugName: "hideHandler" }] : []));
1068
1172
  closeHandler = input(null, ...(ngDevMode ? [{ debugName: "closeHandler" }] : []));
1069
1173
  scrollToBottomTrigger = model(0, ...(ngDevMode ? [{ debugName: "scrollToBottomTrigger" }] : []));
@@ -1098,6 +1202,24 @@ class NgxParlComponent {
1098
1202
  });
1099
1203
  this.scrollToBottom();
1100
1204
  });
1205
+ effect(() => {
1206
+ const event = this.quickActionClick();
1207
+ if (!event || !this.quickActionsAutoSend()) {
1208
+ return;
1209
+ }
1210
+ const content = (event.value ?? '').trim();
1211
+ if (!content) {
1212
+ return;
1213
+ }
1214
+ setTimeout(() => {
1215
+ try {
1216
+ this.sendMessage({ content });
1217
+ }
1218
+ catch (error) {
1219
+ console.error('Quick action send failed', error);
1220
+ }
1221
+ }, 0);
1222
+ });
1101
1223
  }
1102
1224
  ngAfterViewInit() {
1103
1225
  if (this.dialogRef) {
@@ -1230,6 +1352,7 @@ class NgxParlComponent {
1230
1352
  file_list: [],
1231
1353
  checked: true,
1232
1354
  pending: true,
1355
+ actions: [],
1233
1356
  };
1234
1357
  this.messageList.update((list) => [...list, new ChatMessage(dto)]);
1235
1358
  this.scrollToBottomTrigger.update(v => v + 1);
@@ -1277,6 +1400,7 @@ class NgxParlComponent {
1277
1400
  file_list: hasFileList ? file_list : [],
1278
1401
  checked: true,
1279
1402
  pending: true,
1403
+ actions: [],
1280
1404
  };
1281
1405
  this.messageList.update((list) => [...list, new ChatMessage(dto)]);
1282
1406
  this.scrollToBottomTrigger.update(v => v + 1);
@@ -1358,7 +1482,7 @@ class NgxParlComponent {
1358
1482
  }
1359
1483
  FlowTheme = FlowTheme;
1360
1484
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NgxParlComponent, deps: [{ token: UtilsService }, { token: i2.TranslocoService }, { token: i3.MatDialogRef, optional: true }], target: i0.ɵɵFactoryTarget.Component });
1361
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: NgxParlComponent, isStandalone: true, selector: "ngx-parl", inputs: { dragActive: { classPropertyName: "dragActive", publicName: "dragActive", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, messageList: { classPropertyName: "messageList", publicName: "messageList", isSignal: true, isRequired: false, transformFunction: null }, messageUpdate: { classPropertyName: "messageUpdate", publicName: "messageUpdate", isSignal: true, isRequired: false, transformFunction: null }, selectedForEdit: { classPropertyName: "selectedForEdit", publicName: "selectedForEdit", isSignal: true, isRequired: false, transformFunction: null }, messageAction: { classPropertyName: "messageAction", publicName: "messageAction", isSignal: true, isRequired: false, transformFunction: null }, incomingUser: { classPropertyName: "incomingUser", publicName: "incomingUser", isSignal: true, isRequired: false, transformFunction: null }, transportType: { classPropertyName: "transportType", publicName: "transportType", isSignal: true, isRequired: false, transformFunction: null }, transportTypeIcon: { classPropertyName: "transportTypeIcon", publicName: "transportTypeIcon", isSignal: true, isRequired: false, transformFunction: null }, hideHandler: { classPropertyName: "hideHandler", publicName: "hideHandler", isSignal: true, isRequired: false, transformFunction: null }, closeHandler: { classPropertyName: "closeHandler", publicName: "closeHandler", isSignal: true, isRequired: false, transformFunction: null }, scrollToBottomTrigger: { classPropertyName: "scrollToBottomTrigger", publicName: "scrollToBottomTrigger", isSignal: true, isRequired: false, transformFunction: null }, loadHistory: { classPropertyName: "loadHistory", publicName: "loadHistory", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragActive: "dragActiveChange", messageList: "messageListChange", messageUpdate: "messageUpdateChange", selectedForEdit: "selectedForEditChange", messageAction: "messageActionChange", scrollToBottomTrigger: "scrollToBottomTriggerChange", loadHistory: "loadHistoryChange" }, providers: [], viewQueries: [{ propertyName: "chatFlow", first: true, predicate: ChatFlowComponent, descendants: true }, { propertyName: "inputMessage", first: true, predicate: InputMessageComponent, descendants: true }], ngImport: i0, template: "<div class=\"modal-chat\" [ngClass]=\"'flow-theme-' + theme()\">\n <div class=\"modal-chat__body\">\n @if (header()) {\n <header class=\"modal-chat__header\" mat-dialog-title>\n <div class=\"modal-chat__hide-block\"></div>\n\n <div class=\"modal-chat__title\">\n <h1 class=\"modal-chat__heading\" id=\"modal-chat__heading\">\n @if (transportTypeIconSrc()) {\n <img [ngSrc]=\"transportTypeIconSrc()\"\n class=\"modal-chat__heading-icon\"\n width=\"20\"\n height=\"20\"\n [attr.alt]=\"transportType() || 'transport icon'\"/>\n }\n <span class=\"modal-chat__heading-text\">\n {{ transportType() }} {{ incomingUser() }}\n </span>\n </h1>\n </div>\n\n <div class=\"modal-chat__actions\">\n <img ngSrc=\"assets/ngx-parl/icons/hide.svg\" class=\"modal-chat__icon modal-chat__icon--hide\"\n width=\"24\" height=\"24\" alt=\"hide\"\n (click)=\"onHideClick()\"/>\n <img ngSrc=\"assets/ngx-parl/icons/close.svg\" class=\"modal-chat__icon modal-chat__icon--close\"\n width=\"24\" height=\"24\" alt=\"close\"\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\"\n [class.modal-chat__content--header]=\"header() === false\"\n [class.modal-chat__content--dragover]=\"dragActive()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (dragActive()) {\n <div class=\"modal-chat__drag-overlay\"\n role=\"status\"\n aria-live=\"polite\"\n [attr.aria-label]=\"'chat.drag_title' | transloco\">\n <div class=\"modal-chat__drag-card\">\n <img ngSrc=\"assets/ngx-parl/icons/attach-filled.svg\"\n class=\"modal-chat__drag-icon\"\n alt=\"\"\n width=\"56\"\n height=\"56\"/>\n\n <div class=\"modal-chat__drag-title\">\n {{ 'chat.drag_title' | transloco }}\n </div>\n <div class=\"modal-chat__drag-subtitle\">\n {{ 'chat.drag_subtitle' | transloco }}\n </div>\n </div>\n </div>\n }\n <app-chat-flow [messageListInput]=\"messageList()\"\n [(selectedForEdit)]=\"selectedForEdit\"\n (requestDeleteChange)=\"onRequestDelete($event)\"\n [(scrollToBottomTrigger)]=\"scrollToBottomTrigger\"\n [(loadHistory)]=\"loadHistory\">\n </app-chat-flow>\n\n <app-input-message [editMessage]=\"selectedForEdit()\"\n (cancelEditChange)=\"onCancelEdit($event)\"\n (input_textChange)=\"sendMessage($event)\">\n @if (ai_run_in_progress) {\n <mat-spinner [diameter]=\"30\"></mat-spinner>\n }\n </app-input-message>\n </mat-dialog-content>\n </div>\n</div>\n", styles: [".flow-theme-primary ::ng-deep .modal-chat__header{background-color:#5a72d7;color:#fff}.flow-theme-primary ::ng-deep .message--incoming .message__body{background:#e9ecef;color:#343a40}.flow-theme-primary ::ng-deep .message--outgoing .message__body{background:#4656ca;color:#fff}:root{--shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, .05);--shadow-md: 0px 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0px 8px 24px rgba(0, 0, 0, .12);--shadow-soft: 0px 0px 6px 0px rgba(46, 46, 46, .12) }.flow-theme-secondary ::ng-deep .modal-chat__header{background-color:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--incoming .message__body{background:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--outgoing .message__body{background:#efefef;color:#464646}.modal-chat{width:800px;height:600px;border-radius:16px}.modal-chat__body{display:flex;flex-direction:column;height:100%}.modal-chat__header{height:56px;min-height:56px;max-height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;gap:12px;border-top-left-radius:16px;border-top-right-radius:16px;flex-direction:row}.modal-chat__hide-block{width:48px;color:#5a72d7}.modal-chat__title #modal-chat__heading{color:#fff;font:600 16px/20px inter,sans-serif;display:inline-flex;align-items:center;gap:8px}.modal-chat__heading-icon{width:20px;height:20px;border-radius:1000px;flex:0 0 auto}.modal-chat__actions{display:flex;gap:8px}.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column;background:#fff;border-bottom-left-radius:16px;border-bottom-right-radius:16px;transition:background-color .16s ease,box-shadow .16s ease;position:relative}.modal-chat__content--header{border-top-left-radius:16px;border-top-right-radius:16px}.modal-chat__content--dragover:after{content:\"\";position:absolute;inset:0;border-radius:inherit;box-shadow:0 0 0 2px #e9ecef inset;background:#fff0;pointer-events:none;z-index:1000}.modal-chat__content app-chat-flow{flex:1 1 auto;min-height:0px;overflow:auto;display:flex;align-items:flex-end}.modal-chat__drag-overlay{position:absolute;inset:16px;display:flex;align-items:center;justify-content:center;border-radius:16px;border:2px dashed #7A95E0;background:#ffffffeb;z-index:1000;pointer-events:none}.modal-chat__drag-card{display:flex;flex-direction:column;align-items:center;gap:8px;padding:20px 24px;border-radius:16px;background:#fff;box-shadow:0 2px 4px #0000001a;text-align:center}.modal-chat__drag-icon{filter:drop-shadow(0 2px 4px rgba(0,0,0,.2))}.modal-chat__drag-title{font:600 20px/24px inter,sans-serif;color:#4656ca}.modal-chat__drag-subtitle{font:400 14px/18px inter,sans-serif;color:#6c757d}.modal-chat__input{flex:0px 0px auto;border-bottom-left-radius:16px;border-bottom-right-radius:16px}:host ::ng-deep .mat-mdc-dialog-content.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column;padding:0;max-height:none;overflow:hidden}img{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: ChatFlowComponent, selector: "app-chat-flow", inputs: ["scrollToBottomTrigger", "loadHistory", "messageListInput", "selectedForEdit", "requestDelete"], outputs: ["scrollToBottomTriggerChange", "loadHistoryChange", "messageListInputChange", "selectedForEditChange", "requestDeleteChange"] }, { kind: "component", type: InputMessageComponent, selector: "app-input-message", inputs: ["editMessage", "cancelEdit", "input_text", "files", "previews", "messageEvent"], outputs: ["cancelEditChange", "input_textChange", "filesChange", "previewsChange", "messageEventChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
1485
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: NgxParlComponent, isStandalone: true, selector: "ngx-parl", inputs: { dragActive: { classPropertyName: "dragActive", publicName: "dragActive", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, messageList: { classPropertyName: "messageList", publicName: "messageList", isSignal: true, isRequired: false, transformFunction: null }, messageUpdate: { classPropertyName: "messageUpdate", publicName: "messageUpdate", isSignal: true, isRequired: false, transformFunction: null }, selectedForEdit: { classPropertyName: "selectedForEdit", publicName: "selectedForEdit", isSignal: true, isRequired: false, transformFunction: null }, messageAction: { classPropertyName: "messageAction", publicName: "messageAction", isSignal: true, isRequired: false, transformFunction: null }, incomingUser: { classPropertyName: "incomingUser", publicName: "incomingUser", isSignal: true, isRequired: false, transformFunction: null }, transportType: { classPropertyName: "transportType", publicName: "transportType", isSignal: true, isRequired: false, transformFunction: null }, transportTypeIcon: { classPropertyName: "transportTypeIcon", publicName: "transportTypeIcon", isSignal: true, isRequired: false, transformFunction: null }, mobileMode: { classPropertyName: "mobileMode", publicName: "mobileMode", isSignal: true, isRequired: false, transformFunction: null }, quickActionsResolver: { classPropertyName: "quickActionsResolver", publicName: "quickActionsResolver", isSignal: true, isRequired: false, transformFunction: null }, quickActionClick: { classPropertyName: "quickActionClick", publicName: "quickActionClick", isSignal: true, isRequired: false, transformFunction: null }, quickActionsAutoSend: { classPropertyName: "quickActionsAutoSend", publicName: "quickActionsAutoSend", isSignal: true, isRequired: false, transformFunction: null }, hideHandler: { classPropertyName: "hideHandler", publicName: "hideHandler", isSignal: true, isRequired: false, transformFunction: null }, closeHandler: { classPropertyName: "closeHandler", publicName: "closeHandler", isSignal: true, isRequired: false, transformFunction: null }, scrollToBottomTrigger: { classPropertyName: "scrollToBottomTrigger", publicName: "scrollToBottomTrigger", isSignal: true, isRequired: false, transformFunction: null }, loadHistory: { classPropertyName: "loadHistory", publicName: "loadHistory", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragActive: "dragActiveChange", messageList: "messageListChange", messageUpdate: "messageUpdateChange", selectedForEdit: "selectedForEditChange", messageAction: "messageActionChange", quickActionClick: "quickActionClickChange", scrollToBottomTrigger: "scrollToBottomTriggerChange", loadHistory: "loadHistoryChange" }, providers: [], viewQueries: [{ propertyName: "chatFlow", first: true, predicate: ChatFlowComponent, descendants: true }, { propertyName: "inputMessage", first: true, predicate: InputMessageComponent, descendants: true }], ngImport: i0, template: "<div class=\"modal-chat\" [ngClass]=\"'flow-theme-' + theme()\">\n <div class=\"modal-chat__body\">\n @if (header()) {\n <header class=\"modal-chat__header\" mat-dialog-title>\n <div class=\"modal-chat__hide-block\"></div>\n\n <div class=\"modal-chat__title\">\n <h1 class=\"modal-chat__heading\" id=\"modal-chat__heading\">\n @if (transportTypeIconSrc()) {\n <img [ngSrc]=\"transportTypeIconSrc()\"\n class=\"modal-chat__heading-icon\"\n width=\"20\"\n height=\"20\"\n [attr.alt]=\"transportType() || 'transport icon'\"/>\n }\n <span class=\"modal-chat__heading-text\">\n {{ transportType() }} {{ incomingUser() }}\n </span>\n </h1>\n </div>\n\n <div class=\"modal-chat__actions\">\n <img ngSrc=\"assets/ngx-parl/icons/hide.svg\" class=\"modal-chat__icon modal-chat__icon--hide\"\n width=\"24\" height=\"24\" alt=\"hide\"\n (click)=\"onHideClick()\"/>\n <img ngSrc=\"assets/ngx-parl/icons/close.svg\" class=\"modal-chat__icon modal-chat__icon--close\"\n width=\"24\" height=\"24\" alt=\"close\"\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\"\n [class.modal-chat__content--header]=\"header() === false\"\n [class.modal-chat__content--dragover]=\"dragActive()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (dragActive()) {\n <div class=\"modal-chat__drag-overlay\"\n role=\"status\"\n aria-live=\"polite\"\n [attr.aria-label]=\"'chat.drag_title' | transloco\">\n <div class=\"modal-chat__drag-card\">\n <img ngSrc=\"assets/ngx-parl/icons/attach-filled.svg\"\n class=\"modal-chat__drag-icon\"\n alt=\"\"\n width=\"56\"\n height=\"56\"/>\n\n <div class=\"modal-chat__drag-title\">\n {{ 'chat.drag_title' | transloco }}\n </div>\n <div class=\"modal-chat__drag-subtitle\">\n {{ 'chat.drag_subtitle' | transloco }}\n </div>\n </div>\n </div>\n }\n <app-chat-flow [messageListInput]=\"messageList()\"\n [(selectedForEdit)]=\"selectedForEdit\"\n (requestDeleteChange)=\"onRequestDelete($event)\"\n [mobileMode]=\"mobileMode()\"\n [quickActionsResolver]=\"quickActionsResolver()\"\n [(quickActionClick)]=\"quickActionClick\"\n [(scrollToBottomTrigger)]=\"scrollToBottomTrigger\"\n [(loadHistory)]=\"loadHistory\">\n </app-chat-flow>\n\n <app-input-message [editMessage]=\"selectedForEdit()\"\n (cancelEditChange)=\"onCancelEdit($event)\"\n (input_textChange)=\"sendMessage($event)\">\n @if (ai_run_in_progress) {\n <mat-spinner [diameter]=\"30\"></mat-spinner>\n }\n </app-input-message>\n </mat-dialog-content>\n </div>\n</div>\n", styles: [".flow-theme-primary ::ng-deep .modal-chat__header{background-color:#5a72d7;color:#fff}.flow-theme-primary ::ng-deep .message--incoming .message__body{background:#e9ecef;color:#343a40}.flow-theme-primary ::ng-deep .message--outgoing .message__body{background:#4656ca;color:#fff}:root{--shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, .05);--shadow-md: 0px 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0px 8px 24px rgba(0, 0, 0, .12);--shadow-soft: 0px 0px 6px 0px rgba(46, 46, 46, .12) }.flow-theme-secondary ::ng-deep .modal-chat__header{background-color:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--incoming .message__body{background:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--outgoing .message__body{background:#efefef;color:#464646}.modal-chat{width:800px;height:600px;border-radius:16px}.modal-chat__body{display:flex;flex-direction:column;height:100%}.modal-chat__header{height:56px;min-height:56px;max-height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;gap:12px;border-top-left-radius:16px;border-top-right-radius:16px;flex-direction:row}.modal-chat__hide-block{width:48px;color:#5a72d7}.modal-chat__title #modal-chat__heading{color:#fff;font:600 16px/20px inter,sans-serif;display:inline-flex;align-items:center;gap:8px}.modal-chat__heading-icon{width:20px;height:20px;border-radius:1000px;flex:0 0 auto}.modal-chat__actions{display:flex;gap:8px}.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column;background:#fff;border-bottom-left-radius:16px;border-bottom-right-radius:16px;transition:background-color .16s ease,box-shadow .16s ease;position:relative}.modal-chat__content--header{border-top-left-radius:16px;border-top-right-radius:16px}.modal-chat__content--dragover:after{content:\"\";position:absolute;inset:0;border-radius:inherit;box-shadow:0 0 0 2px #e9ecef inset;background:#fff0;pointer-events:none;z-index:1000}.modal-chat__content app-chat-flow{flex:1 1 auto;min-height:0px;overflow:auto;display:flex;align-items:flex-end}.modal-chat__drag-overlay{position:absolute;inset:16px;display:flex;align-items:center;justify-content:center;border-radius:16px;border:2px dashed #7A95E0;background:#ffffffeb;z-index:1000;pointer-events:none}.modal-chat__drag-card{display:flex;flex-direction:column;align-items:center;gap:8px;padding:20px 24px;border-radius:16px;background:#fff;box-shadow:0 2px 4px #0000001a;text-align:center}.modal-chat__drag-icon{filter:drop-shadow(0 2px 4px rgba(0,0,0,.2))}.modal-chat__drag-title{font:600 20px/24px inter,sans-serif;color:#4656ca}.modal-chat__drag-subtitle{font:400 14px/18px inter,sans-serif;color:#6c757d}.modal-chat__input{flex:0px 0px auto;border-bottom-left-radius:16px;border-bottom-right-radius:16px}:host ::ng-deep .mat-mdc-dialog-content.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column;padding:0;max-height:none;overflow:hidden}img{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: ChatFlowComponent, selector: "app-chat-flow", inputs: ["scrollToBottomTrigger", "loadHistory", "messageListInput", "selectedForEdit", "requestDelete", "mobileMode", "quickActionsResolver", "quickActionClick"], outputs: ["scrollToBottomTriggerChange", "loadHistoryChange", "messageListInputChange", "selectedForEditChange", "requestDeleteChange", "quickActionClickChange"] }, { kind: "component", type: InputMessageComponent, selector: "app-input-message", inputs: ["editMessage", "cancelEdit", "input_text", "files", "previews", "messageEvent"], outputs: ["cancelEditChange", "input_textChange", "filesChange", "previewsChange", "messageEventChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
1362
1486
  }
1363
1487
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NgxParlComponent, decorators: [{
1364
1488
  type: Component,
@@ -1366,7 +1490,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1366
1490
  NgOptimizedImage, NgClass, MatDialogContent, MatDialogTitle, MatProgressSpinner, ChatFlowComponent, InputMessageComponent,
1367
1491
  TranslocoModule,
1368
1492
  TranslocoPipe
1369
- ], providers: [], template: "<div class=\"modal-chat\" [ngClass]=\"'flow-theme-' + theme()\">\n <div class=\"modal-chat__body\">\n @if (header()) {\n <header class=\"modal-chat__header\" mat-dialog-title>\n <div class=\"modal-chat__hide-block\"></div>\n\n <div class=\"modal-chat__title\">\n <h1 class=\"modal-chat__heading\" id=\"modal-chat__heading\">\n @if (transportTypeIconSrc()) {\n <img [ngSrc]=\"transportTypeIconSrc()\"\n class=\"modal-chat__heading-icon\"\n width=\"20\"\n height=\"20\"\n [attr.alt]=\"transportType() || 'transport icon'\"/>\n }\n <span class=\"modal-chat__heading-text\">\n {{ transportType() }} {{ incomingUser() }}\n </span>\n </h1>\n </div>\n\n <div class=\"modal-chat__actions\">\n <img ngSrc=\"assets/ngx-parl/icons/hide.svg\" class=\"modal-chat__icon modal-chat__icon--hide\"\n width=\"24\" height=\"24\" alt=\"hide\"\n (click)=\"onHideClick()\"/>\n <img ngSrc=\"assets/ngx-parl/icons/close.svg\" class=\"modal-chat__icon modal-chat__icon--close\"\n width=\"24\" height=\"24\" alt=\"close\"\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\"\n [class.modal-chat__content--header]=\"header() === false\"\n [class.modal-chat__content--dragover]=\"dragActive()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (dragActive()) {\n <div class=\"modal-chat__drag-overlay\"\n role=\"status\"\n aria-live=\"polite\"\n [attr.aria-label]=\"'chat.drag_title' | transloco\">\n <div class=\"modal-chat__drag-card\">\n <img ngSrc=\"assets/ngx-parl/icons/attach-filled.svg\"\n class=\"modal-chat__drag-icon\"\n alt=\"\"\n width=\"56\"\n height=\"56\"/>\n\n <div class=\"modal-chat__drag-title\">\n {{ 'chat.drag_title' | transloco }}\n </div>\n <div class=\"modal-chat__drag-subtitle\">\n {{ 'chat.drag_subtitle' | transloco }}\n </div>\n </div>\n </div>\n }\n <app-chat-flow [messageListInput]=\"messageList()\"\n [(selectedForEdit)]=\"selectedForEdit\"\n (requestDeleteChange)=\"onRequestDelete($event)\"\n [(scrollToBottomTrigger)]=\"scrollToBottomTrigger\"\n [(loadHistory)]=\"loadHistory\">\n </app-chat-flow>\n\n <app-input-message [editMessage]=\"selectedForEdit()\"\n (cancelEditChange)=\"onCancelEdit($event)\"\n (input_textChange)=\"sendMessage($event)\">\n @if (ai_run_in_progress) {\n <mat-spinner [diameter]=\"30\"></mat-spinner>\n }\n </app-input-message>\n </mat-dialog-content>\n </div>\n</div>\n", styles: [".flow-theme-primary ::ng-deep .modal-chat__header{background-color:#5a72d7;color:#fff}.flow-theme-primary ::ng-deep .message--incoming .message__body{background:#e9ecef;color:#343a40}.flow-theme-primary ::ng-deep .message--outgoing .message__body{background:#4656ca;color:#fff}:root{--shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, .05);--shadow-md: 0px 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0px 8px 24px rgba(0, 0, 0, .12);--shadow-soft: 0px 0px 6px 0px rgba(46, 46, 46, .12) }.flow-theme-secondary ::ng-deep .modal-chat__header{background-color:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--incoming .message__body{background:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--outgoing .message__body{background:#efefef;color:#464646}.modal-chat{width:800px;height:600px;border-radius:16px}.modal-chat__body{display:flex;flex-direction:column;height:100%}.modal-chat__header{height:56px;min-height:56px;max-height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;gap:12px;border-top-left-radius:16px;border-top-right-radius:16px;flex-direction:row}.modal-chat__hide-block{width:48px;color:#5a72d7}.modal-chat__title #modal-chat__heading{color:#fff;font:600 16px/20px inter,sans-serif;display:inline-flex;align-items:center;gap:8px}.modal-chat__heading-icon{width:20px;height:20px;border-radius:1000px;flex:0 0 auto}.modal-chat__actions{display:flex;gap:8px}.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column;background:#fff;border-bottom-left-radius:16px;border-bottom-right-radius:16px;transition:background-color .16s ease,box-shadow .16s ease;position:relative}.modal-chat__content--header{border-top-left-radius:16px;border-top-right-radius:16px}.modal-chat__content--dragover:after{content:\"\";position:absolute;inset:0;border-radius:inherit;box-shadow:0 0 0 2px #e9ecef inset;background:#fff0;pointer-events:none;z-index:1000}.modal-chat__content app-chat-flow{flex:1 1 auto;min-height:0px;overflow:auto;display:flex;align-items:flex-end}.modal-chat__drag-overlay{position:absolute;inset:16px;display:flex;align-items:center;justify-content:center;border-radius:16px;border:2px dashed #7A95E0;background:#ffffffeb;z-index:1000;pointer-events:none}.modal-chat__drag-card{display:flex;flex-direction:column;align-items:center;gap:8px;padding:20px 24px;border-radius:16px;background:#fff;box-shadow:0 2px 4px #0000001a;text-align:center}.modal-chat__drag-icon{filter:drop-shadow(0 2px 4px rgba(0,0,0,.2))}.modal-chat__drag-title{font:600 20px/24px inter,sans-serif;color:#4656ca}.modal-chat__drag-subtitle{font:400 14px/18px inter,sans-serif;color:#6c757d}.modal-chat__input{flex:0px 0px auto;border-bottom-left-radius:16px;border-bottom-right-radius:16px}:host ::ng-deep .mat-mdc-dialog-content.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column;padding:0;max-height:none;overflow:hidden}img{cursor:pointer}\n"] }]
1493
+ ], providers: [], template: "<div class=\"modal-chat\" [ngClass]=\"'flow-theme-' + theme()\">\n <div class=\"modal-chat__body\">\n @if (header()) {\n <header class=\"modal-chat__header\" mat-dialog-title>\n <div class=\"modal-chat__hide-block\"></div>\n\n <div class=\"modal-chat__title\">\n <h1 class=\"modal-chat__heading\" id=\"modal-chat__heading\">\n @if (transportTypeIconSrc()) {\n <img [ngSrc]=\"transportTypeIconSrc()\"\n class=\"modal-chat__heading-icon\"\n width=\"20\"\n height=\"20\"\n [attr.alt]=\"transportType() || 'transport icon'\"/>\n }\n <span class=\"modal-chat__heading-text\">\n {{ transportType() }} {{ incomingUser() }}\n </span>\n </h1>\n </div>\n\n <div class=\"modal-chat__actions\">\n <img ngSrc=\"assets/ngx-parl/icons/hide.svg\" class=\"modal-chat__icon modal-chat__icon--hide\"\n width=\"24\" height=\"24\" alt=\"hide\"\n (click)=\"onHideClick()\"/>\n <img ngSrc=\"assets/ngx-parl/icons/close.svg\" class=\"modal-chat__icon modal-chat__icon--close\"\n width=\"24\" height=\"24\" alt=\"close\"\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\"\n [class.modal-chat__content--header]=\"header() === false\"\n [class.modal-chat__content--dragover]=\"dragActive()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (dragActive()) {\n <div class=\"modal-chat__drag-overlay\"\n role=\"status\"\n aria-live=\"polite\"\n [attr.aria-label]=\"'chat.drag_title' | transloco\">\n <div class=\"modal-chat__drag-card\">\n <img ngSrc=\"assets/ngx-parl/icons/attach-filled.svg\"\n class=\"modal-chat__drag-icon\"\n alt=\"\"\n width=\"56\"\n height=\"56\"/>\n\n <div class=\"modal-chat__drag-title\">\n {{ 'chat.drag_title' | transloco }}\n </div>\n <div class=\"modal-chat__drag-subtitle\">\n {{ 'chat.drag_subtitle' | transloco }}\n </div>\n </div>\n </div>\n }\n <app-chat-flow [messageListInput]=\"messageList()\"\n [(selectedForEdit)]=\"selectedForEdit\"\n (requestDeleteChange)=\"onRequestDelete($event)\"\n [mobileMode]=\"mobileMode()\"\n [quickActionsResolver]=\"quickActionsResolver()\"\n [(quickActionClick)]=\"quickActionClick\"\n [(scrollToBottomTrigger)]=\"scrollToBottomTrigger\"\n [(loadHistory)]=\"loadHistory\">\n </app-chat-flow>\n\n <app-input-message [editMessage]=\"selectedForEdit()\"\n (cancelEditChange)=\"onCancelEdit($event)\"\n (input_textChange)=\"sendMessage($event)\">\n @if (ai_run_in_progress) {\n <mat-spinner [diameter]=\"30\"></mat-spinner>\n }\n </app-input-message>\n </mat-dialog-content>\n </div>\n</div>\n", styles: [".flow-theme-primary ::ng-deep .modal-chat__header{background-color:#5a72d7;color:#fff}.flow-theme-primary ::ng-deep .message--incoming .message__body{background:#e9ecef;color:#343a40}.flow-theme-primary ::ng-deep .message--outgoing .message__body{background:#4656ca;color:#fff}:root{--shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, .05);--shadow-md: 0px 4px 12px rgba(0, 0, 0, .08);--shadow-lg: 0px 8px 24px rgba(0, 0, 0, .12);--shadow-soft: 0px 0px 6px 0px rgba(46, 46, 46, .12) }.flow-theme-secondary ::ng-deep .modal-chat__header{background-color:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--incoming .message__body{background:#848af5;color:#fefefe}.flow-theme-secondary ::ng-deep .message--outgoing .message__body{background:#efefef;color:#464646}.modal-chat{width:800px;height:600px;border-radius:16px}.modal-chat__body{display:flex;flex-direction:column;height:100%}.modal-chat__header{height:56px;min-height:56px;max-height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;gap:12px;border-top-left-radius:16px;border-top-right-radius:16px;flex-direction:row}.modal-chat__hide-block{width:48px;color:#5a72d7}.modal-chat__title #modal-chat__heading{color:#fff;font:600 16px/20px inter,sans-serif;display:inline-flex;align-items:center;gap:8px}.modal-chat__heading-icon{width:20px;height:20px;border-radius:1000px;flex:0 0 auto}.modal-chat__actions{display:flex;gap:8px}.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column;background:#fff;border-bottom-left-radius:16px;border-bottom-right-radius:16px;transition:background-color .16s ease,box-shadow .16s ease;position:relative}.modal-chat__content--header{border-top-left-radius:16px;border-top-right-radius:16px}.modal-chat__content--dragover:after{content:\"\";position:absolute;inset:0;border-radius:inherit;box-shadow:0 0 0 2px #e9ecef inset;background:#fff0;pointer-events:none;z-index:1000}.modal-chat__content app-chat-flow{flex:1 1 auto;min-height:0px;overflow:auto;display:flex;align-items:flex-end}.modal-chat__drag-overlay{position:absolute;inset:16px;display:flex;align-items:center;justify-content:center;border-radius:16px;border:2px dashed #7A95E0;background:#ffffffeb;z-index:1000;pointer-events:none}.modal-chat__drag-card{display:flex;flex-direction:column;align-items:center;gap:8px;padding:20px 24px;border-radius:16px;background:#fff;box-shadow:0 2px 4px #0000001a;text-align:center}.modal-chat__drag-icon{filter:drop-shadow(0 2px 4px rgba(0,0,0,.2))}.modal-chat__drag-title{font:600 20px/24px inter,sans-serif;color:#4656ca}.modal-chat__drag-subtitle{font:400 14px/18px inter,sans-serif;color:#6c757d}.modal-chat__input{flex:0px 0px auto;border-bottom-left-radius:16px;border-bottom-right-radius:16px}:host ::ng-deep .mat-mdc-dialog-content.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column;padding:0;max-height:none;overflow:hidden}img{cursor:pointer}\n"] }]
1370
1494
  }], ctorParameters: () => [{ type: UtilsService }, { type: i2.TranslocoService }, { type: i3.MatDialogRef, decorators: [{
1371
1495
  type: Optional
1372
1496
  }] }], propDecorators: { chatFlow: [{
@@ -1375,7 +1499,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1375
1499
  }], inputMessage: [{
1376
1500
  type: ViewChild,
1377
1501
  args: [InputMessageComponent]
1378
- }], dragActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragActive", required: false }] }, { type: i0.Output, args: ["dragActiveChange"] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], language: [{ type: i0.Input, args: [{ isSignal: true, alias: "language", required: false }] }], messageList: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageList", required: false }] }, { type: i0.Output, args: ["messageListChange"] }], messageUpdate: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageUpdate", required: false }] }, { type: i0.Output, args: ["messageUpdateChange"] }], selectedForEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedForEdit", required: false }] }, { type: i0.Output, args: ["selectedForEditChange"] }], messageAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageAction", required: false }] }, { type: i0.Output, args: ["messageActionChange"] }], incomingUser: [{ type: i0.Input, args: [{ isSignal: true, alias: "incomingUser", required: false }] }], transportType: [{ type: i0.Input, args: [{ isSignal: true, alias: "transportType", required: false }] }], transportTypeIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "transportTypeIcon", required: false }] }], hideHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideHandler", required: false }] }], closeHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeHandler", required: false }] }], scrollToBottomTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollToBottomTrigger", required: false }] }, { type: i0.Output, args: ["scrollToBottomTriggerChange"] }], loadHistory: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadHistory", required: false }] }, { type: i0.Output, args: ["loadHistoryChange"] }] } });
1502
+ }], dragActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragActive", required: false }] }, { type: i0.Output, args: ["dragActiveChange"] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], language: [{ type: i0.Input, args: [{ isSignal: true, alias: "language", required: false }] }], messageList: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageList", required: false }] }, { type: i0.Output, args: ["messageListChange"] }], messageUpdate: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageUpdate", required: false }] }, { type: i0.Output, args: ["messageUpdateChange"] }], selectedForEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedForEdit", required: false }] }, { type: i0.Output, args: ["selectedForEditChange"] }], messageAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageAction", required: false }] }, { type: i0.Output, args: ["messageActionChange"] }], incomingUser: [{ type: i0.Input, args: [{ isSignal: true, alias: "incomingUser", required: false }] }], transportType: [{ type: i0.Input, args: [{ isSignal: true, alias: "transportType", required: false }] }], transportTypeIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "transportTypeIcon", required: false }] }], mobileMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileMode", required: false }] }], quickActionsResolver: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickActionsResolver", required: false }] }], quickActionClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickActionClick", required: false }] }, { type: i0.Output, args: ["quickActionClickChange"] }], quickActionsAutoSend: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickActionsAutoSend", required: false }] }], hideHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideHandler", required: false }] }], closeHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeHandler", required: false }] }], scrollToBottomTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollToBottomTrigger", required: false }] }, { type: i0.Output, args: ["scrollToBottomTriggerChange"] }], loadHistory: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadHistory", required: false }] }, { type: i0.Output, args: ["loadHistoryChange"] }] } });
1379
1503
 
1380
1504
  var chat$1 = {
1381
1505
  title: "Telegram",
@@ -1390,6 +1514,8 @@ var chat$1 = {
1390
1514
  video: "Video",
1391
1515
  edit: "Edit",
1392
1516
  remove: "Delete",
1517
+ cancel: "Cancel",
1518
+ delete_message_title: "Delete this message?",
1393
1519
  chat_empty_title: "No messages",
1394
1520
  chat_empty_subscription: "Your chat history will be displayed here. Write your first message to get started!",
1395
1521
  photo_preview: "Photo preview",
@@ -1417,6 +1543,8 @@ var chat = {
1417
1543
  video: "Відео",
1418
1544
  edit: "Редагувати",
1419
1545
  remove: "Видалити",
1546
+ cancel: "Скасувати",
1547
+ delete_message_title: "Видалити це повідомлення?",
1420
1548
  chat_empty_title: "Повідомлень ще немає",
1421
1549
  chat_empty_subscription: "Тут буде відображатись ваша історія спілкування. Напишіть перше повідомлення, щоб почати!",
1422
1550
  photo_preview: "Перегляд фото",
@@ -1464,5 +1592,5 @@ function provideNgxParl() {
1464
1592
  * Generated bundle index. Do not edit.
1465
1593
  */
1466
1594
 
1467
- export { NgxParlComponent, provideNgxParl };
1595
+ export { ChatMessage, MessageType, NgxParlComponent, provideNgxParl };
1468
1596
  //# sourceMappingURL=trixwell-ngx-parl.mjs.map