@trixwell/ngx-parl 1.2.3 → 1.2.6

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.
File without changes
File without changes
File without changes
@@ -2,13 +2,10 @@ import * as i0 from '@angular/core';
2
2
  import { input, model, computed, Component, Injectable, Pipe, effect, ViewChild, signal, isDevMode } from '@angular/core';
3
3
  import { NgClass, NgOptimizedImage, DatePipe } from '@angular/common';
4
4
  import { FormsModule } from '@angular/forms';
5
- import * as i1 from '@angular/material/icon';
6
- import { MatIcon } from '@angular/material/icon';
7
5
  import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
8
- import * as i2$1 from '@ngneat/transloco';
6
+ import * as i2 from '@ngneat/transloco';
9
7
  import { TranslocoPipe, TranslocoModule, provideTransloco } from '@ngneat/transloco';
10
- import * as i2 from '@angular/platform-browser';
11
- import * as i1$1 from '@angular/common/http';
8
+ import * as i1 from '@angular/common/http';
12
9
  import { MatDialogContent, MatDialogTitle } from '@angular/material/dialog';
13
10
  import { MatProgressSpinner } from '@angular/material/progress-spinner';
14
11
  import { of } from 'rxjs';
@@ -56,23 +53,11 @@ var MessageType;
56
53
  })(MessageType || (MessageType = {}));
57
54
 
58
55
  class ChatMessageComponent {
59
- iconRegistry;
60
- sanitizer;
61
56
  currentMessage = input.required(...(ngDevMode ? [{ debugName: "currentMessage" }] : []));
62
57
  edit = model(false, ...(ngDevMode ? [{ debugName: "edit" }] : []));
63
58
  requestEdit = model(null, ...(ngDevMode ? [{ debugName: "requestEdit" }] : []));
64
59
  requestDelete = model(null, ...(ngDevMode ? [{ debugName: "requestDelete" }] : []));
65
- constructor(iconRegistry, sanitizer) {
66
- this.iconRegistry = iconRegistry;
67
- this.sanitizer = sanitizer;
68
- this.iconRegistry.addSvgIcon('checked-message', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/checked-message.svg'));
69
- this.iconRegistry.addSvgIcon('no-check', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/no-check.svg'));
70
- this.iconRegistry.addSvgIcon('trash', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/trash.svg'));
71
- this.iconRegistry.addSvgIcon('icon-edit', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/icon-edit.svg'));
72
- setTimeout(() => {
73
- this.currentMessage().checked = true;
74
- }, 600);
75
- }
60
+ constructor() { }
76
61
  normalizeSourcePath(sourcePath) {
77
62
  const cleanedPath = (sourcePath ?? '').trim();
78
63
  if (!cleanedPath) {
@@ -146,22 +131,21 @@ class ChatMessageComponent {
146
131
  return message.type === this.messageType.Outgoing;
147
132
  }
148
133
  messageType = MessageType;
149
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatMessageComponent, deps: [{ token: i1.MatIconRegistry }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
150
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.7", 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 }, 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", 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 #menuTrigger=\"matMenuTrigger\"\n [matMenuTriggerFor]=\"messageMenu\"\n (contextmenu)=\"openContextMenu($event, menuTrigger)\"\n (keydown.shift.F10)=\"openContextMenu($event, menuTrigger)\">\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file) {\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\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\">{{ currentMessage().cr_time | date:'HH:mm' }}</time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().checked) {\n <mat-icon svgIcon=\"checked-message\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n } @else {\n <mat-icon svgIcon=\"no-check\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n }\n }\n </div>\n </div>\n </div>\n</div>\n\n<mat-menu #messageMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\" class=\"message__menu\">\n @if (currentMessage().type === messageType.Outgoing) {\n <button mat-menu-item (click)=\"editMessage(currentMessage())\">\n <mat-icon svgIcon=\"icon-edit\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n <span>{{ 'chat.edit' | transloco }}</span>\n </button>\n }\n @if (canDelete(currentMessage())) {\n <button mat-menu-item (click)=\"deleteMessage(currentMessage())\">\n <mat-icon svgIcon=\"trash\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\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/24px roboto,sans-serif;border-radius:16px}.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:12px/14px roboto,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,140px))}.message__attachments:has(:nth-child(3)){grid-template-columns:repeat(3,minmax(0,140px))}.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:12px/14px roboto,sans-serif;min-width:30px}.message__icon{width:14px;height:14px;vertical-align:middle}.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}@keyframes pop{0%{transform:translateY(2px);opacity:0}to{transform:translateY(0);opacity:1}}::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:14px/18px roboto,sans-serif}::ng-deep .mat-mdc-menu-item-text{font:14px/18px roboto,sans-serif!important;font-weight:500!important;color:#343a40!important}\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: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
134
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
135
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.7", 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 }, 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", 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 #menuTrigger=\"matMenuTrigger\"\n [matMenuTriggerFor]=\"messageMenu\"\n (contextmenu)=\"openContextMenu($event, menuTrigger)\"\n (keydown.shift.F10)=\"openContextMenu($event, menuTrigger)\">\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file) {\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\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\">{{ currentMessage().cr_time | date:'HH:mm' }}</time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().checked) {\n <img ngSrc=\"assets/ngx-parl/icons/checked-message.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n } @else {\n <img ngSrc=\"assets/ngx-parl/icons/no-check\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n }\n }\n </div>\n </div>\n </div>\n</div>\n\n<mat-menu #messageMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\" 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\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\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\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\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/24px roboto,sans-serif;border-radius:16px}.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:12px/14px roboto,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,140px))}.message__attachments:has(:nth-child(3)){grid-template-columns:repeat(3,minmax(0,140px))}.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:12px/14px roboto,sans-serif;min-width:30px}.message__icon{width:14px;height:14px;vertical-align:middle}.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}@keyframes pop{0%{transform:translateY(2px);opacity:0}to{transform:translateY(0);opacity:1}}::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:14px/18px roboto,sans-serif}::ng-deep .mat-mdc-menu-item-text{font:14px/18px roboto,sans-serif!important;font-weight:500!important;color:#343a40!important}\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: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
151
136
  }
152
137
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatMessageComponent, decorators: [{
153
138
  type: Component,
154
139
  args: [{ selector: 'lib-chat-message', imports: [
155
140
  NgClass,
156
141
  NgOptimizedImage,
157
- MatIcon,
158
142
  DatePipe,
159
143
  MatMenu,
160
144
  MatMenuItem,
161
145
  MatMenuTrigger,
162
146
  TranslocoPipe,
163
- ], 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 #menuTrigger=\"matMenuTrigger\"\n [matMenuTriggerFor]=\"messageMenu\"\n (contextmenu)=\"openContextMenu($event, menuTrigger)\"\n (keydown.shift.F10)=\"openContextMenu($event, menuTrigger)\">\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file) {\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\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\">{{ currentMessage().cr_time | date:'HH:mm' }}</time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().checked) {\n <mat-icon svgIcon=\"checked-message\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n } @else {\n <mat-icon svgIcon=\"no-check\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n }\n }\n </div>\n </div>\n </div>\n</div>\n\n<mat-menu #messageMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\" class=\"message__menu\">\n @if (currentMessage().type === messageType.Outgoing) {\n <button mat-menu-item (click)=\"editMessage(currentMessage())\">\n <mat-icon svgIcon=\"icon-edit\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n <span>{{ 'chat.edit' | transloco }}</span>\n </button>\n }\n @if (canDelete(currentMessage())) {\n <button mat-menu-item (click)=\"deleteMessage(currentMessage())\">\n <mat-icon svgIcon=\"trash\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\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/24px roboto,sans-serif;border-radius:16px}.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:12px/14px roboto,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,140px))}.message__attachments:has(:nth-child(3)){grid-template-columns:repeat(3,minmax(0,140px))}.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:12px/14px roboto,sans-serif;min-width:30px}.message__icon{width:14px;height:14px;vertical-align:middle}.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}@keyframes pop{0%{transform:translateY(2px);opacity:0}to{transform:translateY(0);opacity:1}}::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:14px/18px roboto,sans-serif}::ng-deep .mat-mdc-menu-item-text{font:14px/18px roboto,sans-serif!important;font-weight:500!important;color:#343a40!important}\n"] }]
164
- }], ctorParameters: () => [{ type: i1.MatIconRegistry }, { type: i2.DomSanitizer }], 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"] }], 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"] }] } });
147
+ ], 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 #menuTrigger=\"matMenuTrigger\"\n [matMenuTriggerFor]=\"messageMenu\"\n (contextmenu)=\"openContextMenu($event, menuTrigger)\"\n (keydown.shift.F10)=\"openContextMenu($event, menuTrigger)\">\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file) {\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\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\">{{ currentMessage().cr_time | date:'HH:mm' }}</time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().checked) {\n <img ngSrc=\"assets/ngx-parl/icons/checked-message.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n } @else {\n <img ngSrc=\"assets/ngx-parl/icons/no-check\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n }\n }\n </div>\n </div>\n </div>\n</div>\n\n<mat-menu #messageMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\" 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\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\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\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\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/24px roboto,sans-serif;border-radius:16px}.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:12px/14px roboto,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,140px))}.message__attachments:has(:nth-child(3)){grid-template-columns:repeat(3,minmax(0,140px))}.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:12px/14px roboto,sans-serif;min-width:30px}.message__icon{width:14px;height:14px;vertical-align:middle}.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}@keyframes pop{0%{transform:translateY(2px);opacity:0}to{transform:translateY(0);opacity:1}}::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:14px/18px roboto,sans-serif}::ng-deep .mat-mdc-menu-item-text{font:14px/18px roboto,sans-serif!important;font-weight:500!important;color:#343a40!important}\n"] }]
148
+ }], ctorParameters: () => [], 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"] }], 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"] }] } });
165
149
 
166
150
  class UtilsService {
167
151
  http;
@@ -187,7 +171,7 @@ class UtilsService {
187
171
  const seconds = String(d.getSeconds()).padStart(2, '0');
188
172
  return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
189
173
  }
190
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: UtilsService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
174
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: UtilsService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
191
175
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: UtilsService, providedIn: 'root' });
192
176
  }
193
177
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: UtilsService, decorators: [{
@@ -195,7 +179,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImpor
195
179
  args: [{
196
180
  providedIn: 'root'
197
181
  }]
198
- }], ctorParameters: () => [{ type: i1$1.HttpClient }] });
182
+ }], ctorParameters: () => [{ type: i1.HttpClient }] });
199
183
 
200
184
  class ChatStartDayPipe {
201
185
  utils;
@@ -217,7 +201,7 @@ class ChatStartDayPipe {
217
201
  ? (locale.startsWith('uk') ? 'Сьогодні' : 'Today')
218
202
  : (datePipe.transform(valueDate, format) ?? '');
219
203
  }
220
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatStartDayPipe, deps: [{ token: UtilsService }, { token: i2$1.TranslocoService }], target: i0.ɵɵFactoryTarget.Pipe });
204
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatStartDayPipe, deps: [{ token: UtilsService }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Pipe });
221
205
  static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.7", ngImport: i0, type: ChatStartDayPipe, isStandalone: true, name: "chatStartDay" });
222
206
  }
223
207
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatStartDayPipe, decorators: [{
@@ -225,7 +209,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImpor
225
209
  args: [{
226
210
  name: 'chatStartDay'
227
211
  }]
228
- }], ctorParameters: () => [{ type: UtilsService }, { type: i2$1.TranslocoService }] });
212
+ }], ctorParameters: () => [{ type: UtilsService }, { type: i2.TranslocoService }] });
229
213
 
230
214
  class ToggleDisplayChatStartDayPipe {
231
215
  utils;
@@ -242,7 +226,7 @@ class ToggleDisplayChatStartDayPipe {
242
226
  const prevDay = prev ? datePipe.transform(new Date(prev.cr_time), 'shortDate') : undefined;
243
227
  return prev ? currDay !== prevDay : true;
244
228
  }
245
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ToggleDisplayChatStartDayPipe, deps: [{ token: UtilsService }, { token: i2$1.TranslocoService }], target: i0.ɵɵFactoryTarget.Pipe });
229
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ToggleDisplayChatStartDayPipe, deps: [{ token: UtilsService }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Pipe });
246
230
  static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.7", ngImport: i0, type: ToggleDisplayChatStartDayPipe, isStandalone: true, name: "toggleDisplayChatStartDay" });
247
231
  }
248
232
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ToggleDisplayChatStartDayPipe, decorators: [{
@@ -250,19 +234,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImpor
250
234
  args: [{
251
235
  name: 'toggleDisplayChatStartDay'
252
236
  }]
253
- }], ctorParameters: () => [{ type: UtilsService }, { type: i2$1.TranslocoService }] });
237
+ }], ctorParameters: () => [{ type: UtilsService }, { type: i2.TranslocoService }] });
254
238
 
255
239
  class ChatFlowComponent {
256
- iconRegistry;
257
- sanitizer;
258
240
  flowRef;
259
241
  messageListInput = model.required(...(ngDevMode ? [{ debugName: "messageListInput" }] : []));
260
242
  messageList = computed(() => this.messageListInput(), ...(ngDevMode ? [{ debugName: "messageList" }] : []));
261
243
  selectedForEdit = model.required(...(ngDevMode ? [{ debugName: "selectedForEdit" }] : []));
262
- constructor(iconRegistry, sanitizer) {
263
- this.iconRegistry = iconRegistry;
264
- this.sanitizer = sanitizer;
265
- this.iconRegistry.addSvgIcon('lucide_send', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/lucide_send.svg'));
244
+ constructor() {
266
245
  effect(() => {
267
246
  const length = this.messageList().length;
268
247
  if (length > 0) {
@@ -330,8 +309,8 @@ class ChatFlowComponent {
330
309
  // return message.id;
331
310
  return `${message.chat_id}-${message.type}-${message.id}`;
332
311
  }
333
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatFlowComponent, deps: [{ token: i1.MatIconRegistry }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
334
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.7", type: ChatFlowComponent, isStandalone: true, selector: "app-chat-flow", inputs: { messageListInput: { classPropertyName: "messageListInput", publicName: "messageListInput", isSignal: true, isRequired: true, transformFunction: null }, selectedForEdit: { classPropertyName: "selectedForEdit", publicName: "selectedForEdit", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { messageListInput: "messageListInputChange", selectedForEdit: "selectedForEditChange" }, viewQueries: [{ propertyName: "flowRef", first: true, predicate: ["chatFlowRef"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"chat\">\n @if (messageList()) {\n <div class=\"chat__flow\" #chatFlowRef>\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 <lib-chat-message [currentMessage]=\"message\"\n [edit]=\"message.edit ?? false\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n }\n </div>\n } @else {\n <div class=\"chat__flow__empty\">\n <mat-icon svgIcon=\"lucide_send\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\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", styles: [":host{display:block;height:100%;min-height:0}.chat{background:#fff;height:100%;display:flex;flex-direction:column;min-height:0;width:100%}.chat__flow{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px;scroll-behavior:smooth;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:500 16px/24px roboto,sans-serif;color:#212529}.chat__flow__empty--subscription{margin:0;font:400 16px/24px roboto,sans-serif;color:#495057}.chat__start-day{display:flex;justify-content:center;background:#f8f9fa;color:#6c757d;font:12px/14px roboto,sans-serif;width:78px;height:22px;margin:0 auto;border-radius:1000px;gap:8px;padding:4px 12px}.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", "requestEdit", "requestDelete"], outputs: ["editChange", "requestEditChange", "requestDeleteChange"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: ChatStartDayPipe, name: "chatStartDay" }, { kind: "pipe", type: ToggleDisplayChatStartDayPipe, name: "toggleDisplayChatStartDay" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
312
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatFlowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
313
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.7", type: ChatFlowComponent, isStandalone: true, selector: "app-chat-flow", inputs: { messageListInput: { classPropertyName: "messageListInput", publicName: "messageListInput", isSignal: true, isRequired: true, transformFunction: null }, selectedForEdit: { classPropertyName: "selectedForEdit", publicName: "selectedForEdit", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { messageListInput: "messageListInputChange", selectedForEdit: "selectedForEditChange" }, viewQueries: [{ propertyName: "flowRef", first: true, predicate: ["chatFlowRef"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"chat\">\n @if (messageList()) {\n <div class=\"chat__flow\" #chatFlowRef>\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 <lib-chat-message [currentMessage]=\"message\"\n [edit]=\"message.edit ?? false\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n }\n </div>\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\" priority/>\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", styles: [":host{display:block;height:100%;min-height:0}.chat{background:#fff;height:100%;display:flex;flex-direction:column;min-height:0;width:100%}.chat__flow{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px;scroll-behavior:smooth;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:500 16px/24px roboto,sans-serif;color:#212529}.chat__flow__empty--subscription{margin:0;font:400 16px/24px roboto,sans-serif;color:#495057}.chat__start-day{display:flex;justify-content:center;background:#f8f9fa;color:#6c757d;font:12px/14px roboto,sans-serif;width:78px;height:22px;margin:0 auto;border-radius:1000px;gap:8px;padding:4px 12px}.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", "requestEdit", "requestDelete"], outputs: ["editChange", "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: "pipe", type: ChatStartDayPipe, name: "chatStartDay" }, { kind: "pipe", type: ToggleDisplayChatStartDayPipe, name: "toggleDisplayChatStartDay" }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
335
314
  }
336
315
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: ChatFlowComponent, decorators: [{
337
316
  type: Component,
@@ -342,9 +321,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImpor
342
321
  ToggleDisplayChatStartDayPipe,
343
322
  ChatMessageComponent,
344
323
  TranslocoPipe,
345
- MatIcon
346
- ], standalone: true, template: "<div class=\"chat\">\n @if (messageList()) {\n <div class=\"chat__flow\" #chatFlowRef>\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 <lib-chat-message [currentMessage]=\"message\"\n [edit]=\"message.edit ?? false\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n }\n </div>\n } @else {\n <div class=\"chat__flow__empty\">\n <mat-icon svgIcon=\"lucide_send\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\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", styles: [":host{display:block;height:100%;min-height:0}.chat{background:#fff;height:100%;display:flex;flex-direction:column;min-height:0;width:100%}.chat__flow{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px;scroll-behavior:smooth;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:500 16px/24px roboto,sans-serif;color:#212529}.chat__flow__empty--subscription{margin:0;font:400 16px/24px roboto,sans-serif;color:#495057}.chat__start-day{display:flex;justify-content:center;background:#f8f9fa;color:#6c757d;font:12px/14px roboto,sans-serif;width:78px;height:22px;margin:0 auto;border-radius:1000px;gap:8px;padding:4px 12px}.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"] }]
347
- }], ctorParameters: () => [{ type: i1.MatIconRegistry }, { type: i2.DomSanitizer }], propDecorators: { flowRef: [{
324
+ NgOptimizedImage
325
+ ], standalone: true, template: "<div class=\"chat\">\n @if (messageList()) {\n <div class=\"chat__flow\" #chatFlowRef>\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 <lib-chat-message [currentMessage]=\"message\"\n [edit]=\"message.edit ?? false\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n }\n </div>\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\" priority/>\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", styles: [":host{display:block;height:100%;min-height:0}.chat{background:#fff;height:100%;display:flex;flex-direction:column;min-height:0;width:100%}.chat__flow{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;padding:12px 16px;scroll-behavior:smooth;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:500 16px/24px roboto,sans-serif;color:#212529}.chat__flow__empty--subscription{margin:0;font:400 16px/24px roboto,sans-serif;color:#495057}.chat__start-day{display:flex;justify-content:center;background:#f8f9fa;color:#6c757d;font:12px/14px roboto,sans-serif;width:78px;height:22px;margin:0 auto;border-radius:1000px;gap:8px;padding:4px 12px}.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"] }]
326
+ }], ctorParameters: () => [], propDecorators: { flowRef: [{
348
327
  type: ViewChild,
349
328
  args: ['chatFlowRef', { static: true }]
350
329
  }], 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"] }] } });
@@ -366,8 +345,6 @@ var FileType;
366
345
  })(FileType || (FileType = {}));
367
346
 
368
347
  class InputMessageComponent {
369
- iconRegistry;
370
- sanitizer;
371
348
  inputTextElement;
372
349
  mirrorElement;
373
350
  editMessage = input(null, ...(ngDevMode ? [{ debugName: "editMessage" }] : []));
@@ -391,13 +368,7 @@ class InputMessageComponent {
391
368
  lastHeightPx = 0;
392
369
  lastRows = 1;
393
370
  resizeRaf = null;
394
- constructor(iconRegistry, sanitizer) {
395
- this.iconRegistry = iconRegistry;
396
- this.sanitizer = sanitizer;
397
- this.iconRegistry.addSvgIcon('attach-filled', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/attach-filled.svg'));
398
- this.iconRegistry.addSvgIcon('send', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/send.svg'));
399
- this.iconRegistry.addSvgIcon('remove', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/remove-badge.svg'));
400
- this.iconRegistry.addSvgIcon('close', this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/close.svg'));
371
+ constructor() {
401
372
  effect(() => {
402
373
  const message = this.editMessage();
403
374
  const element = this.inputTextElement?.nativeElement;
@@ -641,13 +612,13 @@ class InputMessageComponent {
641
612
  return Number.isFinite(n) ? n : fb;
642
613
  }
643
614
  FileType = FileType;
644
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: InputMessageComponent, deps: [{ token: i1.MatIconRegistry }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
645
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.7", type: InputMessageComponent, isStandalone: true, selector: "app-input-message", inputs: { editMessage: { classPropertyName: "editMessage", publicName: "editMessage", isSignal: true, isRequired: false, transformFunction: null }, cancelEdit: { classPropertyName: "cancelEdit", publicName: "cancelEdit", isSignal: true, isRequired: false, transformFunction: null }, input_text: { classPropertyName: "input_text", publicName: "input_text", isSignal: true, isRequired: false, transformFunction: null }, files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null }, previews: { classPropertyName: "previews", publicName: "previews", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cancelEdit: "cancelEditChange", input_text: "input_textChange", files: "filesChange", previews: "previewsChange" }, viewQueries: [{ propertyName: "inputTextElement", first: true, predicate: ["inputText"], descendants: true }, { propertyName: "mirrorElement", first: true, predicate: ["mirror"], descendants: true }], ngImport: i0, template: "<section class=\"message\"\n [class.message--focus]=\"focused()\"\n [class.message--filled]=\"hasText()\"\n [class.message--sending]=\"sending()\">\n\n @if (isEditMode()) {\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button class=\"message__button message__button--attach\">\n <mat-icon svgIcon=\"icon-edit\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--edit\">\n </mat-icon>\n </button>\n\n <div class=\"message__edit-hint\">\n <p>{{ editMessage()?.content }}</p>\n </div>\n </div>\n\n <button class=\"message__button message__button--close\"\n type=\"button\"\n (click)=\"cancelEditMessage()\">\n <mat-icon svgIcon=\"close\" aria-hidden=\"true\" class=\"message__icon message__icon--close\"></mat-icon>\n </button>\n </div>\n }\n\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button type=\"button\"\n class=\"message__button message__button--attach\"\n [attr.aria-label]=\"'chat.attach' | transloco\"\n (click)=\"fileDialog.click()\">\n <mat-icon svgIcon=\"attach-filled\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--attach\">\n </mat-icon>\n </button>\n\n <input #fileDialog\n type=\"file\"\n class=\"hidden\"\n accept=\"image/*\"\n multiple\n (change)=\"inputFileChange($event)\">\n\n <div #inputText\n role=\"textbox\"\n class=\"message__input\"\n spellcheck=\"true\"\n contenteditable=\"true\"\n aria-multiline=\"true\"\n [attr.data-placeholder]=\"isEditMode()\n ? ('chat.edit_placeholder' | transloco)\n : ('chat.placeholder' | transloco)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (paste)=\"onPaste()\"\n (keydown)=\"onKeyDown($event)\">\n </div>\n\n <div #mirror class=\"message__input-mirror\" aria-hidden=\"true\"></div>\n\n <ng-content></ng-content>\n </div>\n\n <button class=\"message__button message__button--send\"\n type=\"button\"\n (click)=\"enterDown()\"\n [attr.aria-label]=\"'chat.send' | transloco\"\n [disabled]=\"!canSend()\">\n <mat-icon svgIcon=\"send\" aria-hidden=\"true\" class=\"message__icon message__icon--send\"></mat-icon>\n </button>\n </div>\n\n @if (previews().length) {\n <div class=\"message__files\">\n @for (item of previews(); track $index) {\n <div class=\"message__file\" [attr.data-kind]=\"item.originalKind\">\n <button type=\"button\"\n class=\"message__file-remove\"\n [attr.aria-label]=\"'chat.delete_file' | transloco\"\n (click)=\"removeFile($index, $event)\">\n <mat-icon svgIcon=\"remove\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--file\">\n </mat-icon>\n </button>\n\n <div class=\"message__file-media\" (click)=\"openPreview(item, $index)\">\n <img [src]=\"item.src\" [alt]=\"item.name\" class=\"message__file-img\"/>\n\n @if (item.originalKind === FileType.GIF) {\n <span class=\"message__file-badge message__file-badge--gif\">\n {{ 'chat.gif' | transloco }}\n </span>\n }\n </div>\n </div>\n }\n </div>\n }\n</section>\n\n\n", styles: [":host{display:block}.message{--lh: 24px;--max-rows: 8;display:flex;flex-direction:column;justify-content:space-between;background:#fff;border-top:1px solid #E1E7F8;padding:4px 8px;margin-top:8px;gap:8px;border-bottom-left-radius:16px;border-bottom-right-radius:16px;transition:box-shadow .18s ease,background-color .18s ease,border-color .18s ease}.message__wrap{display:flex;width:100%;min-width:0}.message__wrap--input{position:relative;display:flex;align-items:center;gap:12px;flex:1;min-width:0;padding:8px 0}.message__wrap--input:focus-within{border-color:#f8f9fa}.message__wrap--input::-webkit-scrollbar{width:4px;height:4px}.message__wrap--input::-webkit-scrollbar-track{background:transparent}.message__wrap--input::-webkit-scrollbar-thumb{background-color:#e9ecef;border-radius:4px;border:1px solid #E9ECEF}.message__wrap--input::-webkit-scrollbar-button{display:none}.message__input{flex:1 1 auto;min-height:var(--lh);line-height:var(--lh);font:400 16px/24px roboto,sans-serif;outline:none;border:none;background:transparent;color:#343a40;box-sizing:content-box;resize:none;white-space:pre-wrap;overflow-wrap:break-word;border-radius:8px;caret-color:#3c46b9;transition:height .16s ease;padding:0 4px 0 0;overflow-y:auto;max-height:calc(var(--lh) * var(--max-rows))}.message__input:empty:before{content:attr(data-placeholder);color:#ced4da;pointer-events:none;display:inline-block;animation:subtle-rise .18s ease both}.message__input-mirror{position:absolute;visibility:hidden;pointer-events:none;z-index:-1;white-space:pre-wrap;overflow-wrap:break-word;word-break:normal}.message__button{cursor:pointer;background:none;border:none;transition:transform .12s ease,opacity .12s ease,background-color .12s ease}.message__button:active{transform:scale(.96)}.message__button:disabled{opacity:.45;pointer-events:none}.message__icon{display:inline-flex;width:22px;height:22px}.message__icon:not(.message__icon--file):hover{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(93%) contrast(91%)}.message__icon--focus,.message__icon--filled{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(93%) contrast(91%)}.message__icon--edit{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(73%) contrast(99%)}.message__icon--close{filter:invert(1%) sepia(1%) saturate(1%) hue-rotate(100deg) brightness(100%) contrast(30%)}.message__files{display:flex;flex-wrap:wrap;gap:8px}.message__file{position:relative;width:40px;height:40px;flex:0 0 auto;overflow:visible}.message__file-media{width:100%;height:100%;border-radius:8px;overflow:hidden;cursor:pointer;position:relative;background:#f8f9fa}.message__file-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}.message__file-badge{position:absolute;left:6px;top:6px;z-index:2;display:inline-flex;align-items:center;justify-content:center;height:18px;padding:0 6px;border-radius:4px;font:400 16px/24px roboto,sans-serif;background:#0009;color:#fff;letter-spacing:.3px;line-height:1}.message__file-badge--video{width:28px;height:28px;padding:0;left:50%;top:50%;transform:translate(-50%,-50%);border-radius:50%;background:#00000073}.message__file-badge--video mat-icon{width:18px;height:18px;filter:invert(100%)}.message__file-badge--gif{font-weight:700}.message__file-duration{position:absolute;right:6px;bottom:6px;background:#0009;color:#fff;border-radius:4px;padding:1px;font:400 16px/24px roboto,sans-serif;z-index:2px;line-height:1.1}.message__file-remove{position:absolute;top:-6px;right:-6px;width:16px;height:16px;padding:0;border:none;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;z-index:3;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease}.message__file-remove:hover{transform:scale(1.05)}.message__file-remove:active{transform:scale(.96)}.message__file-remove .message__icon--file{width:14px;height:14px}.message__edit-hint{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:flex;align-items:center;gap:8px;border-radius:4px;border-left:2px solid #4656CA;padding:4px 8px}.message__edit-hint p{color:#ced4da;font:400 16px/24px roboto,sans-serif;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hidden{position:absolute;opacity:0;width:0;height:0;pointer-events:none}@keyframes subtle-rise{0%{transform:translateY(2px);opacity:.6}to{transform:translateY(0);opacity:1}}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
615
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: InputMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
616
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.7", type: InputMessageComponent, isStandalone: true, selector: "app-input-message", inputs: { editMessage: { classPropertyName: "editMessage", publicName: "editMessage", isSignal: true, isRequired: false, transformFunction: null }, cancelEdit: { classPropertyName: "cancelEdit", publicName: "cancelEdit", isSignal: true, isRequired: false, transformFunction: null }, input_text: { classPropertyName: "input_text", publicName: "input_text", isSignal: true, isRequired: false, transformFunction: null }, files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null }, previews: { classPropertyName: "previews", publicName: "previews", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cancelEdit: "cancelEditChange", input_text: "input_textChange", files: "filesChange", previews: "previewsChange" }, viewQueries: [{ propertyName: "inputTextElement", first: true, predicate: ["inputText"], descendants: true }, { propertyName: "mirrorElement", first: true, predicate: ["mirror"], descendants: true }], ngImport: i0, template: "<section class=\"message\"\n [class.message--focus]=\"focused()\"\n [class.message--filled]=\"hasText()\"\n [class.message--sending]=\"sending()\">\n\n @if (isEditMode()) {\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button class=\"message__button message__button--attach\">\n <img ngSrc=\"assets/ngx-parl/icons/icon-edit.svg\"\n class=\"message__icon message__icon--edit\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <div class=\"message__edit-hint\">\n <p>{{ editMessage()?.content }}</p>\n </div>\n </div>\n\n <button class=\"message__button message__button--close\"\n type=\"button\"\n (click)=\"cancelEditMessage()\">\n <img ngSrc=\"assets/ngx-parl/icons/close.svg\"\n class=\"message__icon message__icon--close\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n </div>\n }\n\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button type=\"button\"\n class=\"message__button message__button--attach\"\n [attr.aria-label]=\"'chat.attach' | transloco\"\n (click)=\"fileDialog.click()\">\n <img ngSrc=\"assets/ngx-parl/icons/attach-filled.svg\"\n class=\"message__icon message__icon--attach\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <input #fileDialog\n type=\"file\"\n class=\"hidden\"\n accept=\"image/*\"\n multiple\n (change)=\"inputFileChange($event)\">\n\n <div #inputText\n role=\"textbox\"\n class=\"message__input\"\n spellcheck=\"true\"\n contenteditable=\"true\"\n aria-multiline=\"true\"\n [attr.data-placeholder]=\"isEditMode()\n ? ('chat.edit_placeholder' | transloco)\n : ('chat.placeholder' | transloco)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (paste)=\"onPaste()\"\n (keydown)=\"onKeyDown($event)\">\n </div>\n\n <div #mirror class=\"message__input-mirror\" aria-hidden=\"true\"></div>\n\n <ng-content></ng-content>\n </div>\n\n <button class=\"message__button message__button--send\"\n type=\"button\"\n (click)=\"enterDown()\"\n [attr.aria-label]=\"'chat.send' | transloco\"\n [disabled]=\"!canSend()\">\n <img ngSrc=\"assets/ngx-parl/icons/send.svg\"\n class=\"message__icon message__icon--send\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n\n </button>\n </div>\n\n @if (previews().length) {\n <div class=\"message__files\">\n @for (item of previews(); track $index) {\n <div class=\"message__file\" [attr.data-kind]=\"item.originalKind\">\n <button type=\"button\"\n class=\"message__file-remove\"\n [attr.aria-label]=\"'chat.delete_file' | transloco\"\n (click)=\"removeFile($index, $event)\">\n <img ngSrc=\"assets/ngx-parl/icons/remove.svg\"\n class=\"message__icon message__icon--file\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <div class=\"message__file-media\" (click)=\"openPreview(item, $index)\">\n <img [src]=\"item.src\" [alt]=\"item.name\" class=\"message__file-img\"/>\n\n @if (item.originalKind === FileType.GIF) {\n <span class=\"message__file-badge message__file-badge--gif\">\n {{ 'chat.gif' | transloco }}\n </span>\n }\n </div>\n </div>\n }\n </div>\n }\n</section>\n\n\n", styles: [":host{display:block}.message{--lh: 24px;--max-rows: 8;display:flex;flex-direction:column;justify-content:space-between;background:#fff;border-top:1px solid #E1E7F8;padding:4px 8px;margin-top:8px;gap:8px;border-bottom-left-radius:16px;border-bottom-right-radius:16px;transition:box-shadow .18s ease,background-color .18s ease,border-color .18s ease}.message__wrap{display:flex;width:100%;min-width:0}.message__wrap--input{position:relative;display:flex;align-items:center;gap:12px;flex:1;min-width:0;padding:8px 0}.message__wrap--input:focus-within{border-color:#f8f9fa}.message__wrap--input::-webkit-scrollbar{width:4px;height:4px}.message__wrap--input::-webkit-scrollbar-track{background:transparent}.message__wrap--input::-webkit-scrollbar-thumb{background-color:#e9ecef;border-radius:4px;border:1px solid #E9ECEF}.message__wrap--input::-webkit-scrollbar-button{display:none}.message__input{flex:1 1 auto;min-height:var(--lh);line-height:var(--lh);font:400 16px/24px roboto,sans-serif;outline:none;border:none;background:transparent;color:#343a40;box-sizing:content-box;resize:none;white-space:pre-wrap;overflow-wrap:break-word;border-radius:8px;caret-color:#3c46b9;transition:height .16s ease;padding:0 4px 0 0;overflow-y:auto;max-height:calc(var(--lh) * var(--max-rows))}.message__input:empty:before{content:attr(data-placeholder);color:#ced4da;pointer-events:none;display:inline-block;animation:subtle-rise .18s ease both}.message__input-mirror{position:absolute;visibility:hidden;pointer-events:none;z-index:-1;white-space:pre-wrap;overflow-wrap:break-word;word-break:normal}.message__button{cursor:pointer;background:none;border:none;transition:transform .12s ease,opacity .12s ease,background-color .12s ease}.message__button:active{transform:scale(.96)}.message__button:disabled{opacity:.45;pointer-events:none}.message__icon{display:inline-flex;width:22px;height:22px}.message__icon:not(.message__icon--file):hover{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(93%) contrast(91%)}.message__icon--focus,.message__icon--filled{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(93%) contrast(91%)}.message__icon--edit{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(73%) contrast(99%)}.message__icon--close{filter:invert(1%) sepia(1%) saturate(1%) hue-rotate(100deg) brightness(100%) contrast(30%)}.message__files{display:flex;flex-wrap:wrap;gap:8px}.message__file{position:relative;width:40px;height:40px;flex:0 0 auto;overflow:visible}.message__file-media{width:100%;height:100%;border-radius:8px;overflow:hidden;cursor:pointer;position:relative;background:#f8f9fa}.message__file-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}.message__file-badge{position:absolute;left:6px;top:6px;z-index:2;display:inline-flex;align-items:center;justify-content:center;height:18px;padding:0 6px;border-radius:4px;font:400 16px/24px roboto,sans-serif;background:#0009;color:#fff;letter-spacing:.3px;line-height:1}.message__file-badge--video{width:28px;height:28px;padding:0;left:50%;top:50%;transform:translate(-50%,-50%);border-radius:50%;background:#00000073}.message__file-badge--video img{width:18px;height:18px;filter:invert(100%)}.message__file-badge--gif{font-weight:700}.message__file-duration{position:absolute;right:6px;bottom:6px;background:#0009;color:#fff;border-radius:4px;padding:1px;font:400 16px/24px roboto,sans-serif;z-index:2px;line-height:1.1}.message__file-remove{position:absolute;top:-6px;right:-6px;width:16px;height:16px;padding:0;border:none;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;z-index:3;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease}.message__file-remove:hover{transform:scale(1.05)}.message__file-remove:active{transform:scale(.96)}.message__file-remove .message__icon--file{width:14px;height:14px}.message__edit-hint{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:flex;align-items:center;gap:8px;border-radius:4px;border-left:2px solid #4656CA;padding:4px 8px}.message__edit-hint p{color:#ced4da;font:400 16px/24px roboto,sans-serif;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hidden{position:absolute;opacity:0;width:0;height:0;pointer-events:none}@keyframes subtle-rise{0%{transform:translateY(2px);opacity:.6}to{transform:translateY(0);opacity:1}}\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: "pipe", type: TranslocoPipe, name: "transloco" }] });
646
617
  }
647
618
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: InputMessageComponent, decorators: [{
648
619
  type: Component,
649
- args: [{ selector: 'app-input-message', imports: [MatIcon, TranslocoPipe], standalone: true, template: "<section class=\"message\"\n [class.message--focus]=\"focused()\"\n [class.message--filled]=\"hasText()\"\n [class.message--sending]=\"sending()\">\n\n @if (isEditMode()) {\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button class=\"message__button message__button--attach\">\n <mat-icon svgIcon=\"icon-edit\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--edit\">\n </mat-icon>\n </button>\n\n <div class=\"message__edit-hint\">\n <p>{{ editMessage()?.content }}</p>\n </div>\n </div>\n\n <button class=\"message__button message__button--close\"\n type=\"button\"\n (click)=\"cancelEditMessage()\">\n <mat-icon svgIcon=\"close\" aria-hidden=\"true\" class=\"message__icon message__icon--close\"></mat-icon>\n </button>\n </div>\n }\n\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button type=\"button\"\n class=\"message__button message__button--attach\"\n [attr.aria-label]=\"'chat.attach' | transloco\"\n (click)=\"fileDialog.click()\">\n <mat-icon svgIcon=\"attach-filled\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--attach\">\n </mat-icon>\n </button>\n\n <input #fileDialog\n type=\"file\"\n class=\"hidden\"\n accept=\"image/*\"\n multiple\n (change)=\"inputFileChange($event)\">\n\n <div #inputText\n role=\"textbox\"\n class=\"message__input\"\n spellcheck=\"true\"\n contenteditable=\"true\"\n aria-multiline=\"true\"\n [attr.data-placeholder]=\"isEditMode()\n ? ('chat.edit_placeholder' | transloco)\n : ('chat.placeholder' | transloco)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (paste)=\"onPaste()\"\n (keydown)=\"onKeyDown($event)\">\n </div>\n\n <div #mirror class=\"message__input-mirror\" aria-hidden=\"true\"></div>\n\n <ng-content></ng-content>\n </div>\n\n <button class=\"message__button message__button--send\"\n type=\"button\"\n (click)=\"enterDown()\"\n [attr.aria-label]=\"'chat.send' | transloco\"\n [disabled]=\"!canSend()\">\n <mat-icon svgIcon=\"send\" aria-hidden=\"true\" class=\"message__icon message__icon--send\"></mat-icon>\n </button>\n </div>\n\n @if (previews().length) {\n <div class=\"message__files\">\n @for (item of previews(); track $index) {\n <div class=\"message__file\" [attr.data-kind]=\"item.originalKind\">\n <button type=\"button\"\n class=\"message__file-remove\"\n [attr.aria-label]=\"'chat.delete_file' | transloco\"\n (click)=\"removeFile($index, $event)\">\n <mat-icon svgIcon=\"remove\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--file\">\n </mat-icon>\n </button>\n\n <div class=\"message__file-media\" (click)=\"openPreview(item, $index)\">\n <img [src]=\"item.src\" [alt]=\"item.name\" class=\"message__file-img\"/>\n\n @if (item.originalKind === FileType.GIF) {\n <span class=\"message__file-badge message__file-badge--gif\">\n {{ 'chat.gif' | transloco }}\n </span>\n }\n </div>\n </div>\n }\n </div>\n }\n</section>\n\n\n", styles: [":host{display:block}.message{--lh: 24px;--max-rows: 8;display:flex;flex-direction:column;justify-content:space-between;background:#fff;border-top:1px solid #E1E7F8;padding:4px 8px;margin-top:8px;gap:8px;border-bottom-left-radius:16px;border-bottom-right-radius:16px;transition:box-shadow .18s ease,background-color .18s ease,border-color .18s ease}.message__wrap{display:flex;width:100%;min-width:0}.message__wrap--input{position:relative;display:flex;align-items:center;gap:12px;flex:1;min-width:0;padding:8px 0}.message__wrap--input:focus-within{border-color:#f8f9fa}.message__wrap--input::-webkit-scrollbar{width:4px;height:4px}.message__wrap--input::-webkit-scrollbar-track{background:transparent}.message__wrap--input::-webkit-scrollbar-thumb{background-color:#e9ecef;border-radius:4px;border:1px solid #E9ECEF}.message__wrap--input::-webkit-scrollbar-button{display:none}.message__input{flex:1 1 auto;min-height:var(--lh);line-height:var(--lh);font:400 16px/24px roboto,sans-serif;outline:none;border:none;background:transparent;color:#343a40;box-sizing:content-box;resize:none;white-space:pre-wrap;overflow-wrap:break-word;border-radius:8px;caret-color:#3c46b9;transition:height .16s ease;padding:0 4px 0 0;overflow-y:auto;max-height:calc(var(--lh) * var(--max-rows))}.message__input:empty:before{content:attr(data-placeholder);color:#ced4da;pointer-events:none;display:inline-block;animation:subtle-rise .18s ease both}.message__input-mirror{position:absolute;visibility:hidden;pointer-events:none;z-index:-1;white-space:pre-wrap;overflow-wrap:break-word;word-break:normal}.message__button{cursor:pointer;background:none;border:none;transition:transform .12s ease,opacity .12s ease,background-color .12s ease}.message__button:active{transform:scale(.96)}.message__button:disabled{opacity:.45;pointer-events:none}.message__icon{display:inline-flex;width:22px;height:22px}.message__icon:not(.message__icon--file):hover{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(93%) contrast(91%)}.message__icon--focus,.message__icon--filled{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(93%) contrast(91%)}.message__icon--edit{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(73%) contrast(99%)}.message__icon--close{filter:invert(1%) sepia(1%) saturate(1%) hue-rotate(100deg) brightness(100%) contrast(30%)}.message__files{display:flex;flex-wrap:wrap;gap:8px}.message__file{position:relative;width:40px;height:40px;flex:0 0 auto;overflow:visible}.message__file-media{width:100%;height:100%;border-radius:8px;overflow:hidden;cursor:pointer;position:relative;background:#f8f9fa}.message__file-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}.message__file-badge{position:absolute;left:6px;top:6px;z-index:2;display:inline-flex;align-items:center;justify-content:center;height:18px;padding:0 6px;border-radius:4px;font:400 16px/24px roboto,sans-serif;background:#0009;color:#fff;letter-spacing:.3px;line-height:1}.message__file-badge--video{width:28px;height:28px;padding:0;left:50%;top:50%;transform:translate(-50%,-50%);border-radius:50%;background:#00000073}.message__file-badge--video mat-icon{width:18px;height:18px;filter:invert(100%)}.message__file-badge--gif{font-weight:700}.message__file-duration{position:absolute;right:6px;bottom:6px;background:#0009;color:#fff;border-radius:4px;padding:1px;font:400 16px/24px roboto,sans-serif;z-index:2px;line-height:1.1}.message__file-remove{position:absolute;top:-6px;right:-6px;width:16px;height:16px;padding:0;border:none;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;z-index:3;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease}.message__file-remove:hover{transform:scale(1.05)}.message__file-remove:active{transform:scale(.96)}.message__file-remove .message__icon--file{width:14px;height:14px}.message__edit-hint{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:flex;align-items:center;gap:8px;border-radius:4px;border-left:2px solid #4656CA;padding:4px 8px}.message__edit-hint p{color:#ced4da;font:400 16px/24px roboto,sans-serif;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hidden{position:absolute;opacity:0;width:0;height:0;pointer-events:none}@keyframes subtle-rise{0%{transform:translateY(2px);opacity:.6}to{transform:translateY(0);opacity:1}}\n"] }]
650
- }], ctorParameters: () => [{ type: i1.MatIconRegistry }, { type: i2.DomSanitizer }], propDecorators: { inputTextElement: [{
620
+ args: [{ selector: 'app-input-message', imports: [TranslocoPipe, NgOptimizedImage], standalone: true, template: "<section class=\"message\"\n [class.message--focus]=\"focused()\"\n [class.message--filled]=\"hasText()\"\n [class.message--sending]=\"sending()\">\n\n @if (isEditMode()) {\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button class=\"message__button message__button--attach\">\n <img ngSrc=\"assets/ngx-parl/icons/icon-edit.svg\"\n class=\"message__icon message__icon--edit\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <div class=\"message__edit-hint\">\n <p>{{ editMessage()?.content }}</p>\n </div>\n </div>\n\n <button class=\"message__button message__button--close\"\n type=\"button\"\n (click)=\"cancelEditMessage()\">\n <img ngSrc=\"assets/ngx-parl/icons/close.svg\"\n class=\"message__icon message__icon--close\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n </div>\n }\n\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button type=\"button\"\n class=\"message__button message__button--attach\"\n [attr.aria-label]=\"'chat.attach' | transloco\"\n (click)=\"fileDialog.click()\">\n <img ngSrc=\"assets/ngx-parl/icons/attach-filled.svg\"\n class=\"message__icon message__icon--attach\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <input #fileDialog\n type=\"file\"\n class=\"hidden\"\n accept=\"image/*\"\n multiple\n (change)=\"inputFileChange($event)\">\n\n <div #inputText\n role=\"textbox\"\n class=\"message__input\"\n spellcheck=\"true\"\n contenteditable=\"true\"\n aria-multiline=\"true\"\n [attr.data-placeholder]=\"isEditMode()\n ? ('chat.edit_placeholder' | transloco)\n : ('chat.placeholder' | transloco)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (paste)=\"onPaste()\"\n (keydown)=\"onKeyDown($event)\">\n </div>\n\n <div #mirror class=\"message__input-mirror\" aria-hidden=\"true\"></div>\n\n <ng-content></ng-content>\n </div>\n\n <button class=\"message__button message__button--send\"\n type=\"button\"\n (click)=\"enterDown()\"\n [attr.aria-label]=\"'chat.send' | transloco\"\n [disabled]=\"!canSend()\">\n <img ngSrc=\"assets/ngx-parl/icons/send.svg\"\n class=\"message__icon message__icon--send\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n\n </button>\n </div>\n\n @if (previews().length) {\n <div class=\"message__files\">\n @for (item of previews(); track $index) {\n <div class=\"message__file\" [attr.data-kind]=\"item.originalKind\">\n <button type=\"button\"\n class=\"message__file-remove\"\n [attr.aria-label]=\"'chat.delete_file' | transloco\"\n (click)=\"removeFile($index, $event)\">\n <img ngSrc=\"assets/ngx-parl/icons/remove.svg\"\n class=\"message__icon message__icon--file\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <div class=\"message__file-media\" (click)=\"openPreview(item, $index)\">\n <img [src]=\"item.src\" [alt]=\"item.name\" class=\"message__file-img\"/>\n\n @if (item.originalKind === FileType.GIF) {\n <span class=\"message__file-badge message__file-badge--gif\">\n {{ 'chat.gif' | transloco }}\n </span>\n }\n </div>\n </div>\n }\n </div>\n }\n</section>\n\n\n", styles: [":host{display:block}.message{--lh: 24px;--max-rows: 8;display:flex;flex-direction:column;justify-content:space-between;background:#fff;border-top:1px solid #E1E7F8;padding:4px 8px;margin-top:8px;gap:8px;border-bottom-left-radius:16px;border-bottom-right-radius:16px;transition:box-shadow .18s ease,background-color .18s ease,border-color .18s ease}.message__wrap{display:flex;width:100%;min-width:0}.message__wrap--input{position:relative;display:flex;align-items:center;gap:12px;flex:1;min-width:0;padding:8px 0}.message__wrap--input:focus-within{border-color:#f8f9fa}.message__wrap--input::-webkit-scrollbar{width:4px;height:4px}.message__wrap--input::-webkit-scrollbar-track{background:transparent}.message__wrap--input::-webkit-scrollbar-thumb{background-color:#e9ecef;border-radius:4px;border:1px solid #E9ECEF}.message__wrap--input::-webkit-scrollbar-button{display:none}.message__input{flex:1 1 auto;min-height:var(--lh);line-height:var(--lh);font:400 16px/24px roboto,sans-serif;outline:none;border:none;background:transparent;color:#343a40;box-sizing:content-box;resize:none;white-space:pre-wrap;overflow-wrap:break-word;border-radius:8px;caret-color:#3c46b9;transition:height .16s ease;padding:0 4px 0 0;overflow-y:auto;max-height:calc(var(--lh) * var(--max-rows))}.message__input:empty:before{content:attr(data-placeholder);color:#ced4da;pointer-events:none;display:inline-block;animation:subtle-rise .18s ease both}.message__input-mirror{position:absolute;visibility:hidden;pointer-events:none;z-index:-1;white-space:pre-wrap;overflow-wrap:break-word;word-break:normal}.message__button{cursor:pointer;background:none;border:none;transition:transform .12s ease,opacity .12s ease,background-color .12s ease}.message__button:active{transform:scale(.96)}.message__button:disabled{opacity:.45;pointer-events:none}.message__icon{display:inline-flex;width:22px;height:22px}.message__icon:not(.message__icon--file):hover{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(93%) contrast(91%)}.message__icon--focus,.message__icon--filled{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(93%) contrast(91%)}.message__icon--edit{filter:invert(33%) sepia(79%) saturate(2933%) hue-rotate(205deg) brightness(73%) contrast(99%)}.message__icon--close{filter:invert(1%) sepia(1%) saturate(1%) hue-rotate(100deg) brightness(100%) contrast(30%)}.message__files{display:flex;flex-wrap:wrap;gap:8px}.message__file{position:relative;width:40px;height:40px;flex:0 0 auto;overflow:visible}.message__file-media{width:100%;height:100%;border-radius:8px;overflow:hidden;cursor:pointer;position:relative;background:#f8f9fa}.message__file-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}.message__file-badge{position:absolute;left:6px;top:6px;z-index:2;display:inline-flex;align-items:center;justify-content:center;height:18px;padding:0 6px;border-radius:4px;font:400 16px/24px roboto,sans-serif;background:#0009;color:#fff;letter-spacing:.3px;line-height:1}.message__file-badge--video{width:28px;height:28px;padding:0;left:50%;top:50%;transform:translate(-50%,-50%);border-radius:50%;background:#00000073}.message__file-badge--video img{width:18px;height:18px;filter:invert(100%)}.message__file-badge--gif{font-weight:700}.message__file-duration{position:absolute;right:6px;bottom:6px;background:#0009;color:#fff;border-radius:4px;padding:1px;font:400 16px/24px roboto,sans-serif;z-index:2px;line-height:1.1}.message__file-remove{position:absolute;top:-6px;right:-6px;width:16px;height:16px;padding:0;border:none;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;z-index:3;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease}.message__file-remove:hover{transform:scale(1.05)}.message__file-remove:active{transform:scale(.96)}.message__file-remove .message__icon--file{width:14px;height:14px}.message__edit-hint{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:flex;align-items:center;gap:8px;border-radius:4px;border-left:2px solid #4656CA;padding:4px 8px}.message__edit-hint p{color:#ced4da;font:400 16px/24px roboto,sans-serif;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hidden{position:absolute;opacity:0;width:0;height:0;pointer-events:none}@keyframes subtle-rise{0%{transform:translateY(2px);opacity:.6}to{transform:translateY(0);opacity:1}}\n"] }]
621
+ }], ctorParameters: () => [], propDecorators: { inputTextElement: [{
651
622
  type: ViewChild,
652
623
  args: ['inputText', { static: false }]
653
624
  }], mirrorElement: [{
@@ -812,8 +783,8 @@ class NgxParlComponent {
812
783
  return this;
813
784
  }
814
785
  FlowTheme = FlowTheme;
815
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: NgxParlComponent, deps: [{ token: UtilsService }, { token: i2$1.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
816
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.7", type: NgxParlComponent, isStandalone: true, selector: "ngx-parl", inputs: { 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 }, hideHandler: { classPropertyName: "hideHandler", publicName: "hideHandler", isSignal: true, isRequired: false, transformFunction: null }, closeHandler: { classPropertyName: "closeHandler", publicName: "closeHandler", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { messageList: "messageListChange", messageUpdate: "messageUpdateChange", selectedForEdit: "selectedForEditChange" }, providers: [], 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\">{{ 'chat.title' | transloco }} {{ incomingUser() }}</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\" priority\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\" priority\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\">\n <app-chat-flow [messageListInput]=\"messageList()\" [(selectedForEdit)]=\"selectedForEdit\"></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;display:flex;align-items:center;justify-content:space-between;padding:0 16px;gap:12px;border-top-left-radius:16px;border-top-right-radius:16px}.modal-chat__hide-block{width:48px;color:#5a72d7}.modal-chat__title .modal-chat__heading{color:#fff;font:500 16px/24px roboto,sans-serif}.modal-chat__actions{display:flex;gap:8px}.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column}.modal-chat__content app-chat-flow{flex:1 1 auto;min-height:0px;overflow:auto;display:flex;align-items:flex-end}.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: ["messageListInput", "selectedForEdit"], outputs: ["messageListInputChange", "selectedForEditChange"] }, { kind: "component", type: InputMessageComponent, selector: "app-input-message", inputs: ["editMessage", "cancelEdit", "input_text", "files", "previews"], outputs: ["cancelEditChange", "input_textChange", "filesChange", "previewsChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2$1.TranslocoPipe, name: "transloco" }] });
786
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: NgxParlComponent, deps: [{ token: UtilsService }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
787
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.7", type: NgxParlComponent, isStandalone: true, selector: "ngx-parl", inputs: { 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 }, hideHandler: { classPropertyName: "hideHandler", publicName: "hideHandler", isSignal: true, isRequired: false, transformFunction: null }, closeHandler: { classPropertyName: "closeHandler", publicName: "closeHandler", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { messageList: "messageListChange", messageUpdate: "messageUpdateChange", selectedForEdit: "selectedForEditChange" }, providers: [], 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\">{{ 'chat.title' | transloco }} {{ incomingUser() }}</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\" priority\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\" priority\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\">\n <app-chat-flow [messageListInput]=\"messageList()\" [(selectedForEdit)]=\"selectedForEdit\"></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;display:flex;align-items:center;justify-content:space-between;padding:0 16px;gap:12px;border-top-left-radius:16px;border-top-right-radius:16px}.modal-chat__hide-block{width:48px;color:#5a72d7}.modal-chat__title .modal-chat__heading{color:#fff;font:500 16px/24px roboto,sans-serif}.modal-chat__actions{display:flex;gap:8px}.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column}.modal-chat__content app-chat-flow{flex:1 1 auto;min-height:0px;overflow:auto;display:flex;align-items:flex-end}.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: ["messageListInput", "selectedForEdit"], outputs: ["messageListInputChange", "selectedForEditChange"] }, { kind: "component", type: InputMessageComponent, selector: "app-input-message", inputs: ["editMessage", "cancelEdit", "input_text", "files", "previews"], outputs: ["cancelEditChange", "input_textChange", "filesChange", "previewsChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
817
788
  }
818
789
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImport: i0, type: NgxParlComponent, decorators: [{
819
790
  type: Component,
@@ -822,7 +793,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.7", ngImpor
822
793
  TranslocoModule,
823
794
  TranslocoPipe
824
795
  ], 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\">{{ 'chat.title' | transloco }} {{ incomingUser() }}</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\" priority\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\" priority\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\">\n <app-chat-flow [messageListInput]=\"messageList()\" [(selectedForEdit)]=\"selectedForEdit\"></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;display:flex;align-items:center;justify-content:space-between;padding:0 16px;gap:12px;border-top-left-radius:16px;border-top-right-radius:16px}.modal-chat__hide-block{width:48px;color:#5a72d7}.modal-chat__title .modal-chat__heading{color:#fff;font:500 16px/24px roboto,sans-serif}.modal-chat__actions{display:flex;gap:8px}.modal-chat__content{flex:1 1 auto;display:flex;flex-direction:column}.modal-chat__content app-chat-flow{flex:1 1 auto;min-height:0px;overflow:auto;display:flex;align-items:flex-end}.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"] }]
825
- }], ctorParameters: () => [{ type: UtilsService }, { type: i2$1.TranslocoService }], propDecorators: { 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"] }], hideHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideHandler", required: false }] }], closeHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeHandler", required: false }] }] } });
796
+ }], ctorParameters: () => [{ type: UtilsService }, { type: i2.TranslocoService }], propDecorators: { 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"] }], hideHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideHandler", required: false }] }], closeHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeHandler", required: false }] }] } });
826
797
 
827
798
  var chat$1 = {
828
799
  title: "Telegram",
@@ -1 +1 @@
1
- {"version":3,"file":"trixwell-ngx-parl.mjs","sources":["../../../projects/ngx-parl/src/lib/core/entity/chat.ts","../../../projects/ngx-parl/src/lib/core/components/chat-message/chat-message.ts","../../../projects/ngx-parl/src/lib/core/components/chat-message/chat-message.html","../../../projects/ngx-parl/src/lib/core/service/utils/utils.ts","../../../projects/ngx-parl/src/lib/core/pipes/chat-start-day-pipe.ts","../../../projects/ngx-parl/src/lib/core/pipes/toggle-display-chat-start-day-pipe.ts","../../../projects/ngx-parl/src/lib/chat-flow/chat-flow.ts","../../../projects/ngx-parl/src/lib/chat-flow/chat-flow.html","../../../projects/ngx-parl/src/lib/core/entity/file.ts","../../../projects/ngx-parl/src/lib/input-message/input-message.ts","../../../projects/ngx-parl/src/lib/input-message/input-message.html","../../../projects/ngx-parl/src/lib/core/entity/theme.ts","../../../projects/ngx-parl/src/lib/ngx-parl/ngx-parl.ts","../../../projects/ngx-parl/src/lib/ngx-parl/ngx-parl.html","../../../projects/ngx-parl/src/assets/i18n/parl-transloco.loader.ts","../../../projects/ngx-parl/src/lib/ngx-parl.providers.ts","../../../projects/ngx-parl/src/trixwell-ngx-parl.ts"],"sourcesContent":["export class ChatMessage {\n public id: number;\n public chat_id: number;\n public cr_time: string;\n public type: ChatMessageType;\n public user: string;\n public content: string;\n public avatar: string | null;\n public file_path: string[] | null;\n public checked: boolean | null;\n\n public edit = false;\n\n constructor(data: ChatMessageDTO) {\n this.id = data.id;\n this.chat_id = data.chat_id;\n this.cr_time = data.cr_time;\n this.type = data.type;\n this.user = data.user;\n this.content = data.content;\n this.avatar = data.avatar ?? null;\n this.file_path = data.file_path ?? null;\n this.checked = data.checked ?? null;\n }\n\n get dateSimple(): string {\n const d = new Date(this.cr_time.replace(' ', 'T'));\n const dd = String(d.getDate()).padStart(2, '0');\n const mm = String(d.getMonth() + 1).padStart(2, '0');\n const yyyy = d.getFullYear();\n return `${dd}.${mm}.${yyyy}`;\n }\n\n get timeHHmm(): string {\n const d = new Date(this.cr_time.replace(' ', 'T'));\n const hh = String(d.getHours()).padStart(2, '0');\n const mm = String(d.getMinutes()).padStart(2, '0');\n return `${hh}:${mm}`;\n }\n}\n\nexport interface ChatMessageDTO {\n id: number;\n chat_id: number;\n cr_time: string; // ISO or 'YYYY-MM-DD HH:mm:ss'\n type: ChatMessageType;\n user: string;\n content: string;\n avatar?: string | null;\n file_path?: string[] | null;\n checked?: boolean | null;\n}\n\nexport type ChatMessageType = 'incoming' | 'outgoing';\n\nexport enum MessageType {\n Incoming = 'incoming',\n Outgoing = 'outgoing'\n}\n\nexport interface CurrMessage {\n id?: number;\n content: string;\n files?: string[];\n}\n","import {Component, computed, input, model} from '@angular/core';\nimport {DatePipe, NgClass, NgOptimizedImage} from '@angular/common';\nimport {MatIcon, MatIconRegistry} from '@angular/material/icon';\nimport {ChatMessage, MessageType} from '../../entity/chat';\nimport {DomSanitizer} from '@angular/platform-browser';\nimport {MatMenu, MatMenuItem, MatMenuTrigger} from '@angular/material/menu';\nimport {TranslocoPipe} from '@ngneat/transloco';\n\n@Component({\n selector: 'lib-chat-message',\n imports: [\n NgClass,\n NgOptimizedImage,\n MatIcon,\n DatePipe,\n MatMenu,\n MatMenuItem,\n MatMenuTrigger,\n TranslocoPipe,\n ],\n templateUrl: './chat-message.html',\n styleUrl: './chat-message.scss',\n standalone: true,\n})\n\nexport class ChatMessageComponent {\n public currentMessage = input.required<ChatMessage>();\n public edit = model<boolean>(false);\n\n public requestEdit = model<ChatMessage | null>(null);\n public requestDelete = model<number | null>(null);\n\n constructor(private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) {\n this.iconRegistry.addSvgIcon('checked-message',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/checked-message.svg'));\n this.iconRegistry.addSvgIcon('no-check',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/no-check.svg'));\n this.iconRegistry.addSvgIcon('trash',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/trash.svg'));\n this.iconRegistry.addSvgIcon('icon-edit',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/icon-edit.svg'));\n\n setTimeout(() => {\n this.currentMessage().checked = true;\n }, 600);\n }\n\n private normalizeSourcePath(sourcePath: string): string {\n const cleanedPath = (sourcePath ?? '').trim();\n if (!cleanedPath) {\n return '';\n }\n\n if (cleanedPath.startsWith('data:') || cleanedPath.startsWith('blob:') || /^https?:\\/\\//i.test(cleanedPath)) {\n return cleanedPath;\n }\n\n const assetsIndex = cleanedPath.indexOf('assets/');\n if (assetsIndex >= 0) {\n return '/' + cleanedPath.slice(assetsIndex);\n }\n\n return cleanedPath.replace(/^\\.{1,2}\\//, '/');\n }\n\n attachments = computed(() => {\n const message = this.currentMessage();\n const filePath = message.file_path;\n\n if (Array.isArray(filePath)) {\n return filePath.map(p => this.normalizeSourcePath(p)).filter(Boolean);\n }\n\n const rawFilePath = (filePath as unknown as string) ?? '';\n if (typeof rawFilePath !== 'string' || !rawFilePath.trim) {\n return [];\n }\n\n if (rawFilePath.trim().startsWith('[')) {\n try {\n const parsed = JSON.parse(rawFilePath);\n if (Array.isArray(parsed)) {\n return parsed\n .map(item => (typeof item === 'string' ? this.normalizeSourcePath(item) : ''))\n .filter(Boolean);\n }\n } catch {}\n }\n\n if (rawFilePath.startsWith('data:')) {\n return [rawFilePath];\n }\n\n if (rawFilePath.includes('|')) {\n return rawFilePath.split('|').map(p => this.normalizeSourcePath(p)).filter(Boolean);\n }\n if (rawFilePath.includes(',')) {\n return rawFilePath.split(',').map(p => this.normalizeSourcePath(p)).filter(Boolean);\n }\n\n return [];\n });\n\n avatarSrc = computed(() => {\n const message = this.currentMessage();\n const fallback = message.type === 'incoming'\n ? 'assets/ngx-parl/icons/avatar_anonym.svg'\n : 'assets/ngx-parl/icons/avatar_manager.svg';\n\n return message.avatar || fallback;\n });\n\n openContextMenu(event: Event, trigger: any) {\n event.preventDefault();\n event.stopPropagation();\n trigger.openMenu();\n\n return this;\n }\n\n editMessage(message: ChatMessage) {\n this.edit.set(true);\n this.requestEdit.set(message);\n\n return this;\n }\n\n deleteMessage(message: ChatMessage) {\n this.requestDelete.set(message.id);\n queueMicrotask(() => this.requestDelete.set(null));\n\n return this;\n }\n\n canDelete(message: ChatMessage): boolean {\n return message.type === this.messageType.Outgoing;\n }\n\n public readonly messageType = MessageType;\n}\n","<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 #menuTrigger=\"matMenuTrigger\"\n [matMenuTriggerFor]=\"messageMenu\"\n (contextmenu)=\"openContextMenu($event, menuTrigger)\"\n (keydown.shift.F10)=\"openContextMenu($event, menuTrigger)\">\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file) {\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\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\">{{ currentMessage().cr_time | date:'HH:mm' }}</time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().checked) {\n <mat-icon svgIcon=\"checked-message\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n } @else {\n <mat-icon svgIcon=\"no-check\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n }\n }\n </div>\n </div>\n </div>\n</div>\n\n<mat-menu #messageMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\" class=\"message__menu\">\n @if (currentMessage().type === messageType.Outgoing) {\n <button mat-menu-item (click)=\"editMessage(currentMessage())\">\n <mat-icon svgIcon=\"icon-edit\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n <span>{{ 'chat.edit' | transloco }}</span>\n </button>\n }\n @if (canDelete(currentMessage())) {\n <button mat-menu-item (click)=\"deleteMessage(currentMessage())\">\n <mat-icon svgIcon=\"trash\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\n <span>{{ 'chat.remove' | transloco }}</span>\n </button>\n }\n</mat-menu>\n","import {Injectable} from '@angular/core';\nimport {HttpClient} from '@angular/common/http';\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class UtilsService {\n\n constructor(protected http: HttpClient) {\n }\n\n langToLocale(lang: string): string {\n switch (lang) {\n case 'uk':\n return 'uk-UA';\n case 'en':\n default:\n return 'en-US';\n }\n }\n\n getLocalISODate(): string {\n const d = new Date();\n\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n\n const hours = String(d.getHours()).padStart(2, '0');\n const minutes = String(d.getMinutes()).padStart(2, '0');\n const seconds = String(d.getSeconds()).padStart(2, '0');\n\n return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport {DatePipe} from '@angular/common';\nimport {UtilsService} from '../service/utils/utils';\nimport {TranslocoService} from '@ngneat/transloco';\n\n@Pipe({\n name: 'chatStartDay'\n})\nexport class ChatStartDayPipe implements PipeTransform {\n constructor(protected utils: UtilsService, private transloco: TranslocoService) {}\n\n transform(value: string, format: string = 'd MMMM'): string {\n if (!value) {\n return '';\n }\n\n const locale = this.utils.langToLocale(this.transloco.getActiveLang());\n const datePipe = new DatePipe(locale);\n\n const valueDate = new Date(value);\n const today = new Date();\n\n const isToday = datePipe.transform(valueDate, 'shortDate') === datePipe.transform(today, 'shortDate');\n\n return isToday\n ? (locale.startsWith('uk') ? 'Сьогодні' : 'Today')\n : (datePipe.transform(valueDate, format) ?? '');\n }\n\n}\n","import {Pipe, PipeTransform} from '@angular/core';\nimport {DatePipe} from '@angular/common';\nimport {ChatMessage} from '../entity/chat';\nimport {UtilsService} from '../service/utils/utils';\nimport {TranslocoService} from '@ngneat/transloco';\n\n@Pipe({\n name: 'toggleDisplayChatStartDay'\n})\nexport class ToggleDisplayChatStartDayPipe implements PipeTransform {\n\n constructor(protected utils: UtilsService, private transloco: TranslocoService) {}\n\n transform(message: ChatMessage, messages: ChatMessage[], i: number): boolean {\n const locale = this.utils.langToLocale(this.transloco.getActiveLang());\n const datePipe = new DatePipe(locale);\n\n const prev = i > 0 ? messages[i - 1] : undefined;\n\n const currDay = datePipe.transform(new Date(message.cr_time), 'shortDate');\n const prevDay = prev ? datePipe.transform(new Date(prev.cr_time), 'shortDate') : undefined;\n\n return prev ? currDay !== prevDay : true;\n }\n}\n","import {Component, computed, effect, ElementRef, model, ViewChild,} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {ChatMessage} from '../core/entity/chat';\nimport {ChatMessageComponent} from '../core/components/chat-message/chat-message';\nimport {ChatStartDayPipe} from '../core/pipes/chat-start-day-pipe';\nimport {ToggleDisplayChatStartDayPipe} from '../core/pipes/toggle-display-chat-start-day-pipe';\nimport {TranslocoPipe} from '@ngneat/transloco';\nimport {MatIcon, MatIconRegistry} from '@angular/material/icon';\nimport {DomSanitizer} from '@angular/platform-browser';\n\n@Component({\n selector: 'app-chat-flow',\n imports: [\n FormsModule,\n ChatMessageComponent,\n ChatStartDayPipe,\n ToggleDisplayChatStartDayPipe,\n ChatMessageComponent,\n TranslocoPipe,\n MatIcon\n ],\n templateUrl: './chat-flow.html',\n styleUrl: './chat-flow.scss',\n standalone: true,\n})\n\nexport class ChatFlowComponent {\n @ViewChild('chatFlowRef', {static: true}) private flowRef!: ElementRef<HTMLElement>;\n\n public messageListInput = model.required<ChatMessage[]>();\n public messageList = computed(() => this.messageListInput());\n\n public selectedForEdit = model.required<ChatMessage | null>();\n\n constructor(private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) {\n this.iconRegistry.addSvgIcon('lucide_send',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/lucide_send.svg'));\n\n effect(() => {\n const length = this.messageList().length;\n if (length > 0) {\n queueMicrotask(() => this.scrollToBottomSmooth());\n }\n });\n }\n\n private scrollToBottomSmooth() {\n const element = this.flowRef?.nativeElement;\n if (!element) {\n return this;\n }\n element.scrollTo({top: element.scrollHeight, behavior: 'smooth'});\n\n return this;\n }\n\n startEdit(message: ChatMessage) {\n this.messageList().forEach(currMessage => {\n if (currMessage.id !== message.id && currMessage.edit) {\n currMessage.edit = false;\n }\n });\n\n message.edit = true;\n\n if (this.selectedForEdit()?.id === message.id) {\n this.selectedForEdit.set(null);\n queueMicrotask(() => this.selectedForEdit.set(message));\n } else {\n this.selectedForEdit.set(message);\n }\n\n return this;\n }\n\n onEditChange(id: number, isEdit: boolean) {\n const messageList = this.messageList().find(message => message.id === id);\n if (!messageList) {\n return this;\n }\n\n if (isEdit) {\n return this.startEdit(messageList);\n } else {\n messageList.edit = false;\n\n if (this.selectedForEdit()?.id === id) {\n this.selectedForEdit.set(null);\n }\n }\n\n return this;\n }\n\n onRequestEdit(message: ChatMessage | null) {\n if (message) {\n return this.startEdit(message);\n }\n this.selectedForEdit.set(null);\n\n return this;\n }\n\n onRequestDelete(messageId: number | null) {\n if (!messageId) {\n return this;\n }\n\n const updatedList = this.messageList().filter(m => m.id !== messageId);\n this.selectedForEdit.set(null);\n\n queueMicrotask(() => this.messageListInput.set(updatedList));\n\n return this;\n }\n\n trackByMessageId(_index: number, message: ChatMessage): string {\n // return message.id;\n return `${message.chat_id}-${message.type}-${message.id}`;\n }\n}\n","<div class=\"chat\">\n @if (messageList()) {\n <div class=\"chat__flow\" #chatFlowRef>\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 <lib-chat-message [currentMessage]=\"message\"\n [edit]=\"message.edit ?? false\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n }\n </div>\n } @else {\n <div class=\"chat__flow__empty\">\n <mat-icon svgIcon=\"lucide_send\" aria-hidden=\"true\" class=\"message__icon\"></mat-icon>\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","export class ImageFile {\n constructor(\n public id: string,\n public url: string,\n public cr_time: string,\n ) {}\n}\n\nexport type OriginalKind = 'image' | 'gif';\n\nexport interface PreviewItem {\n originalKind: OriginalKind;\n duration?: number;\n src: string;\n name: string;\n type: string;\n size: number;\n}\n\nexport enum FileType {\n IMAGE = 'image',\n GIF = 'gif'\n}\n","import {\n AfterViewInit,\n Component,\n computed,\n effect,\n ElementRef,\n input,\n model,\n OnDestroy,\n signal,\n ViewChild\n} from '@angular/core';\nimport {MatIcon, MatIconRegistry} from '@angular/material/icon';\nimport {DomSanitizer} from '@angular/platform-browser';\nimport {FileType, OriginalKind, PreviewItem} from '../core/entity/file';\nimport {TranslocoPipe} from '@ngneat/transloco';\nimport {ChatMessage, CurrMessage} from '../core/entity/chat';\n\n@Component({\n selector: 'app-input-message',\n imports: [MatIcon, TranslocoPipe],\n templateUrl: './input-message.html',\n styleUrl: './input-message.scss',\n standalone: true,\n})\n\nexport class InputMessageComponent implements AfterViewInit, OnDestroy {\n @ViewChild('inputText', {static: false}) inputTextElement!: ElementRef<HTMLDivElement>;\n @ViewChild('mirror', {static: false}) mirrorElement!: ElementRef<HTMLDivElement>;\n\n public editMessage = input<ChatMessage | { id: number; content: string; file_path?: string[] | null } | null>(null);\n\n public hasOriginalAttachments = computed(() => {\n const filePaths = this.editFilePaths();\n return filePaths.length > 0;\n });\n\n public hasNewAttachments = computed(() => (this.previews()?.length ?? 0) > 0);\n\n public cancelEdit = model<number | null>(null);\n public input_text = model<string | CurrMessage>('');\n\n public draft = signal<string>('');\n public focused = signal<boolean>(false);\n public sending = signal<boolean>(false);\n public hasText = computed(() => this.draft().trim().length > 0);\n\n public isEditMode = computed(() => !!this.editMessage());\n public canSend = computed(() =>\n this.hasText() ||\n this.hasNewAttachments() ||\n (this.isEditMode() && this.hasOriginalAttachments())\n );\n\n public files = model<File[]>([]);\n public previews = model<PreviewItem[]>([]);\n\n private lastHeightPx = 0;\n private lastRows = 1;\n private resizeRaf: number | null = null;\n\n constructor(private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) {\n this.iconRegistry.addSvgIcon('attach-filled',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/attach-filled.svg'));\n this.iconRegistry.addSvgIcon('send',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/send.svg'));\n this.iconRegistry.addSvgIcon('remove',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/remove-badge.svg'));\n this.iconRegistry.addSvgIcon('close',\n this.sanitizer.bypassSecurityTrustResourceUrl('assets/ngx-parl/icons/close.svg'));\n\n effect(() => {\n const message = this.editMessage();\n const element = this.inputTextElement?.nativeElement;\n\n if (!element) {\n return;\n }\n\n if (message) {\n const content = (message as any).content ?? '';\n this.draft.set(content);\n element.innerText = content;\n\n queueMicrotask(() => {\n this.autoResizeByRows();\n element.focus();\n this.focused.set(true);\n });\n }\n });\n }\n\n ngAfterViewInit() {\n const element = this.inputTextElement.nativeElement;\n element.style.transition = 'height 160ms ease';\n this.initMirror();\n\n const computedStyle = getComputedStyle(element);\n const lineHeight = this.cssNum(computedStyle.lineHeight, 24);\n\n element.style.height = `${lineHeight}px`;\n this.lastHeightPx = lineHeight;\n this.lastRows = 1;\n this.updateOverflow(1);\n\n requestAnimationFrame(() => {\n const {rows, nextHeightPx} = this.measureByMirror();\n element.style.height = `${nextHeightPx}px`;\n\n this.lastRows = rows;\n this.lastHeightPx = nextHeightPx;\n this.updateOverflow(rows);\n });\n }\n\n ngOnDestroy() {\n if (this.resizeRaf) {\n cancelAnimationFrame(this.resizeRaf);\n this.resizeRaf = null;\n }\n }\n\n private editFilePaths(): string[] {\n const message = this.editMessage();\n if (!message) {\n return [];\n }\n\n const file_path = (message as any).file_path;\n\n return Array.isArray(file_path) ? file_path : [];\n }\n\n private collectAttachmentSources(): string[] {\n return (this.previews() ?? []).map(p => p.src).filter(Boolean);\n }\n\n cancelEditMessage() {\n const message = this.editMessage();\n this.cancelEdit.set((message as any)?.id ?? null);\n queueMicrotask(() => this.cancelEdit.set(null));\n\n this.draft.set('');\n const element = this.inputTextElement?.nativeElement;\n\n if (element) {\n element.innerHTML = '';\n this.autoResizeByRows();\n element.focus();\n }\n\n return this;\n }\n\n enterDown() {\n const element = this.inputTextElement.nativeElement;\n const text = this.draft().trim();\n if (!this.canSend()) return this;\n\n this.sending.set(true);\n\n const files = this.collectAttachmentSources();\n const message = this.editMessage();\n\n if (message) {\n this.input_text.set({id: (message as any).id, content: text, files: files.length ? files : undefined});\n } else {\n this.input_text.set({content: text, files: files.length ? files : undefined});\n }\n\n this.draft.set('');\n element.innerHTML = '';\n this.files.set([]);\n this.previews.set([]);\n element.focus();\n this.autoResizeByRows();\n\n setTimeout(() => this.sending.set(false), 150);\n\n return this;\n }\n\n onFocus() {\n if (this.inputTextElement.nativeElement.innerHTML === '<br>') {\n this.inputTextElement.nativeElement.innerHTML = '';\n }\n this.focused.set(true);\n\n return this;\n }\n\n onBlur() {\n this.focused.set(false);\n\n return this;\n }\n\n onKeyDown(event: KeyboardEvent) {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n this.enterDown();\n\n return this;\n }\n queueMicrotask(() => this.autoResizeByRows());\n\n return this;\n }\n\n onInput() {\n this.draft.set(this.inputTextElement.nativeElement.innerText ?? '');\n this.autoResizeByRows();\n\n return this;\n }\n\n onPaste() {\n queueMicrotask(() => {\n this.draft.set(this.inputTextElement.nativeElement.innerText ?? '');\n this.autoResizeByRows();\n });\n\n return this;\n }\n\n inputFileChange(event: Event) {\n const inputEl = event.target as HTMLInputElement;\n const selected = inputEl.files;\n\n if (!selected?.length) {\n inputEl.value = '';\n\n return this;\n }\n\n const list = Array.from(selected).filter(f => (f.type || '').startsWith('image/'));\n if (!list.length) {\n inputEl.value = '';\n\n return this;\n }\n\n this.files.set([...(this.files() ?? []), ...list]);\n\n Promise.all(\n list.map(async f => {\n const src = await this.readFileAsDataURL(f);\n const originalKind: OriginalKind = (f.type || '') === 'image/gif' ? FileType.GIF : FileType.IMAGE;\n return <PreviewItem>{src, originalKind, name: f.name, type: f.type || '', size: f.size};\n })\n )\n .then(items => this.previews.set([...(this.previews() ?? []), ...items]))\n .finally(() => (inputEl.value = ''));\n\n return this;\n }\n\n removeFile(index: number, event?: MouseEvent) {\n event?.stopPropagation();\n event?.preventDefault();\n\n const previews = [...(this.previews() ?? [])];\n previews.splice(index, 1);\n this.previews.set(previews);\n\n const filesArr = [...(this.files() ?? [])];\n if (index >= 0 && index < filesArr.length) {\n filesArr.splice(index, 1);\n this.files.set(filesArr);\n }\n return this;\n }\n\n openPreview(_item: PreviewItem, _index: number) {\n return this;\n }\n\n private autoResizeByRows() {\n const element = this.inputTextElement.nativeElement;\n const {rows, nextHeightPx} = this.measureByMirror();\n\n if (rows === this.lastRows) {\n this.updateOverflow(rows);\n\n return this;\n }\n\n if (this.resizeRaf) {\n cancelAnimationFrame(this.resizeRaf);\n }\n\n element.style.height = `${this.lastHeightPx}px`;\n\n this.resizeRaf = requestAnimationFrame(() => {\n element.style.height = `${nextHeightPx}px`;\n this.lastHeightPx = nextHeightPx;\n this.lastRows = rows;\n this.updateOverflow(rows);\n });\n\n return this;\n }\n\n private measureByMirror(): { rows: number; nextHeightPx: number } {\n const inputEl = this.inputTextElement.nativeElement;\n const mirrorEl = this.mirrorElement.nativeElement;\n const computedStyle = getComputedStyle(inputEl);\n\n let text = inputEl.innerText;\n if (!text || text === '\\n') {\n text = '\\u00A0';\n }\n\n mirrorEl.style.width = computedStyle.width;\n mirrorEl.textContent = text;\n\n const lineHeight = this.cssNum(computedStyle.lineHeight, 24);\n const paddingTop = this.cssNum(computedStyle.paddingTop, 0);\n const paddingBottom = this.cssNum(computedStyle.paddingBottom, 0);\n const paddingY = paddingTop + paddingBottom;\n\n const maxRowsCss = computedStyle.getPropertyValue('--max-rows').trim();\n const maxRows = maxRowsCss ? this.cssNum(maxRowsCss, 8) : 8;\n\n const contentH = mirrorEl.offsetHeight;\n const rawRows = Math.max(1, Math.ceil(contentH / lineHeight));\n const rows = Math.min(rawRows, maxRows);\n\n const nextHeightPx = Math.round(rows * lineHeight + paddingY);\n\n return {rows, nextHeightPx};\n }\n\n private initMirror() {\n const mirror = this.mirrorElement.nativeElement;\n const input = this.inputTextElement.nativeElement;\n const computedStyle = getComputedStyle(input);\n\n mirror.style.position = 'absolute';\n mirror.style.visibility = 'hidden';\n mirror.style.pointerEvents = 'none';\n mirror.style.zIndex = '-1';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.overflowWrap = 'break-word';\n mirror.style.wordBreak = 'normal';\n\n const properties = [\n 'font', 'font-size', 'font-family', 'font-weight', 'font-style',\n 'line-height', 'letter-spacing', 'word-spacing',\n 'padding-top', 'padding-bottom', 'padding-left', 'padding-right',\n 'border-top-width', 'border-bottom-width', 'border-left-width', 'border-right-width',\n 'white-space', 'text-transform', 'box-sizing'\n ];\n\n properties.forEach(property => (mirror.style as any)[property] = computedStyle.getPropertyValue(property));\n mirror.style.paddingTop = '0px';\n mirror.style.paddingBottom = '0px';\n }\n\n private updateOverflow(rows: number) {\n const element = this.inputTextElement.nativeElement;\n const computedStyle = getComputedStyle(element);\n const maxRowsCss = computedStyle.getPropertyValue('--max-rows').trim();\n const maxRows = maxRowsCss ? this.cssNum(maxRowsCss, 8) : 8;\n element.style.overflowY = rows >= maxRows ? 'auto' : 'hidden';\n\n return this;\n }\n\n private readFileAsDataURL(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = e => resolve((e.target?.result as string) || '');\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n }\n\n private cssNum(v: string, fb = 0): number {\n const n = parseFloat(v);\n return Number.isFinite(n) ? n : fb;\n }\n\n protected readonly FileType = FileType;\n}\n","<section class=\"message\"\n [class.message--focus]=\"focused()\"\n [class.message--filled]=\"hasText()\"\n [class.message--sending]=\"sending()\">\n\n @if (isEditMode()) {\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button class=\"message__button message__button--attach\">\n <mat-icon svgIcon=\"icon-edit\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--edit\">\n </mat-icon>\n </button>\n\n <div class=\"message__edit-hint\">\n <p>{{ editMessage()?.content }}</p>\n </div>\n </div>\n\n <button class=\"message__button message__button--close\"\n type=\"button\"\n (click)=\"cancelEditMessage()\">\n <mat-icon svgIcon=\"close\" aria-hidden=\"true\" class=\"message__icon message__icon--close\"></mat-icon>\n </button>\n </div>\n }\n\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button type=\"button\"\n class=\"message__button message__button--attach\"\n [attr.aria-label]=\"'chat.attach' | transloco\"\n (click)=\"fileDialog.click()\">\n <mat-icon svgIcon=\"attach-filled\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--attach\">\n </mat-icon>\n </button>\n\n <input #fileDialog\n type=\"file\"\n class=\"hidden\"\n accept=\"image/*\"\n multiple\n (change)=\"inputFileChange($event)\">\n\n <div #inputText\n role=\"textbox\"\n class=\"message__input\"\n spellcheck=\"true\"\n contenteditable=\"true\"\n aria-multiline=\"true\"\n [attr.data-placeholder]=\"isEditMode()\n ? ('chat.edit_placeholder' | transloco)\n : ('chat.placeholder' | transloco)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (paste)=\"onPaste()\"\n (keydown)=\"onKeyDown($event)\">\n </div>\n\n <div #mirror class=\"message__input-mirror\" aria-hidden=\"true\"></div>\n\n <ng-content></ng-content>\n </div>\n\n <button class=\"message__button message__button--send\"\n type=\"button\"\n (click)=\"enterDown()\"\n [attr.aria-label]=\"'chat.send' | transloco\"\n [disabled]=\"!canSend()\">\n <mat-icon svgIcon=\"send\" aria-hidden=\"true\" class=\"message__icon message__icon--send\"></mat-icon>\n </button>\n </div>\n\n @if (previews().length) {\n <div class=\"message__files\">\n @for (item of previews(); track $index) {\n <div class=\"message__file\" [attr.data-kind]=\"item.originalKind\">\n <button type=\"button\"\n class=\"message__file-remove\"\n [attr.aria-label]=\"'chat.delete_file' | transloco\"\n (click)=\"removeFile($index, $event)\">\n <mat-icon svgIcon=\"remove\"\n aria-hidden=\"true\"\n class=\"message__icon message__icon--file\">\n </mat-icon>\n </button>\n\n <div class=\"message__file-media\" (click)=\"openPreview(item, $index)\">\n <img [src]=\"item.src\" [alt]=\"item.name\" class=\"message__file-img\"/>\n\n @if (item.originalKind === FileType.GIF) {\n <span class=\"message__file-badge message__file-badge--gif\">\n {{ 'chat.gif' | transloco }}\n </span>\n }\n </div>\n </div>\n }\n </div>\n }\n</section>\n\n\n","export enum FlowTheme {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n}\n","import {Component, computed, effect, input, model} from '@angular/core';\nimport {NgClass, NgOptimizedImage} from '@angular/common';\nimport {ChatFlowComponent} from '../chat-flow/chat-flow';\nimport {MatDialogContent, MatDialogTitle} from '@angular/material/dialog';\nimport {ChatMessage, ChatMessageDTO, ChatMessageType, MessageType} from '../core/entity/chat';\nimport {MatProgressSpinner} from '@angular/material/progress-spinner';\nimport {InputMessageComponent} from '../input-message/input-message';\nimport {\n TranslocoModule,\n TranslocoPipe,\n TranslocoService,\n} from '@ngneat/transloco';\nimport {UtilsService} from '../core/service/utils/utils';\nimport {FlowTheme} from '../core/entity/theme';\n\n@Component({\n selector: 'ngx-parl',\n standalone: true,\n imports: [\n NgOptimizedImage, NgClass, MatDialogContent, MatDialogTitle, MatProgressSpinner, ChatFlowComponent, InputMessageComponent,\n TranslocoModule,\n TranslocoPipe\n ],\n templateUrl: './ngx-parl.html',\n styleUrl: './ngx-parl.scss',\n providers: [],\n})\n\nexport class NgxParlComponent {\n public ai_run_in_progress = false;\n private lastUpdateKey: string | null = null;\n\n public theme = input<FlowTheme>(FlowTheme.PRIMARY);\n public header = input<boolean>(true);\n public language = input<'en' | 'uk'>('en');\n\n public messageList = model<ChatMessage[]>([]);\n public messageUpdate = model<ChatMessage>();\n public selectedForEdit = model<ChatMessage | null>(null);\n\n public incomingUser = computed(() => {\n return (\n this.messageList().find((message) => message.type === MessageType.Incoming)?.user ?? ''\n );\n });\n\n public hideHandler = input<(() => unknown) | null>(null);\n public closeHandler = input<(() => unknown) | null>(null);\n\n constructor(private utils: UtilsService,\n private transloco: TranslocoService) {\n effect(() => {\n const lang = this.language();\n this.transloco.setActiveLang(lang);\n });\n\n effect(() => {\n const updatedMessage = this.messageUpdate();\n\n if (!updatedMessage) {\n return;\n }\n\n const key = `${updatedMessage.id}-${updatedMessage.cr_time}-${updatedMessage.type}`;\n if (this.lastUpdateKey === key) {\n return;\n }\n\n this.lastUpdateKey = key;\n\n if (updatedMessage.type !== MessageType.Incoming) {\n return;\n }\n\n this.messageList.update((currentList) => {\n const list = [...currentList];\n\n const incomingIndex = list.findIndex(\n (message) =>\n message.id === updatedMessage.id &&\n message.type === MessageType.Incoming,\n );\n\n if (incomingIndex > -1) {\n list[incomingIndex] = updatedMessage;\n return list;\n }\n\n list.push(updatedMessage);\n\n return list;\n });\n });\n }\n\n onCancelEdit(messageId: number | null) {\n if (messageId != null) {\n this.messageList.update((currentList) => {\n const updatedList = [...currentList];\n const index = updatedList.findIndex(\n (message) => message.id === messageId,\n );\n\n if (index > -1) {\n updatedList[index].edit = false;\n }\n\n return updatedList;\n });\n }\n\n this.selectedForEdit.set(null);\n\n return this;\n }\n\n sendMessage(\n event:\n | string\n | { id: number; content: string; files?: string[]; }\n | { content: string; files?: string[]; }\n | undefined\n ) {\n if (!event) {\n return this;\n }\n\n // edit message\n if (typeof event !== 'string' && 'id' in event) {\n const {id, content, files} = event;\n\n this.messageList.update((currentList) => {\n const updatedList = [...currentList];\n const index = updatedList.findIndex(\n (message) => message.id === id,\n );\n\n if (index > -1) {\n updatedList[index].content = (content ?? '').trim();\n\n if (Array.isArray(files)) {\n updatedList[index].file_path = files.length ? files : null;\n }\n\n updatedList[index].edit = false;\n }\n\n return updatedList;\n });\n\n this.selectedForEdit.set(null);\n\n return this;\n }\n\n // new message\n if (typeof event === 'string') {\n const text = event.trim();\n\n if (!text) {\n return this;\n }\n\n const messages = this.messageList();\n const lastId = messages.at(-1)?.id ?? 0;\n\n const lastOutgoing = [...messages]\n .reverse()\n .find((message) => message.type === MessageType.Outgoing,);\n\n const dto: ChatMessageDTO = {\n id: lastId + 1,\n chat_id: lastOutgoing?.chat_id ?? 1,\n cr_time: this.utils.getLocalISODate(),\n type: MessageType.Outgoing as ChatMessageType,\n user: lastOutgoing?.user ?? '',\n content: text,\n avatar: lastOutgoing?.avatar ?? null,\n file_path: null,\n checked: false,\n };\n\n this.messageList.update((list) => [...list, new ChatMessage(dto)]);\n\n return this;\n }\n\n // new message + files\n const {content, files} = event;\n const text = (content ?? '').trim();\n const hasFiles = Array.isArray(files) && files.length > 0;\n\n if (!text && !hasFiles) {\n return this;\n }\n\n const messages = this.messageList();\n const lastId = messages.at(-1)?.id ?? 0;\n\n const lastOutgoing = [...messages]\n .reverse()\n .find((message) => message.type === MessageType.Outgoing,);\n\n const dto: ChatMessageDTO = {\n id: lastId + 1,\n chat_id: lastOutgoing?.chat_id ?? 1,\n cr_time: this.utils.getLocalISODate(),\n type: MessageType.Outgoing as ChatMessageType,\n user: lastOutgoing?.user ?? '',\n content: text,\n avatar: lastOutgoing?.avatar ?? null,\n file_path: hasFiles ? files : null,\n checked: false,\n };\n\n this.messageList.update((list) => [...list, new ChatMessage(dto)]);\n\n return this;\n }\n\n onHideClick() {\n const handler = this.hideHandler();\n\n if (handler) {\n handler();\n }\n\n return this;\n }\n\n onCloseClick() {\n const handler = this.closeHandler();\n\n if (handler) {\n handler();\n }\n\n return this;\n }\n\n protected readonly FlowTheme = FlowTheme;\n}\n","<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\">{{ 'chat.title' | transloco }} {{ incomingUser() }}</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\" priority\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\" priority\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\">\n <app-chat-flow [messageListInput]=\"messageList()\" [(selectedForEdit)]=\"selectedForEdit\"></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","import { Injectable } from '@angular/core';\nimport { TranslocoLoader, Translation } from '@ngneat/transloco';\nimport { Observable, of } from 'rxjs';\n\nimport en from '../../assets/i18n/en.json';\nimport uk from '../../assets/i18n/uk.json';\n\n@Injectable()\nexport class ParlTranslocoLoader implements TranslocoLoader {\n getTranslation(lang: string): Observable<Translation> {\n switch (lang) {\n case 'uk':\n return of(uk as Translation);\n case 'en':\n default:\n return of(en as Translation);\n }\n }\n}\n","import { isDevMode } from '@angular/core';\nimport { provideTransloco } from '@ngneat/transloco';\nimport { ParlTranslocoLoader } from '../assets/i18n/parl-transloco.loader';\n\nexport function provideNgxParl() {\n return provideTransloco({\n config: {\n availableLangs: ['en', 'uk'],\n defaultLang: 'en',\n reRenderOnLangChange: true,\n prodMode: !isDevMode(),\n },\n loader: ParlTranslocoLoader,\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1","i1.UtilsService","i2"],"mappings":"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"}
1
+ {"version":3,"file":"trixwell-ngx-parl.mjs","sources":["../../../projects/ngx-parl/src/lib/core/entity/chat.ts","../../../projects/ngx-parl/src/lib/core/components/chat-message/chat-message.ts","../../../projects/ngx-parl/src/lib/core/components/chat-message/chat-message.html","../../../projects/ngx-parl/src/lib/core/service/utils/utils.ts","../../../projects/ngx-parl/src/lib/core/pipes/chat-start-day-pipe.ts","../../../projects/ngx-parl/src/lib/core/pipes/toggle-display-chat-start-day-pipe.ts","../../../projects/ngx-parl/src/lib/chat-flow/chat-flow.ts","../../../projects/ngx-parl/src/lib/chat-flow/chat-flow.html","../../../projects/ngx-parl/src/lib/core/entity/file.ts","../../../projects/ngx-parl/src/lib/input-message/input-message.ts","../../../projects/ngx-parl/src/lib/input-message/input-message.html","../../../projects/ngx-parl/src/lib/core/entity/theme.ts","../../../projects/ngx-parl/src/lib/ngx-parl/ngx-parl.ts","../../../projects/ngx-parl/src/lib/ngx-parl/ngx-parl.html","../../../projects/ngx-parl/src/assets/i18n/parl-transloco.loader.ts","../../../projects/ngx-parl/src/lib/ngx-parl.providers.ts","../../../projects/ngx-parl/src/trixwell-ngx-parl.ts"],"sourcesContent":["export class ChatMessage {\n public id: number;\n public chat_id: number;\n public cr_time: string;\n public type: ChatMessageType;\n public user: string;\n public content: string;\n public avatar: string | null;\n public file_path: string[] | null;\n public checked: boolean | null;\n\n public edit = false;\n\n constructor(data: ChatMessageDTO) {\n this.id = data.id;\n this.chat_id = data.chat_id;\n this.cr_time = data.cr_time;\n this.type = data.type;\n this.user = data.user;\n this.content = data.content;\n this.avatar = data.avatar ?? null;\n this.file_path = data.file_path ?? null;\n this.checked = data.checked ?? null;\n }\n\n get dateSimple(): string {\n const d = new Date(this.cr_time.replace(' ', 'T'));\n const dd = String(d.getDate()).padStart(2, '0');\n const mm = String(d.getMonth() + 1).padStart(2, '0');\n const yyyy = d.getFullYear();\n return `${dd}.${mm}.${yyyy}`;\n }\n\n get timeHHmm(): string {\n const d = new Date(this.cr_time.replace(' ', 'T'));\n const hh = String(d.getHours()).padStart(2, '0');\n const mm = String(d.getMinutes()).padStart(2, '0');\n return `${hh}:${mm}`;\n }\n}\n\nexport interface ChatMessageDTO {\n id: number;\n chat_id: number;\n cr_time: string; // ISO or 'YYYY-MM-DD HH:mm:ss'\n type: ChatMessageType;\n user: string;\n content: string;\n avatar?: string | null;\n file_path?: string[] | null;\n checked?: boolean | null;\n}\n\nexport type ChatMessageType = 'incoming' | 'outgoing';\n\nexport enum MessageType {\n Incoming = 'incoming',\n Outgoing = 'outgoing'\n}\n\nexport interface CurrMessage {\n id?: number;\n content: string;\n files?: string[];\n}\n","import {Component, computed, input, model} from '@angular/core';\nimport {DatePipe, NgClass, NgOptimizedImage} from '@angular/common';\nimport {ChatMessage, MessageType} from '../../entity/chat';\nimport {MatMenu, MatMenuItem, MatMenuTrigger} from '@angular/material/menu';\nimport {TranslocoPipe} from '@ngneat/transloco';\n\n@Component({\n selector: 'lib-chat-message',\n imports: [\n NgClass,\n NgOptimizedImage,\n DatePipe,\n MatMenu,\n MatMenuItem,\n MatMenuTrigger,\n TranslocoPipe,\n ],\n templateUrl: './chat-message.html',\n styleUrl: './chat-message.scss',\n standalone: true,\n})\n\nexport class ChatMessageComponent {\n public currentMessage = input.required<ChatMessage>();\n public edit = model<boolean>(false);\n\n public requestEdit = model<ChatMessage | null>(null);\n public requestDelete = model<number | null>(null);\n\n constructor() {}\n\n private normalizeSourcePath(sourcePath: string): string {\n const cleanedPath = (sourcePath ?? '').trim();\n if (!cleanedPath) {\n return '';\n }\n\n if (cleanedPath.startsWith('data:') || cleanedPath.startsWith('blob:') || /^https?:\\/\\//i.test(cleanedPath)) {\n return cleanedPath;\n }\n\n const assetsIndex = cleanedPath.indexOf('assets/');\n if (assetsIndex >= 0) {\n return '/' + cleanedPath.slice(assetsIndex);\n }\n\n return cleanedPath.replace(/^\\.{1,2}\\//, '/');\n }\n\n attachments = computed(() => {\n const message = this.currentMessage();\n const filePath = message.file_path;\n\n if (Array.isArray(filePath)) {\n return filePath.map(p => this.normalizeSourcePath(p)).filter(Boolean);\n }\n\n const rawFilePath = (filePath as unknown as string) ?? '';\n if (typeof rawFilePath !== 'string' || !rawFilePath.trim) {\n return [];\n }\n\n if (rawFilePath.trim().startsWith('[')) {\n try {\n const parsed = JSON.parse(rawFilePath);\n if (Array.isArray(parsed)) {\n return parsed\n .map(item => (typeof item === 'string' ? this.normalizeSourcePath(item) : ''))\n .filter(Boolean);\n }\n } catch {}\n }\n\n if (rawFilePath.startsWith('data:')) {\n return [rawFilePath];\n }\n\n if (rawFilePath.includes('|')) {\n return rawFilePath.split('|').map(p => this.normalizeSourcePath(p)).filter(Boolean);\n }\n if (rawFilePath.includes(',')) {\n return rawFilePath.split(',').map(p => this.normalizeSourcePath(p)).filter(Boolean);\n }\n\n return [];\n });\n\n avatarSrc = computed(() => {\n const message = this.currentMessage();\n const fallback = message.type === 'incoming'\n ? 'assets/ngx-parl/icons/avatar_anonym.svg'\n : 'assets/ngx-parl/icons/avatar_manager.svg';\n\n return message.avatar || fallback;\n });\n\n openContextMenu(event: Event, trigger: any) {\n event.preventDefault();\n event.stopPropagation();\n trigger.openMenu();\n\n return this;\n }\n\n editMessage(message: ChatMessage) {\n this.edit.set(true);\n this.requestEdit.set(message);\n\n return this;\n }\n\n deleteMessage(message: ChatMessage) {\n this.requestDelete.set(message.id);\n queueMicrotask(() => this.requestDelete.set(null));\n\n return this;\n }\n\n canDelete(message: ChatMessage): boolean {\n return message.type === this.messageType.Outgoing;\n }\n\n public readonly messageType = MessageType;\n}\n","<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 #menuTrigger=\"matMenuTrigger\"\n [matMenuTriggerFor]=\"messageMenu\"\n (contextmenu)=\"openContextMenu($event, menuTrigger)\"\n (keydown.shift.F10)=\"openContextMenu($event, menuTrigger)\">\n\n @if (attachments().length) {\n <div class=\"message__attachments\">\n @for (file of attachments(); track file) {\n <img [src]=\"file\"\n alt=\"attachment\"\n class=\"message__image\"\n loading=\"lazy\"/>\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\">{{ currentMessage().cr_time | date:'HH:mm' }}</time>\n @if (currentMessage().type === messageType.Outgoing) {\n @if (currentMessage().checked) {\n <img ngSrc=\"assets/ngx-parl/icons/checked-message.svg\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n } @else {\n <img ngSrc=\"assets/ngx-parl/icons/no-check\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n }\n }\n </div>\n </div>\n </div>\n</div>\n\n<mat-menu #messageMenu=\"matMenu\" xPosition=\"before\" yPosition=\"below\" 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\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\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\"\n class=\"message__icon\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n <span>{{ 'chat.remove' | transloco }}</span>\n </button>\n }\n</mat-menu>\n","import {Injectable} from '@angular/core';\nimport {HttpClient} from '@angular/common/http';\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class UtilsService {\n\n constructor(protected http: HttpClient) {\n }\n\n langToLocale(lang: string): string {\n switch (lang) {\n case 'uk':\n return 'uk-UA';\n case 'en':\n default:\n return 'en-US';\n }\n }\n\n getLocalISODate(): string {\n const d = new Date();\n\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n\n const hours = String(d.getHours()).padStart(2, '0');\n const minutes = String(d.getMinutes()).padStart(2, '0');\n const seconds = String(d.getSeconds()).padStart(2, '0');\n\n return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport {DatePipe} from '@angular/common';\nimport {UtilsService} from '../service/utils/utils';\nimport {TranslocoService} from '@ngneat/transloco';\n\n@Pipe({\n name: 'chatStartDay'\n})\nexport class ChatStartDayPipe implements PipeTransform {\n constructor(protected utils: UtilsService, private transloco: TranslocoService) {}\n\n transform(value: string, format: string = 'd MMMM'): string {\n if (!value) {\n return '';\n }\n\n const locale = this.utils.langToLocale(this.transloco.getActiveLang());\n const datePipe = new DatePipe(locale);\n\n const valueDate = new Date(value);\n const today = new Date();\n\n const isToday = datePipe.transform(valueDate, 'shortDate') === datePipe.transform(today, 'shortDate');\n\n return isToday\n ? (locale.startsWith('uk') ? 'Сьогодні' : 'Today')\n : (datePipe.transform(valueDate, format) ?? '');\n }\n\n}\n","import {Pipe, PipeTransform} from '@angular/core';\nimport {DatePipe} from '@angular/common';\nimport {ChatMessage} from '../entity/chat';\nimport {UtilsService} from '../service/utils/utils';\nimport {TranslocoService} from '@ngneat/transloco';\n\n@Pipe({\n name: 'toggleDisplayChatStartDay'\n})\nexport class ToggleDisplayChatStartDayPipe implements PipeTransform {\n\n constructor(protected utils: UtilsService, private transloco: TranslocoService) {}\n\n transform(message: ChatMessage, messages: ChatMessage[], i: number): boolean {\n const locale = this.utils.langToLocale(this.transloco.getActiveLang());\n const datePipe = new DatePipe(locale);\n\n const prev = i > 0 ? messages[i - 1] : undefined;\n\n const currDay = datePipe.transform(new Date(message.cr_time), 'shortDate');\n const prevDay = prev ? datePipe.transform(new Date(prev.cr_time), 'shortDate') : undefined;\n\n return prev ? currDay !== prevDay : true;\n }\n}\n","import {Component, computed, effect, ElementRef, model, ViewChild,} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {ChatMessage} from '../core/entity/chat';\nimport {ChatMessageComponent} from '../core/components/chat-message/chat-message';\nimport {ChatStartDayPipe} from '../core/pipes/chat-start-day-pipe';\nimport {ToggleDisplayChatStartDayPipe} from '../core/pipes/toggle-display-chat-start-day-pipe';\nimport {TranslocoPipe} from '@ngneat/transloco';\nimport {NgOptimizedImage} from '@angular/common';\n\n@Component({\n selector: 'app-chat-flow',\n imports: [\n FormsModule,\n ChatMessageComponent,\n ChatStartDayPipe,\n ToggleDisplayChatStartDayPipe,\n ChatMessageComponent,\n TranslocoPipe,\n NgOptimizedImage\n ],\n templateUrl: './chat-flow.html',\n styleUrl: './chat-flow.scss',\n standalone: true,\n})\n\nexport class ChatFlowComponent {\n @ViewChild('chatFlowRef', {static: true}) private flowRef!: ElementRef<HTMLElement>;\n\n public messageListInput = model.required<ChatMessage[]>();\n public messageList = computed(() => this.messageListInput());\n\n public selectedForEdit = model.required<ChatMessage | null>();\n\n constructor() {\n effect(() => {\n const length = this.messageList().length;\n if (length > 0) {\n queueMicrotask(() => this.scrollToBottomSmooth());\n }\n });\n }\n\n private scrollToBottomSmooth() {\n const element = this.flowRef?.nativeElement;\n if (!element) {\n return this;\n }\n element.scrollTo({top: element.scrollHeight, behavior: 'smooth'});\n\n return this;\n }\n\n startEdit(message: ChatMessage) {\n this.messageList().forEach(currMessage => {\n if (currMessage.id !== message.id && currMessage.edit) {\n currMessage.edit = false;\n }\n });\n\n message.edit = true;\n\n if (this.selectedForEdit()?.id === message.id) {\n this.selectedForEdit.set(null);\n queueMicrotask(() => this.selectedForEdit.set(message));\n } else {\n this.selectedForEdit.set(message);\n }\n\n return this;\n }\n\n onEditChange(id: number, isEdit: boolean) {\n const messageList = this.messageList().find(message => message.id === id);\n if (!messageList) {\n return this;\n }\n\n if (isEdit) {\n return this.startEdit(messageList);\n } else {\n messageList.edit = false;\n\n if (this.selectedForEdit()?.id === id) {\n this.selectedForEdit.set(null);\n }\n }\n\n return this;\n }\n\n onRequestEdit(message: ChatMessage | null) {\n if (message) {\n return this.startEdit(message);\n }\n this.selectedForEdit.set(null);\n\n return this;\n }\n\n onRequestDelete(messageId: number | null) {\n if (!messageId) {\n return this;\n }\n\n const updatedList = this.messageList().filter(m => m.id !== messageId);\n this.selectedForEdit.set(null);\n\n queueMicrotask(() => this.messageListInput.set(updatedList));\n\n return this;\n }\n\n trackByMessageId(_index: number, message: ChatMessage): string {\n // return message.id;\n return `${message.chat_id}-${message.type}-${message.id}`;\n }\n}\n","<div class=\"chat\">\n @if (messageList()) {\n <div class=\"chat__flow\" #chatFlowRef>\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 <lib-chat-message [currentMessage]=\"message\"\n [edit]=\"message.edit ?? false\"\n (editChange)=\"onEditChange(message.id, $event)\"\n (requestEditChange)=\"onRequestEdit($event)\"\n (requestDeleteChange)=\"onRequestDelete($event)\">\n </lib-chat-message>\n }\n </div>\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\" priority/>\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","export class ImageFile {\n constructor(\n public id: string,\n public url: string,\n public cr_time: string,\n ) {}\n}\n\nexport type OriginalKind = 'image' | 'gif';\n\nexport interface PreviewItem {\n originalKind: OriginalKind;\n duration?: number;\n src: string;\n name: string;\n type: string;\n size: number;\n}\n\nexport enum FileType {\n IMAGE = 'image',\n GIF = 'gif'\n}\n","import {\n AfterViewInit,\n Component,\n computed,\n effect,\n ElementRef,\n input,\n model,\n OnDestroy,\n signal,\n ViewChild\n} from '@angular/core';\nimport {FileType, OriginalKind, PreviewItem} from '../core/entity/file';\nimport {TranslocoPipe} from '@ngneat/transloco';\nimport {ChatMessage, CurrMessage} from '../core/entity/chat';\nimport {NgOptimizedImage} from '@angular/common';\n\n@Component({\n selector: 'app-input-message',\n imports: [TranslocoPipe, NgOptimizedImage],\n templateUrl: './input-message.html',\n styleUrl: './input-message.scss',\n standalone: true,\n})\n\nexport class InputMessageComponent implements AfterViewInit, OnDestroy {\n @ViewChild('inputText', {static: false}) inputTextElement!: ElementRef<HTMLDivElement>;\n @ViewChild('mirror', {static: false}) mirrorElement!: ElementRef<HTMLDivElement>;\n\n public editMessage = input<ChatMessage | { id: number; content: string; file_path?: string[] | null } | null>(null);\n\n public hasOriginalAttachments = computed(() => {\n const filePaths = this.editFilePaths();\n return filePaths.length > 0;\n });\n\n public hasNewAttachments = computed(() => (this.previews()?.length ?? 0) > 0);\n\n public cancelEdit = model<number | null>(null);\n public input_text = model<string | CurrMessage>('');\n\n public draft = signal<string>('');\n public focused = signal<boolean>(false);\n public sending = signal<boolean>(false);\n public hasText = computed(() => this.draft().trim().length > 0);\n\n public isEditMode = computed(() => !!this.editMessage());\n public canSend = computed(() =>\n this.hasText() ||\n this.hasNewAttachments() ||\n (this.isEditMode() && this.hasOriginalAttachments())\n );\n\n public files = model<File[]>([]);\n public previews = model<PreviewItem[]>([]);\n\n private lastHeightPx = 0;\n private lastRows = 1;\n private resizeRaf: number | null = null;\n\n constructor() {\n effect(() => {\n const message = this.editMessage();\n const element = this.inputTextElement?.nativeElement;\n\n if (!element) {\n return;\n }\n\n if (message) {\n const content = (message as any).content ?? '';\n this.draft.set(content);\n element.innerText = content;\n\n queueMicrotask(() => {\n this.autoResizeByRows();\n element.focus();\n this.focused.set(true);\n });\n }\n });\n }\n\n ngAfterViewInit() {\n const element = this.inputTextElement.nativeElement;\n element.style.transition = 'height 160ms ease';\n this.initMirror();\n\n const computedStyle = getComputedStyle(element);\n const lineHeight = this.cssNum(computedStyle.lineHeight, 24);\n\n element.style.height = `${lineHeight}px`;\n this.lastHeightPx = lineHeight;\n this.lastRows = 1;\n this.updateOverflow(1);\n\n requestAnimationFrame(() => {\n const {rows, nextHeightPx} = this.measureByMirror();\n element.style.height = `${nextHeightPx}px`;\n\n this.lastRows = rows;\n this.lastHeightPx = nextHeightPx;\n this.updateOverflow(rows);\n });\n }\n\n ngOnDestroy() {\n if (this.resizeRaf) {\n cancelAnimationFrame(this.resizeRaf);\n this.resizeRaf = null;\n }\n }\n\n private editFilePaths(): string[] {\n const message = this.editMessage();\n if (!message) {\n return [];\n }\n\n const file_path = (message as any).file_path;\n\n return Array.isArray(file_path) ? file_path : [];\n }\n\n private collectAttachmentSources(): string[] {\n return (this.previews() ?? []).map(p => p.src).filter(Boolean);\n }\n\n cancelEditMessage() {\n const message = this.editMessage();\n this.cancelEdit.set((message as any)?.id ?? null);\n queueMicrotask(() => this.cancelEdit.set(null));\n\n this.draft.set('');\n const element = this.inputTextElement?.nativeElement;\n\n if (element) {\n element.innerHTML = '';\n this.autoResizeByRows();\n element.focus();\n }\n\n return this;\n }\n\n enterDown() {\n const element = this.inputTextElement.nativeElement;\n const text = this.draft().trim();\n if (!this.canSend()) return this;\n\n this.sending.set(true);\n\n const files = this.collectAttachmentSources();\n const message = this.editMessage();\n\n if (message) {\n this.input_text.set({id: (message as any).id, content: text, files: files.length ? files : undefined});\n } else {\n this.input_text.set({content: text, files: files.length ? files : undefined});\n }\n\n this.draft.set('');\n element.innerHTML = '';\n this.files.set([]);\n this.previews.set([]);\n element.focus();\n this.autoResizeByRows();\n\n setTimeout(() => this.sending.set(false), 150);\n\n return this;\n }\n\n onFocus() {\n if (this.inputTextElement.nativeElement.innerHTML === '<br>') {\n this.inputTextElement.nativeElement.innerHTML = '';\n }\n this.focused.set(true);\n\n return this;\n }\n\n onBlur() {\n this.focused.set(false);\n\n return this;\n }\n\n onKeyDown(event: KeyboardEvent) {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n this.enterDown();\n\n return this;\n }\n queueMicrotask(() => this.autoResizeByRows());\n\n return this;\n }\n\n onInput() {\n this.draft.set(this.inputTextElement.nativeElement.innerText ?? '');\n this.autoResizeByRows();\n\n return this;\n }\n\n onPaste() {\n queueMicrotask(() => {\n this.draft.set(this.inputTextElement.nativeElement.innerText ?? '');\n this.autoResizeByRows();\n });\n\n return this;\n }\n\n inputFileChange(event: Event) {\n const inputEl = event.target as HTMLInputElement;\n const selected = inputEl.files;\n\n if (!selected?.length) {\n inputEl.value = '';\n\n return this;\n }\n\n const list = Array.from(selected).filter(f => (f.type || '').startsWith('image/'));\n if (!list.length) {\n inputEl.value = '';\n\n return this;\n }\n\n this.files.set([...(this.files() ?? []), ...list]);\n\n Promise.all(\n list.map(async f => {\n const src = await this.readFileAsDataURL(f);\n const originalKind: OriginalKind = (f.type || '') === 'image/gif' ? FileType.GIF : FileType.IMAGE;\n return <PreviewItem>{src, originalKind, name: f.name, type: f.type || '', size: f.size};\n })\n )\n .then(items => this.previews.set([...(this.previews() ?? []), ...items]))\n .finally(() => (inputEl.value = ''));\n\n return this;\n }\n\n removeFile(index: number, event?: MouseEvent) {\n event?.stopPropagation();\n event?.preventDefault();\n\n const previews = [...(this.previews() ?? [])];\n previews.splice(index, 1);\n this.previews.set(previews);\n\n const filesArr = [...(this.files() ?? [])];\n if (index >= 0 && index < filesArr.length) {\n filesArr.splice(index, 1);\n this.files.set(filesArr);\n }\n return this;\n }\n\n openPreview(_item: PreviewItem, _index: number) {\n return this;\n }\n\n private autoResizeByRows() {\n const element = this.inputTextElement.nativeElement;\n const {rows, nextHeightPx} = this.measureByMirror();\n\n if (rows === this.lastRows) {\n this.updateOverflow(rows);\n\n return this;\n }\n\n if (this.resizeRaf) {\n cancelAnimationFrame(this.resizeRaf);\n }\n\n element.style.height = `${this.lastHeightPx}px`;\n\n this.resizeRaf = requestAnimationFrame(() => {\n element.style.height = `${nextHeightPx}px`;\n this.lastHeightPx = nextHeightPx;\n this.lastRows = rows;\n this.updateOverflow(rows);\n });\n\n return this;\n }\n\n private measureByMirror(): { rows: number; nextHeightPx: number } {\n const inputEl = this.inputTextElement.nativeElement;\n const mirrorEl = this.mirrorElement.nativeElement;\n const computedStyle = getComputedStyle(inputEl);\n\n let text = inputEl.innerText;\n if (!text || text === '\\n') {\n text = '\\u00A0';\n }\n\n mirrorEl.style.width = computedStyle.width;\n mirrorEl.textContent = text;\n\n const lineHeight = this.cssNum(computedStyle.lineHeight, 24);\n const paddingTop = this.cssNum(computedStyle.paddingTop, 0);\n const paddingBottom = this.cssNum(computedStyle.paddingBottom, 0);\n const paddingY = paddingTop + paddingBottom;\n\n const maxRowsCss = computedStyle.getPropertyValue('--max-rows').trim();\n const maxRows = maxRowsCss ? this.cssNum(maxRowsCss, 8) : 8;\n\n const contentH = mirrorEl.offsetHeight;\n const rawRows = Math.max(1, Math.ceil(contentH / lineHeight));\n const rows = Math.min(rawRows, maxRows);\n\n const nextHeightPx = Math.round(rows * lineHeight + paddingY);\n\n return {rows, nextHeightPx};\n }\n\n private initMirror() {\n const mirror = this.mirrorElement.nativeElement;\n const input = this.inputTextElement.nativeElement;\n const computedStyle = getComputedStyle(input);\n\n mirror.style.position = 'absolute';\n mirror.style.visibility = 'hidden';\n mirror.style.pointerEvents = 'none';\n mirror.style.zIndex = '-1';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.overflowWrap = 'break-word';\n mirror.style.wordBreak = 'normal';\n\n const properties = [\n 'font', 'font-size', 'font-family', 'font-weight', 'font-style',\n 'line-height', 'letter-spacing', 'word-spacing',\n 'padding-top', 'padding-bottom', 'padding-left', 'padding-right',\n 'border-top-width', 'border-bottom-width', 'border-left-width', 'border-right-width',\n 'white-space', 'text-transform', 'box-sizing'\n ];\n\n properties.forEach(property => (mirror.style as any)[property] = computedStyle.getPropertyValue(property));\n mirror.style.paddingTop = '0px';\n mirror.style.paddingBottom = '0px';\n }\n\n private updateOverflow(rows: number) {\n const element = this.inputTextElement.nativeElement;\n const computedStyle = getComputedStyle(element);\n const maxRowsCss = computedStyle.getPropertyValue('--max-rows').trim();\n const maxRows = maxRowsCss ? this.cssNum(maxRowsCss, 8) : 8;\n element.style.overflowY = rows >= maxRows ? 'auto' : 'hidden';\n\n return this;\n }\n\n private readFileAsDataURL(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = e => resolve((e.target?.result as string) || '');\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n }\n\n private cssNum(v: string, fb = 0): number {\n const n = parseFloat(v);\n return Number.isFinite(n) ? n : fb;\n }\n\n protected readonly FileType = FileType;\n}\n","<section class=\"message\"\n [class.message--focus]=\"focused()\"\n [class.message--filled]=\"hasText()\"\n [class.message--sending]=\"sending()\">\n\n @if (isEditMode()) {\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button class=\"message__button message__button--attach\">\n <img ngSrc=\"assets/ngx-parl/icons/icon-edit.svg\"\n class=\"message__icon message__icon--edit\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <div class=\"message__edit-hint\">\n <p>{{ editMessage()?.content }}</p>\n </div>\n </div>\n\n <button class=\"message__button message__button--close\"\n type=\"button\"\n (click)=\"cancelEditMessage()\">\n <img ngSrc=\"assets/ngx-parl/icons/close.svg\"\n class=\"message__icon message__icon--close\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n </div>\n }\n\n <div class=\"message__wrap\">\n <div class=\"message__wrap--input\">\n <button type=\"button\"\n class=\"message__button message__button--attach\"\n [attr.aria-label]=\"'chat.attach' | transloco\"\n (click)=\"fileDialog.click()\">\n <img ngSrc=\"assets/ngx-parl/icons/attach-filled.svg\"\n class=\"message__icon message__icon--attach\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <input #fileDialog\n type=\"file\"\n class=\"hidden\"\n accept=\"image/*\"\n multiple\n (change)=\"inputFileChange($event)\">\n\n <div #inputText\n role=\"textbox\"\n class=\"message__input\"\n spellcheck=\"true\"\n contenteditable=\"true\"\n aria-multiline=\"true\"\n [attr.data-placeholder]=\"isEditMode()\n ? ('chat.edit_placeholder' | transloco)\n : ('chat.placeholder' | transloco)\"\n (blur)=\"onBlur()\"\n (focus)=\"onFocus()\"\n (input)=\"onInput()\"\n (paste)=\"onPaste()\"\n (keydown)=\"onKeyDown($event)\">\n </div>\n\n <div #mirror class=\"message__input-mirror\" aria-hidden=\"true\"></div>\n\n <ng-content></ng-content>\n </div>\n\n <button class=\"message__button message__button--send\"\n type=\"button\"\n (click)=\"enterDown()\"\n [attr.aria-label]=\"'chat.send' | transloco\"\n [disabled]=\"!canSend()\">\n <img ngSrc=\"assets/ngx-parl/icons/send.svg\"\n class=\"message__icon message__icon--send\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n\n </button>\n </div>\n\n @if (previews().length) {\n <div class=\"message__files\">\n @for (item of previews(); track $index) {\n <div class=\"message__file\" [attr.data-kind]=\"item.originalKind\">\n <button type=\"button\"\n class=\"message__file-remove\"\n [attr.aria-label]=\"'chat.delete_file' | transloco\"\n (click)=\"removeFile($index, $event)\">\n <img ngSrc=\"assets/ngx-parl/icons/remove.svg\"\n class=\"message__icon message__icon--file\"\n width=\"18\" height=\"18\" alt=\"hide\" priority/>\n </button>\n\n <div class=\"message__file-media\" (click)=\"openPreview(item, $index)\">\n <img [src]=\"item.src\" [alt]=\"item.name\" class=\"message__file-img\"/>\n\n @if (item.originalKind === FileType.GIF) {\n <span class=\"message__file-badge message__file-badge--gif\">\n {{ 'chat.gif' | transloco }}\n </span>\n }\n </div>\n </div>\n }\n </div>\n }\n</section>\n\n\n","export enum FlowTheme {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n}\n","import {Component, computed, effect, input, model} from '@angular/core';\nimport {NgClass, NgOptimizedImage} from '@angular/common';\nimport {ChatFlowComponent} from '../chat-flow/chat-flow';\nimport {MatDialogContent, MatDialogTitle} from '@angular/material/dialog';\nimport {ChatMessage, ChatMessageDTO, ChatMessageType, MessageType} from '../core/entity/chat';\nimport {MatProgressSpinner} from '@angular/material/progress-spinner';\nimport {InputMessageComponent} from '../input-message/input-message';\nimport {\n TranslocoModule,\n TranslocoPipe,\n TranslocoService,\n} from '@ngneat/transloco';\nimport {UtilsService} from '../core/service/utils/utils';\nimport {FlowTheme} from '../core/entity/theme';\n\n@Component({\n selector: 'ngx-parl',\n standalone: true,\n imports: [\n NgOptimizedImage, NgClass, MatDialogContent, MatDialogTitle, MatProgressSpinner, ChatFlowComponent, InputMessageComponent,\n TranslocoModule,\n TranslocoPipe\n ],\n templateUrl: './ngx-parl.html',\n styleUrl: './ngx-parl.scss',\n providers: [],\n})\n\nexport class NgxParlComponent {\n public ai_run_in_progress = false;\n private lastUpdateKey: string | null = null;\n\n public theme = input<FlowTheme>(FlowTheme.PRIMARY);\n public header = input<boolean>(true);\n public language = input<'en' | 'uk'>('en');\n\n public messageList = model<ChatMessage[]>([]);\n public messageUpdate = model<ChatMessage>();\n public selectedForEdit = model<ChatMessage | null>(null);\n\n public incomingUser = computed(() => {\n return (\n this.messageList().find((message) => message.type === MessageType.Incoming)?.user ?? ''\n );\n });\n\n public hideHandler = input<(() => unknown) | null>(null);\n public closeHandler = input<(() => unknown) | null>(null);\n\n constructor(private utils: UtilsService,\n private transloco: TranslocoService) {\n effect(() => {\n const lang = this.language();\n this.transloco.setActiveLang(lang);\n });\n\n effect(() => {\n const updatedMessage = this.messageUpdate();\n\n if (!updatedMessage) {\n return;\n }\n\n const key = `${updatedMessage.id}-${updatedMessage.cr_time}-${updatedMessage.type}`;\n if (this.lastUpdateKey === key) {\n return;\n }\n\n this.lastUpdateKey = key;\n\n if (updatedMessage.type !== MessageType.Incoming) {\n return;\n }\n\n this.messageList.update((currentList) => {\n const list = [...currentList];\n\n const incomingIndex = list.findIndex(\n (message) =>\n message.id === updatedMessage.id &&\n message.type === MessageType.Incoming,\n );\n\n if (incomingIndex > -1) {\n list[incomingIndex] = updatedMessage;\n return list;\n }\n\n list.push(updatedMessage);\n\n return list;\n });\n });\n }\n\n onCancelEdit(messageId: number | null) {\n if (messageId != null) {\n this.messageList.update((currentList) => {\n const updatedList = [...currentList];\n const index = updatedList.findIndex(\n (message) => message.id === messageId,\n );\n\n if (index > -1) {\n updatedList[index].edit = false;\n }\n\n return updatedList;\n });\n }\n\n this.selectedForEdit.set(null);\n\n return this;\n }\n\n sendMessage(\n event:\n | string\n | { id: number; content: string; files?: string[]; }\n | { content: string; files?: string[]; }\n | undefined\n ) {\n if (!event) {\n return this;\n }\n\n // edit message\n if (typeof event !== 'string' && 'id' in event) {\n const {id, content, files} = event;\n\n this.messageList.update((currentList) => {\n const updatedList = [...currentList];\n const index = updatedList.findIndex(\n (message) => message.id === id,\n );\n\n if (index > -1) {\n updatedList[index].content = (content ?? '').trim();\n\n if (Array.isArray(files)) {\n updatedList[index].file_path = files.length ? files : null;\n }\n\n updatedList[index].edit = false;\n }\n\n return updatedList;\n });\n\n this.selectedForEdit.set(null);\n\n return this;\n }\n\n // new message\n if (typeof event === 'string') {\n const text = event.trim();\n\n if (!text) {\n return this;\n }\n\n const messages = this.messageList();\n const lastId = messages.at(-1)?.id ?? 0;\n\n const lastOutgoing = [...messages]\n .reverse()\n .find((message) => message.type === MessageType.Outgoing,);\n\n const dto: ChatMessageDTO = {\n id: lastId + 1,\n chat_id: lastOutgoing?.chat_id ?? 1,\n cr_time: this.utils.getLocalISODate(),\n type: MessageType.Outgoing as ChatMessageType,\n user: lastOutgoing?.user ?? '',\n content: text,\n avatar: lastOutgoing?.avatar ?? null,\n file_path: null,\n checked: false,\n };\n\n this.messageList.update((list) => [...list, new ChatMessage(dto)]);\n\n return this;\n }\n\n // new message + files\n const {content, files} = event;\n const text = (content ?? '').trim();\n const hasFiles = Array.isArray(files) && files.length > 0;\n\n if (!text && !hasFiles) {\n return this;\n }\n\n const messages = this.messageList();\n const lastId = messages.at(-1)?.id ?? 0;\n\n const lastOutgoing = [...messages]\n .reverse()\n .find((message) => message.type === MessageType.Outgoing,);\n\n const dto: ChatMessageDTO = {\n id: lastId + 1,\n chat_id: lastOutgoing?.chat_id ?? 1,\n cr_time: this.utils.getLocalISODate(),\n type: MessageType.Outgoing as ChatMessageType,\n user: lastOutgoing?.user ?? '',\n content: text,\n avatar: lastOutgoing?.avatar ?? null,\n file_path: hasFiles ? files : null,\n checked: false,\n };\n\n this.messageList.update((list) => [...list, new ChatMessage(dto)]);\n\n return this;\n }\n\n onHideClick() {\n const handler = this.hideHandler();\n\n if (handler) {\n handler();\n }\n\n return this;\n }\n\n onCloseClick() {\n const handler = this.closeHandler();\n\n if (handler) {\n handler();\n }\n\n return this;\n }\n\n protected readonly FlowTheme = FlowTheme;\n}\n","<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\">{{ 'chat.title' | transloco }} {{ incomingUser() }}</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\" priority\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\" priority\n (click)=\"onCloseClick()\"/>\n </div>\n </header>\n }\n\n <mat-dialog-content class=\"modal-chat__content\">\n <app-chat-flow [messageListInput]=\"messageList()\" [(selectedForEdit)]=\"selectedForEdit\"></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","import { Injectable } from '@angular/core';\nimport { TranslocoLoader, Translation } from '@ngneat/transloco';\nimport { Observable, of } from 'rxjs';\n\nimport en from '../../assets/i18n/en.json';\nimport uk from '../../assets/i18n/uk.json';\n\n@Injectable()\nexport class ParlTranslocoLoader implements TranslocoLoader {\n getTranslation(lang: string): Observable<Translation> {\n switch (lang) {\n case 'uk':\n return of(uk as Translation);\n case 'en':\n default:\n return of(en as Translation);\n }\n }\n}\n","import { isDevMode } from '@angular/core';\nimport { provideTransloco } from '@ngneat/transloco';\nimport { ParlTranslocoLoader } from '../assets/i18n/parl-transloco.loader';\n\nexport function provideNgxParl() {\n return provideTransloco({\n config: {\n availableLangs: ['en', 'uk'],\n defaultLang: 'en',\n reRenderOnLangChange: true,\n prodMode: !isDevMode(),\n },\n loader: ParlTranslocoLoader,\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.UtilsService"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,19 @@
1
1
  {
2
2
  "name": "@trixwell/ngx-parl",
3
- "version": "1.2.3",
3
+ "version": "1.2.6",
4
4
  "license": "LGPL-3.0",
5
+ "main": "bundles/trixwell-ngx-parl.umd.js",
6
+ "module": "fesm2022/trixwell-ngx-parl.mjs",
7
+ "typings": "index.d.ts",
8
+ "files": [
9
+ "bundles/",
10
+ "fesm2022/",
11
+ "esm2022/",
12
+ "lib/",
13
+ "assets/",
14
+ "package.json",
15
+ "README.md"
16
+ ],
5
17
  "description": "Highly customizable Angular Material chat component",
6
18
  "keywords": [
7
19
  "angular",
@@ -23,8 +35,6 @@
23
35
  "tslib": "^2.3.0"
24
36
  },
25
37
  "sideEffects": false,
26
- "module": "fesm2022/trixwell-ngx-parl.mjs",
27
- "typings": "index.d.ts",
28
38
  "exports": {
29
39
  "./package.json": {
30
40
  "default": "./package.json"
package/index.d.ts DELETED
@@ -1,80 +0,0 @@
1
- import * as _angular_core from '@angular/core';
2
- import { TranslocoService } from '@ngneat/transloco';
3
- import { HttpClient } from '@angular/common/http';
4
-
5
- declare class ChatMessage {
6
- id: number;
7
- chat_id: number;
8
- cr_time: string;
9
- type: ChatMessageType;
10
- user: string;
11
- content: string;
12
- avatar: string | null;
13
- file_path: string[] | null;
14
- checked: boolean | null;
15
- edit: boolean;
16
- constructor(data: ChatMessageDTO);
17
- get dateSimple(): string;
18
- get timeHHmm(): string;
19
- }
20
- interface ChatMessageDTO {
21
- id: number;
22
- chat_id: number;
23
- cr_time: string;
24
- type: ChatMessageType;
25
- user: string;
26
- content: string;
27
- avatar?: string | null;
28
- file_path?: string[] | null;
29
- checked?: boolean | null;
30
- }
31
- type ChatMessageType = 'incoming' | 'outgoing';
32
-
33
- declare class UtilsService {
34
- protected http: HttpClient;
35
- constructor(http: HttpClient);
36
- langToLocale(lang: string): string;
37
- getLocalISODate(): string;
38
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<UtilsService, never>;
39
- static ɵprov: _angular_core.ɵɵInjectableDeclaration<UtilsService>;
40
- }
41
-
42
- declare enum FlowTheme {
43
- PRIMARY = "primary",
44
- SECONDARY = "secondary"
45
- }
46
-
47
- declare class NgxParlComponent {
48
- private utils;
49
- private transloco;
50
- ai_run_in_progress: boolean;
51
- private lastUpdateKey;
52
- theme: _angular_core.InputSignal<FlowTheme>;
53
- header: _angular_core.InputSignal<boolean>;
54
- language: _angular_core.InputSignal<"uk" | "en">;
55
- messageList: _angular_core.ModelSignal<ChatMessage[]>;
56
- messageUpdate: _angular_core.ModelSignal<ChatMessage | undefined>;
57
- selectedForEdit: _angular_core.ModelSignal<ChatMessage | null>;
58
- incomingUser: _angular_core.Signal<string>;
59
- hideHandler: _angular_core.InputSignal<(() => unknown) | null>;
60
- closeHandler: _angular_core.InputSignal<(() => unknown) | null>;
61
- constructor(utils: UtilsService, transloco: TranslocoService);
62
- onCancelEdit(messageId: number | null): this;
63
- sendMessage(event: string | {
64
- id: number;
65
- content: string;
66
- files?: string[];
67
- } | {
68
- content: string;
69
- files?: string[];
70
- } | undefined): this;
71
- onHideClick(): this;
72
- onCloseClick(): this;
73
- protected readonly FlowTheme: typeof FlowTheme;
74
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgxParlComponent, never>;
75
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgxParlComponent, "ngx-parl", never, { "theme": { "alias": "theme"; "required": false; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "language": { "alias": "language"; "required": false; "isSignal": true; }; "messageList": { "alias": "messageList"; "required": false; "isSignal": true; }; "messageUpdate": { "alias": "messageUpdate"; "required": false; "isSignal": true; }; "selectedForEdit": { "alias": "selectedForEdit"; "required": false; "isSignal": true; }; "hideHandler": { "alias": "hideHandler"; "required": false; "isSignal": true; }; "closeHandler": { "alias": "closeHandler"; "required": false; "isSignal": true; }; }, { "messageList": "messageListChange"; "messageUpdate": "messageUpdateChange"; "selectedForEdit": "selectedForEditChange"; }, never, never, true, never>;
76
- }
77
-
78
- declare function provideNgxParl(): _angular_core.EnvironmentProviders[];
79
-
80
- export { NgxParlComponent, provideNgxParl };
Binary file
Binary file
Binary file
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes