croco-html 4.9.0 → 4.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
14
14
  import * as i29 from '@angular/material/button-toggle';
15
15
  import { MatButtonToggleGroup, MatButtonToggle, MatButtonToggleModule } from '@angular/material/button-toggle';
16
16
  import { Subject, takeUntil, BehaviorSubject } from 'rxjs';
17
- import * as i5 from '@ng-select/ng-select';
17
+ import * as i6 from '@ng-select/ng-select';
18
18
  import { NgSelectModule } from '@ng-select/ng-select';
19
19
  import * as i1$2 from '@angular/platform-browser';
20
20
  import * as i1$3 from '@angular/material/card';
@@ -36,7 +36,7 @@ import * as i11 from '@angular/material/select';
36
36
  import { MatSelect, MatSelectModule } from '@angular/material/select';
37
37
  import * as i7 from '@angular/material/progress-spinner';
38
38
  import { MatProgressSpinner, MatProgressSpinnerModule } from '@angular/material/progress-spinner';
39
- import * as i5$1 from '@angular/material/tabs';
39
+ import * as i5 from '@angular/material/tabs';
40
40
  import { MatTabsModule } from '@angular/material/tabs';
41
41
  import * as i2$2 from '@angular/material/dialog';
42
42
  import { MatDialogTitle, MatDialogContent, MatDialogActions, MatDialogModule } from '@angular/material/dialog';
@@ -59,7 +59,7 @@ import * as i9 from '@angular/material/menu';
59
59
  import { MatMenuModule } from '@angular/material/menu';
60
60
  import * as i19 from '@angular/material/paginator';
61
61
  import { MatPaginatorModule } from '@angular/material/paginator';
62
- import * as i6 from '@angular/material/progress-bar';
62
+ import * as i6$1 from '@angular/material/progress-bar';
63
63
  import { MatProgressBarModule } from '@angular/material/progress-bar';
64
64
  import * as i26 from '@angular/material/sidenav';
65
65
  import { MatSidenavModule } from '@angular/material/sidenav';
@@ -136,7 +136,7 @@ class AngularMaterialTableMethods {
136
136
  class FileAudioTagDataConsts {
137
137
  static { this.TagName = "audio-player"; }
138
138
  static { this.FileIdAttrName = "file-id"; }
139
- static { this.FileNameAttrName = "file-name"; }
139
+ static { this.TitleAttrName = "title"; }
140
140
  }
141
141
  class AudioMethods {
142
142
  static buildUrl(fileId, fileName) {
@@ -746,27 +746,25 @@ class FileAudioTagService {
746
746
  }
747
747
  bodyTagToHtmlStringConverter(bodyTag) {
748
748
  let fileIdAttr = "";
749
- let fileNameAttr = "";
749
+ let titleAttr = "";
750
750
  if (bodyTag.attributes.hasOwnProperty(FileAudioTagDataConsts.FileIdAttrName) &&
751
751
  bodyTag.attributes[FileAudioTagDataConsts.FileIdAttrName]) {
752
752
  fileIdAttr = `${FileAudioTagDataConsts.FileIdAttrName}="${bodyTag.attributes[FileAudioTagDataConsts.FileIdAttrName]}"`;
753
753
  }
754
- if (bodyTag.attributes.hasOwnProperty(FileAudioTagDataConsts.FileNameAttrName) &&
755
- bodyTag.attributes[FileAudioTagDataConsts.FileNameAttrName]) {
756
- fileNameAttr = ` ${FileAudioTagDataConsts.FileNameAttrName}="${bodyTag.attributes[FileAudioTagDataConsts.FileNameAttrName]}"`;
754
+ if (bodyTag.attributes.hasOwnProperty(FileAudioTagDataConsts.TitleAttrName) &&
755
+ bodyTag.attributes[FileAudioTagDataConsts.TitleAttrName]) {
756
+ titleAttr = `${FileAudioTagDataConsts.TitleAttrName}="${bodyTag.attributes[FileAudioTagDataConsts.TitleAttrName]}"`;
757
757
  }
758
- return `<${FileAudioTagDataConsts.TagName} ${fileIdAttr}${fileNameAttr}></${FileAudioTagDataConsts.TagName}>`;
758
+ return `<${FileAudioTagDataConsts.TagName} ${fileIdAttr} ${titleAttr}></${FileAudioTagDataConsts.TagName}>`;
759
759
  }
760
760
  extractBlockFromHtmlElement(elem, options) {
761
761
  let fileId = elem.getAttribute(FileAudioTagDataConsts.FileIdAttrName);
762
- let fileName = elem.getAttribute(FileAudioTagDataConsts.FileNameAttrName);
763
- let src = AudioMethods.buildUrl(fileId, fileName);
762
+ let title = elem.getAttribute(FileAudioTagDataConsts.TitleAttrName);
764
763
  return {
765
764
  tagName: FileAudioTagDataConsts.TagName,
766
765
  data: {
767
- src,
768
766
  fileId: fileId,
769
- fileName: fileName
767
+ title: title
770
768
  }
771
769
  };
772
770
  }
@@ -776,8 +774,8 @@ class FileAudioTagService {
776
774
  if (fileData.fileId) {
777
775
  attrs[FileAudioTagDataConsts.FileIdAttrName] = fileData.fileId;
778
776
  }
779
- if (fileData.fileName) {
780
- attrs[FileAudioTagDataConsts.FileNameAttrName] = fileData.fileName;
777
+ if (fileData.title) {
778
+ attrs[FileAudioTagDataConsts.TitleAttrName] = fileData.title;
781
779
  }
782
780
  return {
783
781
  tagDescription: {
@@ -798,7 +796,7 @@ class FileAudioTagService {
798
796
  },
799
797
  attributes: {
800
798
  [FileAudioTagDataConsts.FileIdAttrName]: '',
801
- [FileAudioTagDataConsts.FileNameAttrName]: ''
799
+ [FileAudioTagDataConsts.TitleAttrName]: ''
802
800
  },
803
801
  innerHtml: "",
804
802
  };
@@ -1479,20 +1477,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1479
1477
  args: ['BASE_URL']
1480
1478
  }] }] });
1481
1479
 
1480
+ class CommonFileInfoQueryService {
1481
+ constructor(_httpClient, baseUrl) {
1482
+ this._httpClient = _httpClient;
1483
+ this._baseControllerUrl = `${baseUrl}api/common-files`;
1484
+ }
1485
+ /**
1486
+ * Получить информацию о файле на сервере по идентификатору.
1487
+ * @param model
1488
+ * @returns
1489
+ */
1490
+ getInfo(id) {
1491
+ return this._httpClient.get(`${this._baseControllerUrl}/query/get-info/${id}`);
1492
+ }
1493
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CommonFileInfoQueryService, deps: [{ token: i1.HttpClient }, { token: 'BASE_URL' }], target: i0.ɵɵFactoryTarget.Injectable }); }
1494
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CommonFileInfoQueryService, providedIn: 'root' }); }
1495
+ }
1496
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CommonFileInfoQueryService, decorators: [{
1497
+ type: Injectable,
1498
+ args: [{
1499
+ providedIn: 'root'
1500
+ }]
1501
+ }], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
1502
+ type: Inject,
1503
+ args: ['BASE_URL']
1504
+ }] }] });
1505
+
1482
1506
  class AudioEditorComponent {
1483
- constructor(_publicFileService, _privateFileService, _htmlSettingsService) {
1507
+ constructor(_publicFileService, _privateFileService, _htmlSettingsService, _commonFileInfoService) {
1484
1508
  this._publicFileService = _publicFileService;
1485
1509
  this._privateFileService = _privateFileService;
1486
1510
  this._htmlSettingsService = _htmlSettingsService;
1511
+ this._commonFileInfoService = _commonFileInfoService;
1487
1512
  this.hasAudioError = false;
1513
+ this.errorMessage = '';
1488
1514
  this.isPlaying = false;
1489
1515
  this.isLoading = false;
1490
1516
  this.currentTime = 0;
1491
1517
  this.duration = 0;
1492
1518
  this.volume = 1;
1493
1519
  this.isMuted = false;
1520
+ this.audioSrc = '';
1494
1521
  this.searchOrEdit = "search";
1495
- this.fileName = '';
1496
1522
  this.files = [];
1497
1523
  this.loading = false;
1498
1524
  this.q = '';
@@ -1505,39 +1531,69 @@ class AudioEditorComponent {
1505
1531
  set fileId(value) {
1506
1532
  this.tag.attributes[FileAudioTagDataConsts.FileIdAttrName] = value;
1507
1533
  }
1508
- get fileNameAttr() {
1509
- return this.tag.attributes[FileAudioTagDataConsts.FileNameAttrName];
1534
+ get title() {
1535
+ return this.tag.attributes[FileAudioTagDataConsts.TitleAttrName] || '';
1510
1536
  }
1511
- set fileNameAttr(value) {
1512
- this.tag.attributes[FileAudioTagDataConsts.FileNameAttrName] = value;
1537
+ set title(value) {
1538
+ this.tag.attributes[FileAudioTagDataConsts.TitleAttrName] = value;
1513
1539
  }
1514
1540
  hasFileId() {
1515
1541
  return this.tag.attributes.hasOwnProperty(FileAudioTagDataConsts.FileIdAttrName) && this.fileId && this.fileId !== '';
1516
1542
  }
1517
- getSrc() {
1518
- // return AudioMethods.buildUrl(this.fileId, this.fileNameAttr);
1519
- return this.fileId;
1520
- }
1521
1543
  get audioElement() {
1522
1544
  return this.audioPlayer?.nativeElement || null;
1523
1545
  }
1524
1546
  onErrorHandler() {
1525
1547
  this.hasAudioError = true;
1526
1548
  this.isLoading = false;
1549
+ if (!this.errorMessage) {
1550
+ this.errorMessage = 'Аудио-файл не найден по указанному идентификатору, возможно файл не существует или отсутствует на сервере.';
1551
+ }
1527
1552
  }
1528
1553
  removeAudioError() {
1529
1554
  this.hasAudioError = false;
1555
+ this.errorMessage = '';
1556
+ }
1557
+ setError(message) {
1558
+ this.hasAudioError = true;
1559
+ this.errorMessage = message;
1560
+ this.isLoading = false;
1530
1561
  }
1531
1562
  onFileIdChanged(fileId) {
1532
1563
  this.fileId = fileId;
1533
1564
  this.removeAudioError();
1534
- this.loadAudioFile();
1565
+ this.checkAndLoadAudioFile();
1535
1566
  }
1536
- onFileNameChanged(fileName) {
1537
- this.fileNameAttr = fileName;
1567
+ checkAndLoadAudioFile() {
1568
+ if (!this.hasFileId()) {
1569
+ return;
1570
+ }
1571
+ this.isLoading = true;
1572
+ this.hasAudioError = false;
1573
+ this.errorMessage = '';
1574
+ const fileIdValue = this.fileId;
1575
+ this._commonFileInfoService.getInfo(fileIdValue)
1576
+ .pipe(takeUntil(this.unsubscribe))
1577
+ .subscribe({
1578
+ next: (result) => {
1579
+ if (!result.fileInfo) {
1580
+ this.setError(`Файл с идентификатором ${fileIdValue} не найден на сервере.`);
1581
+ return;
1582
+ }
1583
+ if (result.fileInfo.type !== FileType.Audio) {
1584
+ this.setError(`Файл с идентификатором ${fileIdValue} должен быть c типом Audio, а получено ${result.fileInfo.type}.`);
1585
+ return;
1586
+ }
1587
+ this.audioSrc = result.fileInfo.downloadUrl;
1588
+ this.loadAudioFile();
1589
+ },
1590
+ error: (error) => {
1591
+ this.setError(`Ошибка при получении информации о файле: ${error.message || 'Неизвестная ошибка'}`);
1592
+ }
1593
+ });
1538
1594
  }
1539
1595
  loadAudioFile() {
1540
- if (!this.hasFileId()) {
1596
+ if (!this.hasFileId() || !this.audioSrc) {
1541
1597
  return;
1542
1598
  }
1543
1599
  this.isLoading = true;
@@ -1675,22 +1731,22 @@ class AudioEditorComponent {
1675
1731
  onFileSelected(fileId) {
1676
1732
  const selectedFile = this.files.find(f => f.fileId === fileId);
1677
1733
  if (selectedFile) {
1678
- //TODO заглушка
1679
- this.fileId = "./ona_ne_tvoya.mp3";
1680
- this.fileNameAttr = selectedFile.fileName;
1681
- this.loadAudioFile();
1734
+ this.fileId = fileId;
1735
+ this.checkAndLoadAudioFile();
1682
1736
  }
1683
1737
  }
1684
1738
  onFilesUploaded(fileIds) {
1685
1739
  if (fileIds && fileIds.length > 0) {
1686
- //TODO заглушка
1687
- this.fileId = '"./ona_ne_tvoya.mp3"';
1740
+ const firstFileId = fileIds[0];
1741
+ this.fileId = typeof firstFileId === 'number' ? firstFileId.toString() : firstFileId;
1688
1742
  this.loadFiles();
1743
+ this.checkAndLoadAudioFile();
1689
1744
  }
1690
1745
  }
1691
1746
  removeAudio() {
1692
1747
  this.fileId = '';
1693
- this.fileNameAttr = '';
1748
+ this.title = '';
1749
+ this.audioSrc = '';
1694
1750
  this.isPlaying = false;
1695
1751
  this.currentTime = 0;
1696
1752
  this.duration = 0;
@@ -1700,9 +1756,9 @@ class AudioEditorComponent {
1700
1756
  if (this.audioPlayer?.nativeElement) {
1701
1757
  const audio = this.audioPlayer.nativeElement;
1702
1758
  audio.volume = this.volume;
1703
- if (this.hasFileId()) {
1704
- this.loadAudioFile();
1705
- }
1759
+ }
1760
+ if (this.hasFileId()) {
1761
+ this.checkAndLoadAudioFile();
1706
1762
  }
1707
1763
  this.loadFiles();
1708
1764
  }
@@ -1710,8 +1766,8 @@ class AudioEditorComponent {
1710
1766
  this.unsubscribe.next();
1711
1767
  this.unsubscribe.complete();
1712
1768
  }
1713
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AudioEditorComponent, deps: [{ token: PublicFilesQueryService }, { token: PrivateFilesQueryService }, { token: CrocoHtmlFileOptionsService }], target: i0.ɵɵFactoryTarget.Component }); }
1714
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AudioEditorComponent, isStandalone: true, selector: "croco-html-audio-editor", inputs: { tag: "tag", presentOrEdit: "presentOrEdit" }, viewQueries: [{ propertyName: "audioPlayer", first: true, predicate: ["audioPlayer"], descendants: true }], ngImport: i0, template: "<div class=\"audio-editor\">\n @if (hasAudioError) {\n <div class=\"error-block\">\n <mat-icon>error</mat-icon>\n <span>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u043F\u043E \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0444\u0430\u0439\u043B \u043D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043B\u0438 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.</span>\n </div>\n }\n\n @if (hasFileId() && !hasAudioError) {\n <div class=\"audio-player-container\">\n <audio\n #audioPlayer\n [src]=\"getSrc()\"\n (error)=\"onErrorHandler()\"\n (loadedmetadata)=\"onLoadedMetadata()\"\n (timeupdate)=\"onTimeUpdate()\"\n (ended)=\"onEnded()\"\n (canplay)=\"onCanPlay()\"\n preload=\"metadata\">\n </audio>\n\n @if (isLoading) {\n <div class=\"loading-indicator\">\n <div class=\"progress-bar\">\n <div class=\"progress-bar-fill\"></div>\n </div>\n <span>\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0430\u0443\u0434\u0438\u043E...</span>\n </div>\n }\n\n <div class=\"player-controls\">\n <div class=\"control-buttons\">\n <button (click)=\"restart()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay</mat-icon>\n </button>\n\n <button (click)=\"rewind()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay_10</mat-icon>\n </button>\n\n <button\n (click)=\"togglePlayPause()\"\n [disabled]=\"!hasFileId() || isLoading\"\n class=\"play-pause-btn\" mat-icon-button>\n <mat-icon>{{ isPlaying ? 'pause' : 'play_arrow' }}</mat-icon>\n </button>\n\n <button (click)=\"forward()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>forward_10</mat-icon>\n </button>\n\n @if (!presentOrEdit) {\n <button (click)=\"removeAudio()\" [disabled]=\"!hasFileId()\" color=\"warn\" mat-icon-button>\n <mat-icon>delete</mat-icon>\n </button>\n }\n </div>\n\n <div class=\"progress-section\">\n <span class=\"time-display\">{{ formatTime(currentTime) }}</span>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"getProgress()\"\n (input)=\"onSeekChange($event)\"\n [disabled]=\"!hasFileId() || duration === 0\"\n class=\"progress-slider\">\n\n <span class=\"time-display\">{{ formatTime(duration) }}</span>\n </div>\n\n <div class=\"volume-controls\">\n <button (click)=\"toggleMute()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>{{ isMuted ? 'volume_off' : 'volume_up' }}</mat-icon>\n </button>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volume * 100\"\n (input)=\"onVolumeChange($event)\"\n [disabled]=\"!hasFileId()\"\n class=\"volume-slider\">\n </div>\n </div>\n </div>\n }\n\n @if (!hasFileId()) {\n <div class=\"no-file-message\">\n <mat-icon>music_off</mat-icon>\n <h5>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D</h5>\n @if (!presentOrEdit) {\n <p>\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u043A\u043D\u043E\u043F\u043A\u0443 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0434\u043B\u044F \u0432\u044B\u0431\u043E\u0440\u0430 \u0438\u043B\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</p>\n }\n </div>\n }\n @if (!presentOrEdit) {\n <div class=\"edit-panel\">\n <div class=\"edit-header\">\n <h6>\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</h6>\n </div>\n\n <div class=\"mode-toggle\">\n <mat-button-toggle-group [(ngModel)]=\"searchOrEdit\">\n <mat-button-toggle value=\"search\">\n <mat-icon>search</mat-icon>\n \u0418\u0441\u043A\u0430\u0442\u044C \u0444\u0430\u0439\u043B\n </mat-button-toggle>\n <mat-button-toggle value=\"edit\">\n <mat-icon>settings</mat-icon>\n \u0423\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E ID\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n @if (searchOrEdit === 'search') {\n <div class=\"file-selection\">\n <div class=\"existing-files\">\n <h6>\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0438\u0437 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0445 \u0444\u0430\u0439\u043B\u043E\u0432:</h6>\n <ng-select\n [(ngModel)]=\"fileId\"\n (ngModelChange)=\"onFileSelected($event)\"\n [items]=\"files\"\n bindLabel=\"fileName\"\n bindValue=\"fileId\"\n (search)=\"onSearchChanged($event)\"\n [loading]=\"loading\"\n [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\"\n [clearable]=\"true\">\n <ng-template ng-option-tmp let-item=\"item\">\n <div class=\"file-option\">\n <mat-icon>audiotrack</mat-icon>\n <span>{{ item.fileName }}</span>\n <small>ID: {{ item.fileId }}</small>\n </div>\n </ng-template>\n </ng-select>\n </div>\n\n <div class=\"upload-section\">\n <h6>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u0444\u0430\u0439\u043B:</h6>\n <croco-app-upload-files-btn\n extAccepts=\"audio/*\"\n [isMultiple]=\"false\"\n btnText=\"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\"\n (onPublicFilesUploaded)=\"onFilesUploaded($event.fileIds)\"\n (onPrivateFilesUploaded)=\"onFilesUploaded($event.fileIds)\">\n </croco-app-upload-files-btn>\n </div>\n </div>\n } @else if (searchOrEdit === 'edit') {\n <div class=\"manual-input\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 ID \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"fileId\"\n (ngModelChange)=\"onFileIdChanged($event)\">\n </mat-form-field>\n\n <mat-form-field class=\"w-100\">\n <mat-label>\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043C\u044F \u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"fileNameAttr\"\n (ngModelChange)=\"onFileNameChanged($event)\">\n </mat-form-field>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".audio-editor{width:100%;padding:16px;background:#fafafa;border-radius:8px;border:1px solid #e0e0e0}.error-block{display:flex;align-items:center;gap:8px;background-color:#ffebee;color:#c62828;padding:12px;border-radius:8px;border:1px solid #ffcdd2;margin-bottom:16px}.error-block mat-icon{color:#c62828}.audio-player-container{background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 8px #0000001a;margin-bottom:16px}.loading-indicator{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;color:#666}.loading-indicator .progress-bar{width:200px;height:4px;background-color:#e0e0e0;border-radius:2px;overflow:hidden}.loading-indicator .progress-bar .progress-bar-fill{height:100%;background-color:#1976d2;animation:loading 1.5s ease-in-out infinite}@keyframes loading{0%{transform:translate(-100%)}50%{transform:translate(0)}to{transform:translate(100%)}}.file-info{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px;background:#f5f5f5;border-radius:8px}.file-info mat-icon{color:#1976d2}.file-info .file-name{font-weight:500;flex:1}.file-info .edit-btn{margin-left:auto}.player-controls{display:flex;flex-direction:column;gap:16px}.control-buttons{display:flex;justify-content:center;align-items:center;gap:8px}.control-buttons .play-pause-btn{background-color:#1976d2;color:#fff;width:48px;height:48px}.control-buttons .play-pause-btn:hover{background-color:#1565c0}.control-buttons .play-pause-btn mat-icon{font-size:24px}.control-buttons mat-icon-button{width:40px;height:40px}.control-buttons mat-icon-button:disabled{color:#ccc}.progress-section{display:flex;align-items:center;gap:12px}.progress-section .time-display{font-family:Roboto Mono,monospace;font-size:14px;color:#666;min-width:40px;text-align:center}.progress-section .progress-slider{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.progress-section .progress-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider:hover::-webkit-slider-thumb{background:#1565c0}.progress-section .progress-slider:hover::-moz-range-thumb{background:#1565c0}.volume-controls{display:flex;align-items:center;gap:8px;justify-content:center}.volume-controls .volume-slider{width:100px;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.volume-controls .volume-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider:hover::-webkit-slider-thumb{background:#1565c0}.volume-controls .volume-slider:hover::-moz-range-thumb{background:#1565c0}.no-file-message{text-align:center;padding:40px 20px;color:#666}.no-file-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;color:#ccc}.no-file-message h5{margin:0 0 8px;color:#999}.no-file-message p{margin:0;font-size:14px;color:#999}.edit-panel{background:#fff;border-radius:8px;padding:20px;border:1px solid #e0e0e0;margin-top:16px}.edit-panel .edit-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.edit-panel .edit-header h6{margin:0;color:#333}.edit-panel .mode-toggle{margin-bottom:20px}.edit-panel .mode-toggle mat-button-toggle-group{width:100%}.edit-panel .mode-toggle mat-button-toggle{flex:1;display:flex;align-items:center;justify-content:center;gap:8px}.edit-panel .file-selection{display:flex;flex-direction:column;gap:20px}.edit-panel .file-selection h6{margin:0 0 12px;color:#333}.edit-panel .file-selection .file-option{display:flex;align-items:center;gap:8px}.edit-panel .file-selection .file-option mat-icon{color:#1976d2}.edit-panel .file-selection .file-option small{margin-left:auto;color:#666}.edit-panel .file-selection .upload-section{padding-top:16px;border-top:1px solid #e0e0e0}.edit-panel .manual-input{display:flex;flex-direction:column;gap:16px}.edit-button-container{display:flex;justify-content:center;margin-top:16px}.edit-button-container .edit-mode-btn{background-color:#1976d2;color:#fff}.edit-button-container .edit-mode-btn:hover{background-color:#1565c0}@media screen and (max-width: 768px){.audio-editor{padding:12px}.audio-player-container{padding:16px}.control-buttons{flex-wrap:wrap;gap:4px}.progress-section{flex-direction:column;gap:8px}.progress-section .progress-slider{width:100%}.volume-controls{justify-content:flex-start}.volume-controls .volume-slider{width:80px}.edit-panel{padding:16px}.edit-panel .mode-toggle mat-button-toggle-group{flex-direction:column}}::ng-deep .ng-select .ng-select-container{border-radius:4px;border:1px solid #ccc}::ng-deep .ng-select.ng-select-focused .ng-select-container{border-color:#1976d2}input[type=range].progress-slider:disabled,input[type=range].volume-slider:disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: UploadFilesBtnComponent, selector: "croco-app-upload-files-btn", inputs: ["extAccepts", "isMultiple", "btnText", "hidden"], outputs: ["postFilesStarted", "onPublicFilesUploaded", "onPrivateFilesUploaded"] }, { kind: "ngmodule", type: NgSelectModule }, { kind: "component", type: i5.NgSelectComponent, selector: "ng-select", inputs: ["ariaLabelDropdown", "bindLabel", "bindValue", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "tabFocusOnClearButton", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: i5.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] }); }
1769
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AudioEditorComponent, deps: [{ token: PublicFilesQueryService }, { token: PrivateFilesQueryService }, { token: CrocoHtmlFileOptionsService }, { token: CommonFileInfoQueryService }], target: i0.ɵɵFactoryTarget.Component }); }
1770
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AudioEditorComponent, isStandalone: true, selector: "croco-html-audio-editor", inputs: { tag: "tag", presentOrEdit: "presentOrEdit" }, viewQueries: [{ propertyName: "audioPlayer", first: true, predicate: ["audioPlayer"], descendants: true }], ngImport: i0, template: "<div class=\"audio-editor\">\n @if (hasAudioError) {\n <div class=\"error-block\">\n <mat-icon>error</mat-icon>\n <span>{{ errorMessage }}</span>\n </div>\n }\n\n @if (hasFileId() && !hasAudioError) {\n <div class=\"audio-player-container\">\n <audio\n #audioPlayer\n [src]=\"audioSrc\"\n (error)=\"onErrorHandler()\"\n (loadedmetadata)=\"onLoadedMetadata()\"\n (timeupdate)=\"onTimeUpdate()\"\n (ended)=\"onEnded()\"\n (canplay)=\"onCanPlay()\"\n preload=\"metadata\">\n </audio>\n\n @if (isLoading) {\n <div class=\"loading-indicator\">\n <div class=\"progress-bar\">\n <div class=\"progress-bar-fill\"></div>\n </div>\n <span>\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0430\u0443\u0434\u0438\u043E...</span>\n </div>\n }\n\n <div class=\"player-controls\">\n <div class=\"control-buttons\">\n <button (click)=\"restart()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay</mat-icon>\n </button>\n\n <button (click)=\"rewind()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay_10</mat-icon>\n </button>\n\n <button\n (click)=\"togglePlayPause()\"\n [disabled]=\"!hasFileId() || isLoading\"\n class=\"play-pause-btn\" mat-icon-button>\n <mat-icon>{{ isPlaying ? 'pause' : 'play_arrow' }}</mat-icon>\n </button>\n\n <button (click)=\"forward()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>forward_10</mat-icon>\n </button>\n\n @if (!presentOrEdit) {\n <button (click)=\"removeAudio()\" [disabled]=\"!hasFileId()\" color=\"warn\" mat-icon-button>\n <mat-icon>delete</mat-icon>\n </button>\n }\n </div>\n\n <div class=\"progress-section\">\n <span class=\"time-display\">{{ formatTime(currentTime) }}</span>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"getProgress()\"\n (input)=\"onSeekChange($event)\"\n [disabled]=\"!hasFileId() || duration === 0\"\n class=\"progress-slider\">\n\n <span class=\"time-display\">{{ formatTime(duration) }}</span>\n </div>\n\n <div class=\"volume-controls\">\n <button (click)=\"toggleMute()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>{{ isMuted ? 'volume_off' : 'volume_up' }}</mat-icon>\n </button>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volume * 100\"\n (input)=\"onVolumeChange($event)\"\n [disabled]=\"!hasFileId()\"\n class=\"volume-slider\">\n </div>\n </div>\n </div>\n }\n\n @if (!hasFileId()) {\n <div class=\"no-file-message\">\n <mat-icon>music_off</mat-icon>\n <h5>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D</h5>\n @if (!presentOrEdit) {\n <p>\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u043A\u043D\u043E\u043F\u043A\u0443 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0434\u043B\u044F \u0432\u044B\u0431\u043E\u0440\u0430 \u0438\u043B\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</p>\n }\n </div>\n }\n @if (!presentOrEdit) {\n <div class=\"edit-panel\">\n <div class=\"edit-header\">\n <h6>\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</h6>\n </div>\n\n <div class=\"mode-toggle\">\n <mat-button-toggle-group [(ngModel)]=\"searchOrEdit\">\n <mat-button-toggle value=\"search\">\n <mat-icon>search</mat-icon>\n \u0418\u0441\u043A\u0430\u0442\u044C \u0444\u0430\u0439\u043B\n </mat-button-toggle>\n <mat-button-toggle value=\"edit\">\n <mat-icon>settings</mat-icon>\n \u0423\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E ID\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n @if (searchOrEdit === 'search') {\n <div class=\"file-selection\">\n <div class=\"existing-files\">\n <h6>\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0438\u0437 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0445 \u0444\u0430\u0439\u043B\u043E\u0432:</h6>\n <ng-select\n [(ngModel)]=\"fileId\"\n (ngModelChange)=\"onFileSelected($event)\"\n [items]=\"files\"\n bindLabel=\"fileName\"\n bindValue=\"fileId\"\n (search)=\"onSearchChanged($event)\"\n [loading]=\"loading\"\n [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\"\n [clearable]=\"true\">\n <ng-template ng-option-tmp let-item=\"item\">\n <div class=\"file-option\">\n <mat-icon>audiotrack</mat-icon>\n <span>{{ item.fileName }}</span>\n <small>ID: {{ item.fileId }}</small>\n </div>\n </ng-template>\n </ng-select>\n </div>\n\n <div class=\"title-input\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"title\">\n </mat-form-field>\n </div>\n\n <div class=\"upload-section\">\n <h6>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u0444\u0430\u0439\u043B:</h6>\n <croco-app-upload-files-btn\n extAccepts=\"audio/*\"\n [isMultiple]=\"false\"\n btnText=\"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\"\n (onPublicFilesUploaded)=\"onFilesUploaded($event.fileIds)\"\n (onPrivateFilesUploaded)=\"onFilesUploaded($event.fileIds)\">\n </croco-app-upload-files-btn>\n </div>\n </div>\n } @else if (searchOrEdit === 'edit') {\n <div class=\"manual-input\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 ID \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"fileId\"\n (ngModelChange)=\"onFileIdChanged($event)\">\n </mat-form-field>\n\n <mat-form-field class=\"w-100\">\n <mat-label>\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"title\">\n </mat-form-field>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".audio-editor{width:100%;padding:16px;background:#fafafa;border-radius:8px;border:1px solid #e0e0e0}.error-block{display:flex;align-items:center;gap:8px;background-color:#ffebee;color:#c62828;padding:12px;border-radius:8px;border:1px solid #ffcdd2;margin-bottom:16px}.error-block mat-icon{color:#c62828}.audio-player-container{background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 8px #0000001a;margin-bottom:16px}.loading-indicator{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;color:#666}.loading-indicator .progress-bar{width:200px;height:4px;background-color:#e0e0e0;border-radius:2px;overflow:hidden}.loading-indicator .progress-bar .progress-bar-fill{height:100%;background-color:#1976d2;animation:loading 1.5s ease-in-out infinite}@keyframes loading{0%{transform:translate(-100%)}50%{transform:translate(0)}to{transform:translate(100%)}}.file-info{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px;background:#f5f5f5;border-radius:8px}.file-info mat-icon{color:#1976d2}.file-info .file-name{font-weight:500;flex:1}.file-info .edit-btn{margin-left:auto}.player-controls{display:flex;flex-direction:column;gap:16px}.control-buttons{display:flex;justify-content:center;align-items:center;gap:8px}.control-buttons .play-pause-btn{background-color:#1976d2;color:#fff;width:48px;height:48px}.control-buttons .play-pause-btn:hover{background-color:#1565c0}.control-buttons .play-pause-btn mat-icon{font-size:24px}.control-buttons mat-icon-button{width:40px;height:40px}.control-buttons mat-icon-button:disabled{color:#ccc}.progress-section{display:flex;align-items:center;gap:12px}.progress-section .time-display{font-family:Roboto Mono,monospace;font-size:14px;color:#666;min-width:40px;text-align:center}.progress-section .progress-slider{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.progress-section .progress-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider:hover::-webkit-slider-thumb{background:#1565c0}.progress-section .progress-slider:hover::-moz-range-thumb{background:#1565c0}.volume-controls{display:flex;align-items:center;gap:8px;justify-content:center}.volume-controls .volume-slider{width:100px;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.volume-controls .volume-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider:hover::-webkit-slider-thumb{background:#1565c0}.volume-controls .volume-slider:hover::-moz-range-thumb{background:#1565c0}.no-file-message{text-align:center;padding:40px 20px;color:#666}.no-file-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;color:#ccc}.no-file-message h5{margin:0 0 8px;color:#999}.no-file-message p{margin:0;font-size:14px;color:#999}.edit-panel{background:#fff;border-radius:8px;padding:20px;border:1px solid #e0e0e0;margin-top:16px}.edit-panel .edit-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.edit-panel .edit-header h6{margin:0;color:#333}.edit-panel .mode-toggle{margin-bottom:20px}.edit-panel .mode-toggle mat-button-toggle-group{width:100%}.edit-panel .mode-toggle mat-button-toggle{flex:1;display:flex;align-items:center;justify-content:center;gap:8px}.edit-panel .file-selection{display:flex;flex-direction:column;gap:20px}.edit-panel .file-selection h6{margin:0 0 12px;color:#333}.edit-panel .file-selection .file-option{display:flex;align-items:center;gap:8px}.edit-panel .file-selection .file-option mat-icon{color:#1976d2}.edit-panel .file-selection .file-option small{margin-left:auto;color:#666}.edit-panel .file-selection .upload-section{padding-top:16px;border-top:1px solid #e0e0e0}.edit-panel .manual-input{display:flex;flex-direction:column;gap:16px}.edit-button-container{display:flex;justify-content:center;margin-top:16px}.edit-button-container .edit-mode-btn{background-color:#1976d2;color:#fff}.edit-button-container .edit-mode-btn:hover{background-color:#1565c0}@media screen and (max-width: 768px){.audio-editor{padding:12px}.audio-player-container{padding:16px}.control-buttons{flex-wrap:wrap;gap:4px}.progress-section{flex-direction:column;gap:8px}.progress-section .progress-slider{width:100%}.volume-controls{justify-content:flex-start}.volume-controls .volume-slider{width:80px}.edit-panel{padding:16px}.edit-panel .mode-toggle mat-button-toggle-group{flex-direction:column}}::ng-deep .ng-select .ng-select-container{border-radius:4px;border:1px solid #ccc}::ng-deep .ng-select.ng-select-focused .ng-select-container{border-color:#1976d2}input[type=range].progress-slider:disabled,input[type=range].volume-slider:disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: UploadFilesBtnComponent, selector: "croco-app-upload-files-btn", inputs: ["extAccepts", "isMultiple", "btnText", "hidden"], outputs: ["postFilesStarted", "onPublicFilesUploaded", "onPrivateFilesUploaded"] }, { kind: "ngmodule", type: NgSelectModule }, { kind: "component", type: i6.NgSelectComponent, selector: "ng-select", inputs: ["ariaLabelDropdown", "bindLabel", "bindValue", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "tabFocusOnClearButton", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: i6.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] }); }
1715
1771
  }
1716
1772
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AudioEditorComponent, decorators: [{
1717
1773
  type: Component,
@@ -1726,8 +1782,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1726
1782
  UploadFilesBtnComponent,
1727
1783
  NgSelectModule,
1728
1784
  MatIconButton
1729
- ], template: "<div class=\"audio-editor\">\n @if (hasAudioError) {\n <div class=\"error-block\">\n <mat-icon>error</mat-icon>\n <span>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u043F\u043E \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0444\u0430\u0439\u043B \u043D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043B\u0438 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.</span>\n </div>\n }\n\n @if (hasFileId() && !hasAudioError) {\n <div class=\"audio-player-container\">\n <audio\n #audioPlayer\n [src]=\"getSrc()\"\n (error)=\"onErrorHandler()\"\n (loadedmetadata)=\"onLoadedMetadata()\"\n (timeupdate)=\"onTimeUpdate()\"\n (ended)=\"onEnded()\"\n (canplay)=\"onCanPlay()\"\n preload=\"metadata\">\n </audio>\n\n @if (isLoading) {\n <div class=\"loading-indicator\">\n <div class=\"progress-bar\">\n <div class=\"progress-bar-fill\"></div>\n </div>\n <span>\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0430\u0443\u0434\u0438\u043E...</span>\n </div>\n }\n\n <div class=\"player-controls\">\n <div class=\"control-buttons\">\n <button (click)=\"restart()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay</mat-icon>\n </button>\n\n <button (click)=\"rewind()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay_10</mat-icon>\n </button>\n\n <button\n (click)=\"togglePlayPause()\"\n [disabled]=\"!hasFileId() || isLoading\"\n class=\"play-pause-btn\" mat-icon-button>\n <mat-icon>{{ isPlaying ? 'pause' : 'play_arrow' }}</mat-icon>\n </button>\n\n <button (click)=\"forward()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>forward_10</mat-icon>\n </button>\n\n @if (!presentOrEdit) {\n <button (click)=\"removeAudio()\" [disabled]=\"!hasFileId()\" color=\"warn\" mat-icon-button>\n <mat-icon>delete</mat-icon>\n </button>\n }\n </div>\n\n <div class=\"progress-section\">\n <span class=\"time-display\">{{ formatTime(currentTime) }}</span>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"getProgress()\"\n (input)=\"onSeekChange($event)\"\n [disabled]=\"!hasFileId() || duration === 0\"\n class=\"progress-slider\">\n\n <span class=\"time-display\">{{ formatTime(duration) }}</span>\n </div>\n\n <div class=\"volume-controls\">\n <button (click)=\"toggleMute()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>{{ isMuted ? 'volume_off' : 'volume_up' }}</mat-icon>\n </button>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volume * 100\"\n (input)=\"onVolumeChange($event)\"\n [disabled]=\"!hasFileId()\"\n class=\"volume-slider\">\n </div>\n </div>\n </div>\n }\n\n @if (!hasFileId()) {\n <div class=\"no-file-message\">\n <mat-icon>music_off</mat-icon>\n <h5>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D</h5>\n @if (!presentOrEdit) {\n <p>\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u043A\u043D\u043E\u043F\u043A\u0443 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0434\u043B\u044F \u0432\u044B\u0431\u043E\u0440\u0430 \u0438\u043B\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</p>\n }\n </div>\n }\n @if (!presentOrEdit) {\n <div class=\"edit-panel\">\n <div class=\"edit-header\">\n <h6>\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</h6>\n </div>\n\n <div class=\"mode-toggle\">\n <mat-button-toggle-group [(ngModel)]=\"searchOrEdit\">\n <mat-button-toggle value=\"search\">\n <mat-icon>search</mat-icon>\n \u0418\u0441\u043A\u0430\u0442\u044C \u0444\u0430\u0439\u043B\n </mat-button-toggle>\n <mat-button-toggle value=\"edit\">\n <mat-icon>settings</mat-icon>\n \u0423\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E ID\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n @if (searchOrEdit === 'search') {\n <div class=\"file-selection\">\n <div class=\"existing-files\">\n <h6>\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0438\u0437 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0445 \u0444\u0430\u0439\u043B\u043E\u0432:</h6>\n <ng-select\n [(ngModel)]=\"fileId\"\n (ngModelChange)=\"onFileSelected($event)\"\n [items]=\"files\"\n bindLabel=\"fileName\"\n bindValue=\"fileId\"\n (search)=\"onSearchChanged($event)\"\n [loading]=\"loading\"\n [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\"\n [clearable]=\"true\">\n <ng-template ng-option-tmp let-item=\"item\">\n <div class=\"file-option\">\n <mat-icon>audiotrack</mat-icon>\n <span>{{ item.fileName }}</span>\n <small>ID: {{ item.fileId }}</small>\n </div>\n </ng-template>\n </ng-select>\n </div>\n\n <div class=\"upload-section\">\n <h6>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u0444\u0430\u0439\u043B:</h6>\n <croco-app-upload-files-btn\n extAccepts=\"audio/*\"\n [isMultiple]=\"false\"\n btnText=\"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\"\n (onPublicFilesUploaded)=\"onFilesUploaded($event.fileIds)\"\n (onPrivateFilesUploaded)=\"onFilesUploaded($event.fileIds)\">\n </croco-app-upload-files-btn>\n </div>\n </div>\n } @else if (searchOrEdit === 'edit') {\n <div class=\"manual-input\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 ID \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"fileId\"\n (ngModelChange)=\"onFileIdChanged($event)\">\n </mat-form-field>\n\n <mat-form-field class=\"w-100\">\n <mat-label>\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043C\u044F \u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"fileNameAttr\"\n (ngModelChange)=\"onFileNameChanged($event)\">\n </mat-form-field>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".audio-editor{width:100%;padding:16px;background:#fafafa;border-radius:8px;border:1px solid #e0e0e0}.error-block{display:flex;align-items:center;gap:8px;background-color:#ffebee;color:#c62828;padding:12px;border-radius:8px;border:1px solid #ffcdd2;margin-bottom:16px}.error-block mat-icon{color:#c62828}.audio-player-container{background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 8px #0000001a;margin-bottom:16px}.loading-indicator{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;color:#666}.loading-indicator .progress-bar{width:200px;height:4px;background-color:#e0e0e0;border-radius:2px;overflow:hidden}.loading-indicator .progress-bar .progress-bar-fill{height:100%;background-color:#1976d2;animation:loading 1.5s ease-in-out infinite}@keyframes loading{0%{transform:translate(-100%)}50%{transform:translate(0)}to{transform:translate(100%)}}.file-info{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px;background:#f5f5f5;border-radius:8px}.file-info mat-icon{color:#1976d2}.file-info .file-name{font-weight:500;flex:1}.file-info .edit-btn{margin-left:auto}.player-controls{display:flex;flex-direction:column;gap:16px}.control-buttons{display:flex;justify-content:center;align-items:center;gap:8px}.control-buttons .play-pause-btn{background-color:#1976d2;color:#fff;width:48px;height:48px}.control-buttons .play-pause-btn:hover{background-color:#1565c0}.control-buttons .play-pause-btn mat-icon{font-size:24px}.control-buttons mat-icon-button{width:40px;height:40px}.control-buttons mat-icon-button:disabled{color:#ccc}.progress-section{display:flex;align-items:center;gap:12px}.progress-section .time-display{font-family:Roboto Mono,monospace;font-size:14px;color:#666;min-width:40px;text-align:center}.progress-section .progress-slider{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.progress-section .progress-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider:hover::-webkit-slider-thumb{background:#1565c0}.progress-section .progress-slider:hover::-moz-range-thumb{background:#1565c0}.volume-controls{display:flex;align-items:center;gap:8px;justify-content:center}.volume-controls .volume-slider{width:100px;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.volume-controls .volume-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider:hover::-webkit-slider-thumb{background:#1565c0}.volume-controls .volume-slider:hover::-moz-range-thumb{background:#1565c0}.no-file-message{text-align:center;padding:40px 20px;color:#666}.no-file-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;color:#ccc}.no-file-message h5{margin:0 0 8px;color:#999}.no-file-message p{margin:0;font-size:14px;color:#999}.edit-panel{background:#fff;border-radius:8px;padding:20px;border:1px solid #e0e0e0;margin-top:16px}.edit-panel .edit-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.edit-panel .edit-header h6{margin:0;color:#333}.edit-panel .mode-toggle{margin-bottom:20px}.edit-panel .mode-toggle mat-button-toggle-group{width:100%}.edit-panel .mode-toggle mat-button-toggle{flex:1;display:flex;align-items:center;justify-content:center;gap:8px}.edit-panel .file-selection{display:flex;flex-direction:column;gap:20px}.edit-panel .file-selection h6{margin:0 0 12px;color:#333}.edit-panel .file-selection .file-option{display:flex;align-items:center;gap:8px}.edit-panel .file-selection .file-option mat-icon{color:#1976d2}.edit-panel .file-selection .file-option small{margin-left:auto;color:#666}.edit-panel .file-selection .upload-section{padding-top:16px;border-top:1px solid #e0e0e0}.edit-panel .manual-input{display:flex;flex-direction:column;gap:16px}.edit-button-container{display:flex;justify-content:center;margin-top:16px}.edit-button-container .edit-mode-btn{background-color:#1976d2;color:#fff}.edit-button-container .edit-mode-btn:hover{background-color:#1565c0}@media screen and (max-width: 768px){.audio-editor{padding:12px}.audio-player-container{padding:16px}.control-buttons{flex-wrap:wrap;gap:4px}.progress-section{flex-direction:column;gap:8px}.progress-section .progress-slider{width:100%}.volume-controls{justify-content:flex-start}.volume-controls .volume-slider{width:80px}.edit-panel{padding:16px}.edit-panel .mode-toggle mat-button-toggle-group{flex-direction:column}}::ng-deep .ng-select .ng-select-container{border-radius:4px;border:1px solid #ccc}::ng-deep .ng-select.ng-select-focused .ng-select-container{border-color:#1976d2}input[type=range].progress-slider:disabled,input[type=range].volume-slider:disabled{opacity:.5;cursor:not-allowed}\n"] }]
1730
- }], ctorParameters: () => [{ type: PublicFilesQueryService }, { type: PrivateFilesQueryService }, { type: CrocoHtmlFileOptionsService }], propDecorators: { audioPlayer: [{
1785
+ ], template: "<div class=\"audio-editor\">\n @if (hasAudioError) {\n <div class=\"error-block\">\n <mat-icon>error</mat-icon>\n <span>{{ errorMessage }}</span>\n </div>\n }\n\n @if (hasFileId() && !hasAudioError) {\n <div class=\"audio-player-container\">\n <audio\n #audioPlayer\n [src]=\"audioSrc\"\n (error)=\"onErrorHandler()\"\n (loadedmetadata)=\"onLoadedMetadata()\"\n (timeupdate)=\"onTimeUpdate()\"\n (ended)=\"onEnded()\"\n (canplay)=\"onCanPlay()\"\n preload=\"metadata\">\n </audio>\n\n @if (isLoading) {\n <div class=\"loading-indicator\">\n <div class=\"progress-bar\">\n <div class=\"progress-bar-fill\"></div>\n </div>\n <span>\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0430\u0443\u0434\u0438\u043E...</span>\n </div>\n }\n\n <div class=\"player-controls\">\n <div class=\"control-buttons\">\n <button (click)=\"restart()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay</mat-icon>\n </button>\n\n <button (click)=\"rewind()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay_10</mat-icon>\n </button>\n\n <button\n (click)=\"togglePlayPause()\"\n [disabled]=\"!hasFileId() || isLoading\"\n class=\"play-pause-btn\" mat-icon-button>\n <mat-icon>{{ isPlaying ? 'pause' : 'play_arrow' }}</mat-icon>\n </button>\n\n <button (click)=\"forward()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>forward_10</mat-icon>\n </button>\n\n @if (!presentOrEdit) {\n <button (click)=\"removeAudio()\" [disabled]=\"!hasFileId()\" color=\"warn\" mat-icon-button>\n <mat-icon>delete</mat-icon>\n </button>\n }\n </div>\n\n <div class=\"progress-section\">\n <span class=\"time-display\">{{ formatTime(currentTime) }}</span>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"getProgress()\"\n (input)=\"onSeekChange($event)\"\n [disabled]=\"!hasFileId() || duration === 0\"\n class=\"progress-slider\">\n\n <span class=\"time-display\">{{ formatTime(duration) }}</span>\n </div>\n\n <div class=\"volume-controls\">\n <button (click)=\"toggleMute()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>{{ isMuted ? 'volume_off' : 'volume_up' }}</mat-icon>\n </button>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volume * 100\"\n (input)=\"onVolumeChange($event)\"\n [disabled]=\"!hasFileId()\"\n class=\"volume-slider\">\n </div>\n </div>\n </div>\n }\n\n @if (!hasFileId()) {\n <div class=\"no-file-message\">\n <mat-icon>music_off</mat-icon>\n <h5>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D</h5>\n @if (!presentOrEdit) {\n <p>\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u043A\u043D\u043E\u043F\u043A\u0443 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0434\u043B\u044F \u0432\u044B\u0431\u043E\u0440\u0430 \u0438\u043B\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</p>\n }\n </div>\n }\n @if (!presentOrEdit) {\n <div class=\"edit-panel\">\n <div class=\"edit-header\">\n <h6>\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</h6>\n </div>\n\n <div class=\"mode-toggle\">\n <mat-button-toggle-group [(ngModel)]=\"searchOrEdit\">\n <mat-button-toggle value=\"search\">\n <mat-icon>search</mat-icon>\n \u0418\u0441\u043A\u0430\u0442\u044C \u0444\u0430\u0439\u043B\n </mat-button-toggle>\n <mat-button-toggle value=\"edit\">\n <mat-icon>settings</mat-icon>\n \u0423\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E ID\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n @if (searchOrEdit === 'search') {\n <div class=\"file-selection\">\n <div class=\"existing-files\">\n <h6>\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0438\u0437 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0445 \u0444\u0430\u0439\u043B\u043E\u0432:</h6>\n <ng-select\n [(ngModel)]=\"fileId\"\n (ngModelChange)=\"onFileSelected($event)\"\n [items]=\"files\"\n bindLabel=\"fileName\"\n bindValue=\"fileId\"\n (search)=\"onSearchChanged($event)\"\n [loading]=\"loading\"\n [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\"\n [clearable]=\"true\">\n <ng-template ng-option-tmp let-item=\"item\">\n <div class=\"file-option\">\n <mat-icon>audiotrack</mat-icon>\n <span>{{ item.fileName }}</span>\n <small>ID: {{ item.fileId }}</small>\n </div>\n </ng-template>\n </ng-select>\n </div>\n\n <div class=\"title-input\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"title\">\n </mat-form-field>\n </div>\n\n <div class=\"upload-section\">\n <h6>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u0444\u0430\u0439\u043B:</h6>\n <croco-app-upload-files-btn\n extAccepts=\"audio/*\"\n [isMultiple]=\"false\"\n btnText=\"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\"\n (onPublicFilesUploaded)=\"onFilesUploaded($event.fileIds)\"\n (onPrivateFilesUploaded)=\"onFilesUploaded($event.fileIds)\">\n </croco-app-upload-files-btn>\n </div>\n </div>\n } @else if (searchOrEdit === 'edit') {\n <div class=\"manual-input\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 ID \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"fileId\"\n (ngModelChange)=\"onFileIdChanged($event)\">\n </mat-form-field>\n\n <mat-form-field class=\"w-100\">\n <mat-label>\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0430\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B\u0430\"\n autocomplete=\"off\"\n [(ngModel)]=\"title\">\n </mat-form-field>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".audio-editor{width:100%;padding:16px;background:#fafafa;border-radius:8px;border:1px solid #e0e0e0}.error-block{display:flex;align-items:center;gap:8px;background-color:#ffebee;color:#c62828;padding:12px;border-radius:8px;border:1px solid #ffcdd2;margin-bottom:16px}.error-block mat-icon{color:#c62828}.audio-player-container{background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 8px #0000001a;margin-bottom:16px}.loading-indicator{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;color:#666}.loading-indicator .progress-bar{width:200px;height:4px;background-color:#e0e0e0;border-radius:2px;overflow:hidden}.loading-indicator .progress-bar .progress-bar-fill{height:100%;background-color:#1976d2;animation:loading 1.5s ease-in-out infinite}@keyframes loading{0%{transform:translate(-100%)}50%{transform:translate(0)}to{transform:translate(100%)}}.file-info{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px;background:#f5f5f5;border-radius:8px}.file-info mat-icon{color:#1976d2}.file-info .file-name{font-weight:500;flex:1}.file-info .edit-btn{margin-left:auto}.player-controls{display:flex;flex-direction:column;gap:16px}.control-buttons{display:flex;justify-content:center;align-items:center;gap:8px}.control-buttons .play-pause-btn{background-color:#1976d2;color:#fff;width:48px;height:48px}.control-buttons .play-pause-btn:hover{background-color:#1565c0}.control-buttons .play-pause-btn mat-icon{font-size:24px}.control-buttons mat-icon-button{width:40px;height:40px}.control-buttons mat-icon-button:disabled{color:#ccc}.progress-section{display:flex;align-items:center;gap:12px}.progress-section .time-display{font-family:Roboto Mono,monospace;font-size:14px;color:#666;min-width:40px;text-align:center}.progress-section .progress-slider{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.progress-section .progress-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider:hover::-webkit-slider-thumb{background:#1565c0}.progress-section .progress-slider:hover::-moz-range-thumb{background:#1565c0}.volume-controls{display:flex;align-items:center;gap:8px;justify-content:center}.volume-controls .volume-slider{width:100px;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.volume-controls .volume-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider:hover::-webkit-slider-thumb{background:#1565c0}.volume-controls .volume-slider:hover::-moz-range-thumb{background:#1565c0}.no-file-message{text-align:center;padding:40px 20px;color:#666}.no-file-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;color:#ccc}.no-file-message h5{margin:0 0 8px;color:#999}.no-file-message p{margin:0;font-size:14px;color:#999}.edit-panel{background:#fff;border-radius:8px;padding:20px;border:1px solid #e0e0e0;margin-top:16px}.edit-panel .edit-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.edit-panel .edit-header h6{margin:0;color:#333}.edit-panel .mode-toggle{margin-bottom:20px}.edit-panel .mode-toggle mat-button-toggle-group{width:100%}.edit-panel .mode-toggle mat-button-toggle{flex:1;display:flex;align-items:center;justify-content:center;gap:8px}.edit-panel .file-selection{display:flex;flex-direction:column;gap:20px}.edit-panel .file-selection h6{margin:0 0 12px;color:#333}.edit-panel .file-selection .file-option{display:flex;align-items:center;gap:8px}.edit-panel .file-selection .file-option mat-icon{color:#1976d2}.edit-panel .file-selection .file-option small{margin-left:auto;color:#666}.edit-panel .file-selection .upload-section{padding-top:16px;border-top:1px solid #e0e0e0}.edit-panel .manual-input{display:flex;flex-direction:column;gap:16px}.edit-button-container{display:flex;justify-content:center;margin-top:16px}.edit-button-container .edit-mode-btn{background-color:#1976d2;color:#fff}.edit-button-container .edit-mode-btn:hover{background-color:#1565c0}@media screen and (max-width: 768px){.audio-editor{padding:12px}.audio-player-container{padding:16px}.control-buttons{flex-wrap:wrap;gap:4px}.progress-section{flex-direction:column;gap:8px}.progress-section .progress-slider{width:100%}.volume-controls{justify-content:flex-start}.volume-controls .volume-slider{width:80px}.edit-panel{padding:16px}.edit-panel .mode-toggle mat-button-toggle-group{flex-direction:column}}::ng-deep .ng-select .ng-select-container{border-radius:4px;border:1px solid #ccc}::ng-deep .ng-select.ng-select-focused .ng-select-container{border-color:#1976d2}input[type=range].progress-slider:disabled,input[type=range].volume-slider:disabled{opacity:.5;cursor:not-allowed}\n"] }]
1786
+ }], ctorParameters: () => [{ type: PublicFilesQueryService }, { type: PrivateFilesQueryService }, { type: CrocoHtmlFileOptionsService }, { type: CommonFileInfoQueryService }], propDecorators: { audioPlayer: [{
1731
1787
  type: ViewChild,
1732
1788
  args: ['audioPlayer', { static: false }]
1733
1789
  }], tag: [{
@@ -1741,28 +1797,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1741
1797
  const CrocoHtmlOptionsToken = "croco-html-options";
1742
1798
 
1743
1799
  class AudioPlayerTagViewComponent {
1744
- constructor(_options) {
1800
+ constructor(_options, _commonFileInfoService) {
1745
1801
  this._options = _options;
1802
+ this._commonFileInfoService = _commonFileInfoService;
1746
1803
  this.hasAudioError = false;
1804
+ this.errorMessage = '';
1747
1805
  this.isPlaying = false;
1748
1806
  this.isLoading = false;
1749
1807
  this.currentTime = 0;
1750
1808
  this.duration = 0;
1751
1809
  this.volume = 1;
1752
1810
  this.isMuted = false;
1811
+ this.audioSrc = '';
1753
1812
  this.unsubscribe = new Subject();
1754
1813
  }
1755
1814
  get fileId() {
1756
1815
  return this.data.data.fileId;
1757
1816
  }
1758
- get fileName() {
1759
- return this.data.data.fileName;
1760
- }
1761
- getSrc() {
1762
- //this._options.fileIdAndNamePathUrlFormat;
1763
- // TODO если fileId указан то нужно
1764
- // return AudioMethods.buildUrl(this.fileId, this.fileName);
1765
- return this.fileId;
1817
+ get title() {
1818
+ return this.data.data.title || 'Аудио-файл';
1766
1819
  }
1767
1820
  get audioElement() {
1768
1821
  return this.audioPlayer?.nativeElement || null;
@@ -1773,6 +1826,14 @@ class AudioPlayerTagViewComponent {
1773
1826
  onErrorHandler() {
1774
1827
  this.hasAudioError = true;
1775
1828
  this.isLoading = false;
1829
+ if (!this.errorMessage) {
1830
+ this.errorMessage = 'Аудио-файл не найден по указанному идентификатору.';
1831
+ }
1832
+ }
1833
+ setError(message) {
1834
+ this.hasAudioError = true;
1835
+ this.errorMessage = message;
1836
+ this.isLoading = false;
1776
1837
  }
1777
1838
  onLoadedMetadata() {
1778
1839
  const audio = this.audioElement;
@@ -1872,30 +1933,75 @@ class AudioPlayerTagViewComponent {
1872
1933
  const audio = this.audioElement;
1873
1934
  if (audio) {
1874
1935
  audio.volume = this.volume;
1875
- if (this.hasFileId()) {
1876
- this.isLoading = true;
1877
- audio.load();
1936
+ }
1937
+ }
1938
+ if (this.hasFileId()) {
1939
+ this.checkAndLoadAudioFile();
1940
+ }
1941
+ }
1942
+ checkAndLoadAudioFile() {
1943
+ if (!this.hasFileId()) {
1944
+ return;
1945
+ }
1946
+ this.isLoading = true;
1947
+ this.hasAudioError = false;
1948
+ this.errorMessage = '';
1949
+ const fileIdValue = this.fileId;
1950
+ this._commonFileInfoService.getInfo(fileIdValue)
1951
+ .pipe(takeUntil(this.unsubscribe))
1952
+ .subscribe({
1953
+ next: (result) => {
1954
+ if (!result.fileInfo) {
1955
+ this.setError(`Файл с идентификатором ${fileIdValue} не найден на сервере.`);
1956
+ return;
1957
+ }
1958
+ if (result.fileInfo.type !== FileType.Audio) {
1959
+ this.setError(`Файл с идентификатором ${fileIdValue} должен быть c типом Audio, а получено ${result.fileInfo.type}.`);
1960
+ return;
1878
1961
  }
1962
+ this.audioSrc = result.fileInfo.downloadUrl;
1963
+ this.loadAudioFile();
1964
+ },
1965
+ error: (error) => {
1966
+ this.setError(`Ошибка при получении информации о файле: ${error.message || 'Неизвестная ошибка'}`);
1879
1967
  }
1968
+ });
1969
+ }
1970
+ loadAudioFile() {
1971
+ if (!this.hasFileId() || !this.audioSrc) {
1972
+ return;
1973
+ }
1974
+ this.isLoading = true;
1975
+ this.hasAudioError = false;
1976
+ const audio = this.audioElement;
1977
+ if (audio) {
1978
+ audio.load();
1880
1979
  }
1881
1980
  }
1882
1981
  ngOnDestroy() {
1883
1982
  this.unsubscribe.next();
1884
1983
  this.unsubscribe.complete();
1885
1984
  }
1886
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AudioPlayerTagViewComponent, deps: [{ token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
1887
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AudioPlayerTagViewComponent, isStandalone: true, selector: "croco-html-audio-player-tag-view", inputs: { data: "data" }, viewQueries: [{ propertyName: "audioPlayer", first: true, predicate: ["audioPlayer"], descendants: true }], ngImport: i0, template: "<div class=\"audio-view\">\n @if (hasAudioError) {\n <div class=\"error-block\">\n <mat-icon>error</mat-icon>\n <span>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u043F\u043E \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443</span>\n </div>\n }\n\n @if (hasFileId() && !hasAudioError) {\n <div class=\"audio-player-container\">\n <audio\n #audioPlayer\n [src]=\"getSrc()\"\n (error)=\"onErrorHandler()\"\n (loadedmetadata)=\"onLoadedMetadata()\"\n (timeupdate)=\"onTimeUpdate()\"\n (ended)=\"onEnded()\"\n (canplay)=\"onCanPlay()\"\n preload=\"metadata\">\n </audio>\n\n @if (isLoading) {\n <div class=\"loading-indicator\">\n <div class=\"progress-bar\">\n <div class=\"progress-bar-fill\"></div>\n </div>\n <span>\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0430\u0443\u0434\u0438\u043E...</span>\n </div>\n }\n\n <div class=\"file-info\">\n <mat-icon>audiotrack</mat-icon>\n <span class=\"file-name\">{{ fileName || '\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B' }}</span>\n </div>\n\n <div class=\"player-controls\">\n <div class=\"control-buttons\">\n <button (click)=\"restart()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay</mat-icon>\n </button>\n\n <button (click)=\"rewind()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay_10</mat-icon>\n </button>\n\n <button\n (click)=\"togglePlayPause()\"\n [disabled]=\"!hasFileId() || isLoading\"\n class=\"play-pause-btn\" mat-icon-button>\n <mat-icon>{{ isPlaying ? 'pause' : 'play_arrow' }}</mat-icon>\n </button>\n\n <button (click)=\"forward()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>forward_10</mat-icon>\n </button>\n </div>\n\n <div class=\"progress-section\">\n <span class=\"time-display\">{{ formatTime(currentTime) }}</span>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"getProgress()\"\n (input)=\"onSeekChange($event)\"\n [disabled]=\"!hasFileId() || duration === 0\"\n class=\"progress-slider\">\n\n <span class=\"time-display\">{{ formatTime(duration) }}</span>\n </div>\n\n <div class=\"volume-controls\">\n <button (click)=\"toggleMute()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>{{ isMuted ? 'volume_off' : 'volume_up' }}</mat-icon>\n </button>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volume * 100\"\n (input)=\"onVolumeChange($event)\"\n [disabled]=\"!hasFileId()\"\n class=\"volume-slider\">\n </div>\n </div>\n </div>\n }\n\n <!-- \u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043E\u0431 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0444\u0430\u0439\u043B\u0430 -->\n @if (!hasFileId()) {\n <div class=\"no-file-message\">\n <mat-icon>music_off</mat-icon>\n <h5>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D</h5>\n </div>\n }\n</div>\n", styles: [".audio-view{width:100%;max-width:500px;margin:0 auto}.error-block{display:flex;align-items:center;gap:8px;background-color:#ffebee;color:#c62828;padding:12px;border-radius:8px;border:1px solid #ffcdd2;margin-bottom:16px}.error-block mat-icon{color:#c62828}.audio-player-container{background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 8px #0000001a;margin-bottom:16px}.loading-indicator{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;color:#666}.loading-indicator .progress-bar{width:200px;height:4px;background-color:#e0e0e0;border-radius:2px;overflow:hidden}.loading-indicator .progress-bar .progress-bar-fill{height:100%;background-color:#1976d2;animation:loading 1.5s ease-in-out infinite}@keyframes loading{0%{transform:translate(-100%)}50%{transform:translate(0)}to{transform:translate(100%)}}.file-info{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px;background:#f5f5f5;border-radius:8px}.file-info mat-icon{color:#1976d2}.file-info .file-name{font-weight:500;flex:1}.player-controls{display:flex;flex-direction:column;gap:16px}.control-buttons{display:flex;justify-content:center;align-items:center;gap:8px}.control-buttons .play-pause-btn{background-color:#1976d2;color:#fff;width:48px;height:48px}.control-buttons .play-pause-btn:hover{background-color:#1565c0}.control-buttons .play-pause-btn mat-icon{font-size:24px}.control-buttons mat-icon-button{width:40px;height:40px}.control-buttons mat-icon-button:disabled{color:#ccc}.progress-section{display:flex;align-items:center;gap:12px}.progress-section .time-display{font-family:Roboto Mono,monospace;font-size:14px;color:#666;min-width:40px;text-align:center}.progress-section .progress-slider{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.progress-section .progress-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider:hover::-webkit-slider-thumb{background:#1565c0}.progress-section .progress-slider:hover::-moz-range-thumb{background:#1565c0}.volume-controls{display:flex;align-items:center;gap:8px;justify-content:center}.volume-controls .volume-slider{width:100px;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.volume-controls .volume-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider:hover::-webkit-slider-thumb{background:#1565c0}.volume-controls .volume-slider:hover::-moz-range-thumb{background:#1565c0}.no-file-message{text-align:center;padding:40px 20px;color:#666}.no-file-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;color:#ccc}.no-file-message h5{margin:0;color:#999}@media screen and (max-width: 768px){.audio-view{padding:0 12px}.audio-player-container{padding:16px}.control-buttons{flex-wrap:wrap;gap:4px}.progress-section{flex-direction:column;gap:8px}.progress-section .progress-slider{width:100%}.volume-controls{justify-content:flex-start}.volume-controls .volume-slider{width:80px}}input[type=range].progress-slider:disabled,input[type=range].volume-slider:disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] }); }
1985
+ ngOnChanges(changes) {
1986
+ if (changes['data'] && !changes['data'].firstChange) {
1987
+ if (this.hasFileId()) {
1988
+ this.checkAndLoadAudioFile();
1989
+ }
1990
+ }
1991
+ }
1992
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AudioPlayerTagViewComponent, deps: [{ token: CrocoHtmlOptionsToken }, { token: CommonFileInfoQueryService }], target: i0.ɵɵFactoryTarget.Component }); }
1993
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AudioPlayerTagViewComponent, isStandalone: true, selector: "croco-html-audio-player-tag-view", inputs: { data: "data" }, viewQueries: [{ propertyName: "audioPlayer", first: true, predicate: ["audioPlayer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"audio-view\">\n @if (hasAudioError) {\n <div class=\"error-block\">\n <mat-icon>error</mat-icon>\n <span>{{ errorMessage }}</span>\n </div>\n }\n\n @if (hasFileId() && !hasAudioError) {\n <div class=\"audio-player-container\">\n <audio\n #audioPlayer\n [src]=\"audioSrc\"\n (error)=\"onErrorHandler()\"\n (loadedmetadata)=\"onLoadedMetadata()\"\n (timeupdate)=\"onTimeUpdate()\"\n (ended)=\"onEnded()\"\n (canplay)=\"onCanPlay()\"\n preload=\"metadata\">\n </audio>\n\n @if (isLoading) {\n <div class=\"loading-indicator\">\n <div class=\"progress-bar\">\n <div class=\"progress-bar-fill\"></div>\n </div>\n <span>\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0430\u0443\u0434\u0438\u043E...</span>\n </div>\n }\n\n <div class=\"file-info\">\n <mat-icon>audiotrack</mat-icon>\n <span class=\"file-name\">{{ title }}</span>\n </div>\n\n <div class=\"player-controls\">\n <div class=\"control-buttons\">\n <button (click)=\"restart()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay</mat-icon>\n </button>\n\n <button (click)=\"rewind()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay_10</mat-icon>\n </button>\n\n <button\n (click)=\"togglePlayPause()\"\n [disabled]=\"!hasFileId() || isLoading\"\n class=\"play-pause-btn\" mat-icon-button>\n <mat-icon>{{ isPlaying ? 'pause' : 'play_arrow' }}</mat-icon>\n </button>\n\n <button (click)=\"forward()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>forward_10</mat-icon>\n </button>\n </div>\n\n <div class=\"progress-section\">\n <span class=\"time-display\">{{ formatTime(currentTime) }}</span>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"getProgress()\"\n (input)=\"onSeekChange($event)\"\n [disabled]=\"!hasFileId() || duration === 0\"\n class=\"progress-slider\">\n\n <span class=\"time-display\">{{ formatTime(duration) }}</span>\n </div>\n\n <div class=\"volume-controls\">\n <button (click)=\"toggleMute()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>{{ isMuted ? 'volume_off' : 'volume_up' }}</mat-icon>\n </button>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volume * 100\"\n (input)=\"onVolumeChange($event)\"\n [disabled]=\"!hasFileId()\"\n class=\"volume-slider\">\n </div>\n </div>\n </div>\n }\n\n <!-- \u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043E\u0431 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0444\u0430\u0439\u043B\u0430 -->\n @if (!hasFileId()) {\n <div class=\"no-file-message\">\n <mat-icon>music_off</mat-icon>\n <h5>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D</h5>\n </div>\n }\n</div>\n", styles: [".audio-view{width:100%;max-width:500px;margin:0 auto}.error-block{display:flex;align-items:center;gap:8px;background-color:#ffebee;color:#c62828;padding:12px;border-radius:8px;border:1px solid #ffcdd2;margin-bottom:16px}.error-block mat-icon{color:#c62828}.audio-player-container{background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 8px #0000001a;margin-bottom:16px}.loading-indicator{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;color:#666}.loading-indicator .progress-bar{width:200px;height:4px;background-color:#e0e0e0;border-radius:2px;overflow:hidden}.loading-indicator .progress-bar .progress-bar-fill{height:100%;background-color:#1976d2;animation:loading 1.5s ease-in-out infinite}@keyframes loading{0%{transform:translate(-100%)}50%{transform:translate(0)}to{transform:translate(100%)}}.file-info{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px;background:#f5f5f5;border-radius:8px}.file-info mat-icon{color:#1976d2}.file-info .file-name{font-weight:500;flex:1}.player-controls{display:flex;flex-direction:column;gap:16px}.control-buttons{display:flex;justify-content:center;align-items:center;gap:8px}.control-buttons .play-pause-btn{background-color:#1976d2;color:#fff;width:48px;height:48px}.control-buttons .play-pause-btn:hover{background-color:#1565c0}.control-buttons .play-pause-btn mat-icon{font-size:24px}.control-buttons mat-icon-button{width:40px;height:40px}.control-buttons mat-icon-button:disabled{color:#ccc}.progress-section{display:flex;align-items:center;gap:12px}.progress-section .time-display{font-family:Roboto Mono,monospace;font-size:14px;color:#666;min-width:40px;text-align:center}.progress-section .progress-slider{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.progress-section .progress-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider:hover::-webkit-slider-thumb{background:#1565c0}.progress-section .progress-slider:hover::-moz-range-thumb{background:#1565c0}.volume-controls{display:flex;align-items:center;gap:8px;justify-content:center}.volume-controls .volume-slider{width:100px;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.volume-controls .volume-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider:hover::-webkit-slider-thumb{background:#1565c0}.volume-controls .volume-slider:hover::-moz-range-thumb{background:#1565c0}.no-file-message{text-align:center;padding:40px 20px;color:#666}.no-file-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;color:#ccc}.no-file-message h5{margin:0;color:#999}@media screen and (max-width: 768px){.audio-view{padding:0 12px}.audio-player-container{padding:16px}.control-buttons{flex-wrap:wrap;gap:4px}.progress-section{flex-direction:column;gap:8px}.progress-section .progress-slider{width:100%}.volume-controls{justify-content:flex-start}.volume-controls .volume-slider{width:80px}}input[type=range].progress-slider:disabled,input[type=range].volume-slider:disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] }); }
1888
1994
  }
1889
1995
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AudioPlayerTagViewComponent, decorators: [{
1890
1996
  type: Component,
1891
1997
  args: [{ selector: 'croco-html-audio-player-tag-view', standalone: true, imports: [
1892
1998
  MatIcon,
1893
1999
  MatIconButton
1894
- ], template: "<div class=\"audio-view\">\n @if (hasAudioError) {\n <div class=\"error-block\">\n <mat-icon>error</mat-icon>\n <span>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u043F\u043E \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443</span>\n </div>\n }\n\n @if (hasFileId() && !hasAudioError) {\n <div class=\"audio-player-container\">\n <audio\n #audioPlayer\n [src]=\"getSrc()\"\n (error)=\"onErrorHandler()\"\n (loadedmetadata)=\"onLoadedMetadata()\"\n (timeupdate)=\"onTimeUpdate()\"\n (ended)=\"onEnded()\"\n (canplay)=\"onCanPlay()\"\n preload=\"metadata\">\n </audio>\n\n @if (isLoading) {\n <div class=\"loading-indicator\">\n <div class=\"progress-bar\">\n <div class=\"progress-bar-fill\"></div>\n </div>\n <span>\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0430\u0443\u0434\u0438\u043E...</span>\n </div>\n }\n\n <div class=\"file-info\">\n <mat-icon>audiotrack</mat-icon>\n <span class=\"file-name\">{{ fileName || '\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B' }}</span>\n </div>\n\n <div class=\"player-controls\">\n <div class=\"control-buttons\">\n <button (click)=\"restart()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay</mat-icon>\n </button>\n\n <button (click)=\"rewind()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay_10</mat-icon>\n </button>\n\n <button\n (click)=\"togglePlayPause()\"\n [disabled]=\"!hasFileId() || isLoading\"\n class=\"play-pause-btn\" mat-icon-button>\n <mat-icon>{{ isPlaying ? 'pause' : 'play_arrow' }}</mat-icon>\n </button>\n\n <button (click)=\"forward()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>forward_10</mat-icon>\n </button>\n </div>\n\n <div class=\"progress-section\">\n <span class=\"time-display\">{{ formatTime(currentTime) }}</span>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"getProgress()\"\n (input)=\"onSeekChange($event)\"\n [disabled]=\"!hasFileId() || duration === 0\"\n class=\"progress-slider\">\n\n <span class=\"time-display\">{{ formatTime(duration) }}</span>\n </div>\n\n <div class=\"volume-controls\">\n <button (click)=\"toggleMute()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>{{ isMuted ? 'volume_off' : 'volume_up' }}</mat-icon>\n </button>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volume * 100\"\n (input)=\"onVolumeChange($event)\"\n [disabled]=\"!hasFileId()\"\n class=\"volume-slider\">\n </div>\n </div>\n </div>\n }\n\n <!-- \u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043E\u0431 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0444\u0430\u0439\u043B\u0430 -->\n @if (!hasFileId()) {\n <div class=\"no-file-message\">\n <mat-icon>music_off</mat-icon>\n <h5>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D</h5>\n </div>\n }\n</div>\n", styles: [".audio-view{width:100%;max-width:500px;margin:0 auto}.error-block{display:flex;align-items:center;gap:8px;background-color:#ffebee;color:#c62828;padding:12px;border-radius:8px;border:1px solid #ffcdd2;margin-bottom:16px}.error-block mat-icon{color:#c62828}.audio-player-container{background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 8px #0000001a;margin-bottom:16px}.loading-indicator{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;color:#666}.loading-indicator .progress-bar{width:200px;height:4px;background-color:#e0e0e0;border-radius:2px;overflow:hidden}.loading-indicator .progress-bar .progress-bar-fill{height:100%;background-color:#1976d2;animation:loading 1.5s ease-in-out infinite}@keyframes loading{0%{transform:translate(-100%)}50%{transform:translate(0)}to{transform:translate(100%)}}.file-info{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px;background:#f5f5f5;border-radius:8px}.file-info mat-icon{color:#1976d2}.file-info .file-name{font-weight:500;flex:1}.player-controls{display:flex;flex-direction:column;gap:16px}.control-buttons{display:flex;justify-content:center;align-items:center;gap:8px}.control-buttons .play-pause-btn{background-color:#1976d2;color:#fff;width:48px;height:48px}.control-buttons .play-pause-btn:hover{background-color:#1565c0}.control-buttons .play-pause-btn mat-icon{font-size:24px}.control-buttons mat-icon-button{width:40px;height:40px}.control-buttons mat-icon-button:disabled{color:#ccc}.progress-section{display:flex;align-items:center;gap:12px}.progress-section .time-display{font-family:Roboto Mono,monospace;font-size:14px;color:#666;min-width:40px;text-align:center}.progress-section .progress-slider{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.progress-section .progress-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider:hover::-webkit-slider-thumb{background:#1565c0}.progress-section .progress-slider:hover::-moz-range-thumb{background:#1565c0}.volume-controls{display:flex;align-items:center;gap:8px;justify-content:center}.volume-controls .volume-slider{width:100px;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.volume-controls .volume-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider:hover::-webkit-slider-thumb{background:#1565c0}.volume-controls .volume-slider:hover::-moz-range-thumb{background:#1565c0}.no-file-message{text-align:center;padding:40px 20px;color:#666}.no-file-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;color:#ccc}.no-file-message h5{margin:0;color:#999}@media screen and (max-width: 768px){.audio-view{padding:0 12px}.audio-player-container{padding:16px}.control-buttons{flex-wrap:wrap;gap:4px}.progress-section{flex-direction:column;gap:8px}.progress-section .progress-slider{width:100%}.volume-controls{justify-content:flex-start}.volume-controls .volume-slider{width:80px}}input[type=range].progress-slider:disabled,input[type=range].volume-slider:disabled{opacity:.5;cursor:not-allowed}\n"] }]
2000
+ ], template: "<div class=\"audio-view\">\n @if (hasAudioError) {\n <div class=\"error-block\">\n <mat-icon>error</mat-icon>\n <span>{{ errorMessage }}</span>\n </div>\n }\n\n @if (hasFileId() && !hasAudioError) {\n <div class=\"audio-player-container\">\n <audio\n #audioPlayer\n [src]=\"audioSrc\"\n (error)=\"onErrorHandler()\"\n (loadedmetadata)=\"onLoadedMetadata()\"\n (timeupdate)=\"onTimeUpdate()\"\n (ended)=\"onEnded()\"\n (canplay)=\"onCanPlay()\"\n preload=\"metadata\">\n </audio>\n\n @if (isLoading) {\n <div class=\"loading-indicator\">\n <div class=\"progress-bar\">\n <div class=\"progress-bar-fill\"></div>\n </div>\n <span>\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0430\u0443\u0434\u0438\u043E...</span>\n </div>\n }\n\n <div class=\"file-info\">\n <mat-icon>audiotrack</mat-icon>\n <span class=\"file-name\">{{ title }}</span>\n </div>\n\n <div class=\"player-controls\">\n <div class=\"control-buttons\">\n <button (click)=\"restart()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay</mat-icon>\n </button>\n\n <button (click)=\"rewind()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>replay_10</mat-icon>\n </button>\n\n <button\n (click)=\"togglePlayPause()\"\n [disabled]=\"!hasFileId() || isLoading\"\n class=\"play-pause-btn\" mat-icon-button>\n <mat-icon>{{ isPlaying ? 'pause' : 'play_arrow' }}</mat-icon>\n </button>\n\n <button (click)=\"forward()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>forward_10</mat-icon>\n </button>\n </div>\n\n <div class=\"progress-section\">\n <span class=\"time-display\">{{ formatTime(currentTime) }}</span>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"getProgress()\"\n (input)=\"onSeekChange($event)\"\n [disabled]=\"!hasFileId() || duration === 0\"\n class=\"progress-slider\">\n\n <span class=\"time-display\">{{ formatTime(duration) }}</span>\n </div>\n\n <div class=\"volume-controls\">\n <button (click)=\"toggleMute()\" [disabled]=\"!hasFileId()\" mat-icon-button>\n <mat-icon>{{ isMuted ? 'volume_off' : 'volume_up' }}</mat-icon>\n </button>\n\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n [value]=\"volume * 100\"\n (input)=\"onVolumeChange($event)\"\n [disabled]=\"!hasFileId()\"\n class=\"volume-slider\">\n </div>\n </div>\n </div>\n }\n\n <!-- \u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043E\u0431 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0444\u0430\u0439\u043B\u0430 -->\n @if (!hasFileId()) {\n <div class=\"no-file-message\">\n <mat-icon>music_off</mat-icon>\n <h5>\u0410\u0443\u0434\u0438\u043E-\u0444\u0430\u0439\u043B \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D</h5>\n </div>\n }\n</div>\n", styles: [".audio-view{width:100%;max-width:500px;margin:0 auto}.error-block{display:flex;align-items:center;gap:8px;background-color:#ffebee;color:#c62828;padding:12px;border-radius:8px;border:1px solid #ffcdd2;margin-bottom:16px}.error-block mat-icon{color:#c62828}.audio-player-container{background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 8px #0000001a;margin-bottom:16px}.loading-indicator{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;color:#666}.loading-indicator .progress-bar{width:200px;height:4px;background-color:#e0e0e0;border-radius:2px;overflow:hidden}.loading-indicator .progress-bar .progress-bar-fill{height:100%;background-color:#1976d2;animation:loading 1.5s ease-in-out infinite}@keyframes loading{0%{transform:translate(-100%)}50%{transform:translate(0)}to{transform:translate(100%)}}.file-info{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px;background:#f5f5f5;border-radius:8px}.file-info mat-icon{color:#1976d2}.file-info .file-name{font-weight:500;flex:1}.player-controls{display:flex;flex-direction:column;gap:16px}.control-buttons{display:flex;justify-content:center;align-items:center;gap:8px}.control-buttons .play-pause-btn{background-color:#1976d2;color:#fff;width:48px;height:48px}.control-buttons .play-pause-btn:hover{background-color:#1565c0}.control-buttons .play-pause-btn mat-icon{font-size:24px}.control-buttons mat-icon-button{width:40px;height:40px}.control-buttons mat-icon-button:disabled{color:#ccc}.progress-section{display:flex;align-items:center;gap:12px}.progress-section .time-display{font-family:Roboto Mono,monospace;font-size:14px;color:#666;min-width:40px;text-align:center}.progress-section .progress-slider{flex:1;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.progress-section .progress-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.progress-section .progress-slider:hover::-webkit-slider-thumb{background:#1565c0}.progress-section .progress-slider:hover::-moz-range-thumb{background:#1565c0}.volume-controls{display:flex;align-items:center;gap:8px;justify-content:center}.volume-controls .volume-slider{width:100px;height:6px;-webkit-appearance:none;appearance:none;background:#e0e0e0;outline:none;border-radius:3px}.volume-controls .volume-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider::-moz-range-thumb{width:20px;height:20px;background:#1976d2;border-radius:50%;cursor:pointer;border:2px solid white;box-shadow:0 2px 4px #0003}.volume-controls .volume-slider:hover::-webkit-slider-thumb{background:#1565c0}.volume-controls .volume-slider:hover::-moz-range-thumb{background:#1565c0}.no-file-message{text-align:center;padding:40px 20px;color:#666}.no-file-message mat-icon{font-size:48px;width:48px;height:48px;margin-bottom:16px;color:#ccc}.no-file-message h5{margin:0;color:#999}@media screen and (max-width: 768px){.audio-view{padding:0 12px}.audio-player-container{padding:16px}.control-buttons{flex-wrap:wrap;gap:4px}.progress-section{flex-direction:column;gap:8px}.progress-section .progress-slider{width:100%}.volume-controls{justify-content:flex-start}.volume-controls .volume-slider{width:80px}}input[type=range].progress-slider:disabled,input[type=range].volume-slider:disabled{opacity:.5;cursor:not-allowed}\n"] }]
1895
2001
  }], ctorParameters: () => [{ type: undefined, decorators: [{
1896
2002
  type: Inject,
1897
2003
  args: [CrocoHtmlOptionsToken]
1898
- }] }], propDecorators: { audioPlayer: [{
2004
+ }] }, { type: CommonFileInfoQueryService }], propDecorators: { audioPlayer: [{
1899
2005
  type: ViewChild,
1900
2006
  args: ['audioPlayer', { static: false }]
1901
2007
  }], data: [{
@@ -2027,11 +2133,11 @@ class XmlTagHtmlViewComponent {
2027
2133
  this.html = "";
2028
2134
  }
2029
2135
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: XmlTagHtmlViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2030
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: XmlTagHtmlViewComponent, isStandalone: true, selector: "croco-html-xml-tag-html-view", inputs: { html: "html" }, ngImport: i0, template: "<div class=\"col\" [innerHTML]=\"html\">\n</div>" }); }
2136
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: XmlTagHtmlViewComponent, isStandalone: true, selector: "croco-html-xml-tag-html-view", inputs: { html: "html" }, ngImport: i0, template: "<div class=\"col\" [innerHTML]=\"html\">\n</div>", styles: [".col{width:100%;overflow-x:auto}\n"] }); }
2031
2137
  }
2032
2138
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: XmlTagHtmlViewComponent, decorators: [{
2033
2139
  type: Component,
2034
- args: [{ selector: 'croco-html-xml-tag-html-view', standalone: true, template: "<div class=\"col\" [innerHTML]=\"html\">\n</div>" }]
2140
+ args: [{ selector: 'croco-html-xml-tag-html-view', standalone: true, template: "<div class=\"col\" [innerHTML]=\"html\">\n</div>", styles: [".col{width:100%;overflow-x:auto}\n"] }]
2035
2141
  }], ctorParameters: () => [], propDecorators: { html: [{
2036
2142
  type: Input
2037
2143
  }] } });
@@ -2151,6 +2257,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
2151
2257
  class FileImageTagViewComponent {
2152
2258
  set item(item) {
2153
2259
  let data = item.data;
2260
+ this.imageData = data;
2154
2261
  this.imageSrc = data.src;
2155
2262
  this.requests = this.getMediaRequests(data.screenMediaRequest);
2156
2263
  }
@@ -2158,6 +2265,7 @@ class FileImageTagViewComponent {
2158
2265
  this.screenWidthService = screenWidthService;
2159
2266
  this._options = _options;
2160
2267
  this.imageSrc = "";
2268
+ this.imageData = null;
2161
2269
  this.requests = [];
2162
2270
  this.unsubscribe = new Subject();
2163
2271
  this.imageMaxHeight = null;
@@ -2183,14 +2291,19 @@ class FileImageTagViewComponent {
2183
2291
  this.unsubscribe.next();
2184
2292
  this.unsubscribe.complete();
2185
2293
  }
2294
+ onImageClick() {
2295
+ if (this.imageData && this._options.imageOptions.onImageClick) {
2296
+ this._options.imageOptions.onImageClick(this.imageData);
2297
+ }
2298
+ }
2186
2299
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FileImageTagViewComponent, deps: [{ token: ScreenWidthService }, { token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
2187
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: FileImageTagViewComponent, isStandalone: true, selector: "croco-html-file-image-tag-view", inputs: { item: "item" }, ngImport: i0, template: "<img\n [ngStyle]=\"{ 'max-height': imageMaxHeight ? imageMaxHeight + 'px' : '100%', 'max-width': imageMaxWidth ? imageMaxWidth + 'px' : '100%', }\"\n class=\"mx-auto d-block img-fluid\"\n [src]=\"imageSrc\"\n alt=\"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E\"\n/>\n", dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); }
2300
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: FileImageTagViewComponent, isStandalone: true, selector: "croco-html-file-image-tag-view", inputs: { item: "item" }, ngImport: i0, template: "<img\n [ngStyle]=\"{ 'max-height': imageMaxHeight ? imageMaxHeight + 'px' : '100%', 'max-width': imageMaxWidth ? imageMaxWidth + 'px' : '100%', }\"\n class=\"mx-auto d-block img-fluid\"\n [src]=\"imageSrc\"\n alt=\"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E\"\n (click)=\"onImageClick()\"\n style=\"cursor: pointer;\"\n/>\n", dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); }
2188
2301
  }
2189
2302
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FileImageTagViewComponent, decorators: [{
2190
2303
  type: Component,
2191
2304
  args: [{ selector: 'croco-html-file-image-tag-view', imports: [
2192
2305
  NgStyle
2193
- ], standalone: true, template: "<img\n [ngStyle]=\"{ 'max-height': imageMaxHeight ? imageMaxHeight + 'px' : '100%', 'max-width': imageMaxWidth ? imageMaxWidth + 'px' : '100%', }\"\n class=\"mx-auto d-block img-fluid\"\n [src]=\"imageSrc\"\n alt=\"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E\"\n/>\n" }]
2306
+ ], standalone: true, template: "<img\n [ngStyle]=\"{ 'max-height': imageMaxHeight ? imageMaxHeight + 'px' : '100%', 'max-width': imageMaxWidth ? imageMaxWidth + 'px' : '100%', }\"\n class=\"mx-auto d-block img-fluid\"\n [src]=\"imageSrc\"\n alt=\"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E\"\n (click)=\"onImageClick()\"\n style=\"cursor: pointer;\"\n/>\n" }]
2194
2307
  }], ctorParameters: () => [{ type: ScreenWidthService }, { type: undefined, decorators: [{
2195
2308
  type: Inject,
2196
2309
  args: [CrocoHtmlOptionsToken]
@@ -2602,7 +2715,7 @@ class FileIdSelectComponent {
2602
2715
  this.loadFiles();
2603
2716
  }
2604
2717
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FileIdSelectComponent, deps: [{ token: PublicFilesQueryService }, { token: PrivateFilesQueryService }, { token: CrocoHtmlFileOptionsService }, { token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
2605
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: FileIdSelectComponent, isStandalone: true, selector: "croco-html-file-id-select", inputs: { labelText: "labelText", fileId: "fileId" }, outputs: { fileId: "fileId", onFileIdChanged: "onFileIdChanged" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"file-id\">\n <div class=\"form-group\">\n <label for=\"fileName\">{{labelText}}</label>\n <ng-select [(ngModel)]=\"fileId\" (ngModelChange)=\"onModelChanged($event)\" [items]=\"files\" #select\n bindLabel=\"fileName\" (search)=\"onSearchChanged($event)\" [loading]=\"loading\" [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\n dropdownPosition=\"auto\" [bindValue]=\"'fileId'\" labelForId=\"fileName\" placeholder=\"\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B\"\n [virtualScroll]=\"true\">\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\n <div class=\"file-id__container\">\n <div class=\"file-id__text-container\">\n <div>\n <span class=\"h5\">\u0424\u0430\u0439\u043B: </span>\n <span class=\"h5\"><b>{{item.fileName}}</b></span>\n </div>\n <div>\n <small>\n <span>\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: <b>{{item.fileId }}</b>\n </span>\n </small>\n </div>\n </div>\n <div class=\"file-id__img\">\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc(item.fileId)\" />\n </div>\n </div>\n\n </ng-template>\n </ng-select>\n </div>\n</div>\n\n<div>\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: {{fileId}}\n</div>\n", styles: [".file-id__container{display:flex;align-items:center;justify-content:space-between;gap:10px}@media (max-width: 768px){.file-id__container{align-items:unset;flex-direction:column}}.file-id__text-container{display:flex;flex-direction:column}.file-id__text-container b{word-break:break-word;white-space:normal}@media (max-width: 768px){.file-id__text-container b{font-size:14px}}@media (max-width: 768px){.file-id__text-container span{font-size:14px}}.file-id__img img{width:100px;height:100px}\n"], dependencies: [{ kind: "ngmodule", type: NgSelectModule }, { kind: "component", type: i5.NgSelectComponent, selector: "ng-select", inputs: ["ariaLabelDropdown", "bindLabel", "bindValue", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "tabFocusOnClearButton", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: i5.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
2718
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: FileIdSelectComponent, isStandalone: true, selector: "croco-html-file-id-select", inputs: { labelText: "labelText", fileId: "fileId" }, outputs: { fileId: "fileId", onFileIdChanged: "onFileIdChanged" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"file-id\">\n <div class=\"form-group\">\n <label for=\"fileName\">{{labelText}}</label>\n <ng-select [(ngModel)]=\"fileId\" (ngModelChange)=\"onModelChanged($event)\" [items]=\"files\" #select\n bindLabel=\"fileName\" (search)=\"onSearchChanged($event)\" [loading]=\"loading\" [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\n dropdownPosition=\"auto\" [bindValue]=\"'fileId'\" labelForId=\"fileName\" placeholder=\"\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B\"\n [virtualScroll]=\"true\">\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\n <div class=\"file-id__container\">\n <div class=\"file-id__text-container\">\n <div>\n <span class=\"h5\">\u0424\u0430\u0439\u043B: </span>\n <span class=\"h5\"><b>{{item.fileName}}</b></span>\n </div>\n <div>\n <small>\n <span>\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: <b>{{item.fileId }}</b>\n </span>\n </small>\n </div>\n </div>\n <div class=\"file-id__img\">\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc(item.fileId)\" />\n </div>\n </div>\n\n </ng-template>\n </ng-select>\n </div>\n</div>\n\n<div>\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: {{fileId}}\n</div>\n", styles: [".file-id__container{display:flex;align-items:center;justify-content:space-between;gap:10px}@media (max-width: 768px){.file-id__container{align-items:unset;flex-direction:column}}.file-id__text-container{display:flex;flex-direction:column}.file-id__text-container b{word-break:break-word;white-space:normal}@media (max-width: 768px){.file-id__text-container b{font-size:14px}}@media (max-width: 768px){.file-id__text-container span{font-size:14px}}.file-id__img img{width:100px;height:100px}\n"], dependencies: [{ kind: "ngmodule", type: NgSelectModule }, { kind: "component", type: i6.NgSelectComponent, selector: "ng-select", inputs: ["ariaLabelDropdown", "bindLabel", "bindValue", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "tabFocusOnClearButton", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: i6.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
2606
2719
  }
2607
2720
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FileIdSelectComponent, decorators: [{
2608
2721
  type: Component,
@@ -3258,7 +3371,7 @@ class VisualEditorComponent {
3258
3371
  return `align-${type}`;
3259
3372
  }
3260
3373
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VisualEditorComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
3261
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: VisualEditorComponent, isStandalone: true, selector: "croco-visual-editor", inputs: { showMarkUp: "showMarkUp", useHtmlRaw: "useHtmlRaw", html: "html" }, outputs: { html: "html", onHtmlChanged: "onHtmlChanged", rendered: "rendered" }, viewQueries: [{ propertyName: "textArea", first: true, predicate: ["textArea"], descendants: true }], ngImport: i0, template: "@if (isLoading) {\n <div>\n <div>\n <mat-spinner style=\"margin:0 auto;\"></mat-spinner>\n <div style=\"text-align: center;\">{{loadingText}}</div>\n </div>\n <div style=\"height: 10px;\"></div>\n </div>\n}\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <div class=\"w-100\" style=\"margin-bottom: 22px\">\n <div class=\"tags\">\n @for (tag of tags; track tag.displayValue) {\n <div class=\"tag-item\"\n (click)=\"selectTag(tag)\"\n [class.active]=\"selectedValue === tag.tag\"\n >\n <div class=\"tag-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: tag.tag}\">\n </ng-container>\n </div>\n <div class=\"tag-text\">{{tag.displayValue}}</div>\n </div>\n }\n\n @if (useCustomWidgetsButton) {\n <div class=\"tag-item\"\n (click)=\"customWidgetsClickHandler()\"\n >\n <div class=\"tag-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: 'custom-widget'}\">\n </ng-container>\n </div>\n <div class=\"tag-text\">\u0414\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044B</div>\n </div>\n }\n </div>\n </div>\n </div>\n @if (selectedValue === ExternalVideoTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0438\u0434\u0435\u043E\u043F\u043B\u0435\u0435\u0440</mat-label>\n <mat-select [(ngModel)]=\"selectedVideoPlayer\">\n @for (videoPlayer of videoPlayers; track videoPlayer.type) {\n <mat-option [value]=\"videoPlayer.type\">\n {{videoPlayer.displayValue}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (selectedVideoPlayer === ExternalVideoSupportedTypes.Code) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\"\n [(ngModel)]=\"htmlRaw\"\n >\n </mat-form-field>\n </div>\n }\n }\n @if (selectedValue === HtmlRawTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430</mat-label>\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\"\n #textArea\n [(ngModel)]=\"htmlRaw\"\n ></textarea>\n </mat-form-field>\n </div>\n }\n @if (selectedValue === 'text') {\n <div style=\"display: flex; justify-content: space-between; flex-wrap: wrap\">\n <div style=\"margin-bottom: 22px; overflow-x: auto;\">\n <mat-button-toggle-group\n [(ngModel)]=\"textTag\"\n [hideSingleSelectionIndicator]=\"true\"\n >\n @for (option of textTagOptions; track option) {\n <mat-button-toggle value=\"{{ option.tag }}\">\n {{ option.displayValue }}\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n\n <div style=\"margin-bottom: 22px\">\n <mat-button-toggle-group\n [(ngModel)]=\"alignment\"\n [hideSingleSelectionIndicator]=\"true\"\n >\n @for (option of alignmentOptions; track option) {\n <mat-button-toggle value=\"{{ option.value }}\">\n <span class=\"text-align-icon\">\n <ng-container [ngTemplateOutlet]=\"textAlignToggleIcons\"\n [ngTemplateOutletContext]=\"{icon: option.value}\">\n </ng-container>\n </span>\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0422\u0435\u043A\u0441\u0442</mat-label>\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0422\u0435\u043A\u0441\u0442\"\n #textArea\n [(ngModel)]=\"text\"\n ></textarea>\n </mat-form-field>\n }\n\n <div class=\"col-12\">\n <button (click)=\"addTagClickHandler()\" class=\"w-100\" mat-stroked-button>\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u0433\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <croco-html-add-files-btn (filesTagsReady)=\"filesTagsReadyHandler($event)\"\n (postFilesStarted)=\"postFilesStartedEventHandler()\" class=\"w-100\">\n </croco-html-add-files-btn>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\">\n @for (tag of bodyTags; track tag; let i = $index) {\n <div cdkDrag>\n <mat-card style=\"margin: 2px;\" class=\"mat-card special\">\n <mat-card-content>\n <div class=\"d-flex justify-content-between\">\n <div class=\"example-handle\" cdkDragHandle>\n <svg width=\"24\" height=\"24\" class=\"move-icon\">\n <use [attr.xlink:href]=\"'move-icon' | spriteIconPath\"></use>\n </svg>\n </div>\n <div>\n <div class=\"badge\" [matTooltip]=\"tag.tagDescription.displayValue\">\n <span class=\"text-align-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: tag.tagDescription.tag}\">\n </ng-container>\n </span>\n </div>\n </div>\n </div>\n <div style=\"height: 15px;\"></div>\n <croco-html-main-editor-block [tag]=\"tag\" (onTagSaved)=\"onTagChangedHandler($event, i)\"\n (onTagRemoved)=\"onTagRemovedHandler(i)\">\n </croco-html-main-editor-block>\n </mat-card-content>\n </mat-card>\n </div>\n }\n </div>\n</div>\n\n<ng-template #textAlignToggleIcons let-icon=\"icon\">\n <svg width=\"20\" height=\"20\">\n <use [attr.xlink:href]=\"setAlignButton(icon) | spriteIconPath\"></use>\n </svg>\n</ng-template>\n\n<ng-template #tagButtonIcons let-icon=\"icon\">\n @if (isDefinedCustomWidget(icon)) {\n <croco-html-custom-widget-icon [tagName]=\"icon\"></croco-html-custom-widget-icon>\n }\n @else if (icon.indexOf('h') === 0 && icon.length === 2) {\n {{icon.toUpperCase()}}\n }\n @else {\n <svg width=\"20\" height=\"20\">\n <use [attr.xlink:href]=\"setTagButton(icon) | spriteIconPath\"></use>\n </svg>\n }\n</ng-template>\n", styles: [":host{--mat-standard-button-toggle-selected-state-background-color: #323E8B;--mat-standard-button-toggle-text-color: #323E8B;--mat-standard-button-toggle-selected-state-text-color: white;--mat-standard-button-toggle-height: 36px;--mat-standard-button-toggle-divider-color: #323E8B;--mdc-outlined-button-label-text-weight: 400;--mdc-outlined-button-label-text-color: #333333 !important;--mdc-outlined-button-container-shape: 30px;--mdc-outlined-button-outline-width: 2px;--mdc-outlined-button-container-height: 44px}:host ::ng-deep .mat-button-toggle-appearance-standard span.mat-button-toggle-label-content{padding:0 8px;min-width:36px}.text-align-icon,.mat-button-toggle .text-align-icon{color:#323e8b}.mat-button-toggle:hover,.mat-button-toggle:hover .text-align-icon{color:#747ebf}.mat-button-toggle-checked .text-align-icon{color:#fff}.example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.badge{width:44px;height:44px;border-radius:50%;border:1px solid #323E8B;display:flex;align-items:center;justify-content:center;color:#323e8b}.mat-card.special{border:1px solid #747EBF;border-radius:8px;box-shadow:none;margin:2px 2px 10px}.tags{display:flex;gap:10px;flex-wrap:wrap}@media (max-width: 768px){.tags{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;padding:16px;background-color:#f5f5f5;border-radius:12px}}@media (max-width: 575px){.tags{grid-template-columns:repeat(2,1fr);gap:10px;padding:12px}}.tag-item{display:flex;align-items:center;gap:5px;cursor:pointer;padding:10px 20px;border:1px solid #323E8B;border-radius:30px;background-color:#fff;color:#23262a;transition:.2s ease-in-out}@media (max-width: 768px){.tag-item{flex-direction:column;justify-content:center;padding:16px 8px;border-radius:12px;min-height:80px;gap:8px}}.tag-icon{color:#323e8b;display:flex;align-items:center;justify-content:center}.tag-icon svg{width:20px;height:20px}@media (max-width: 768px){.tag-icon{font-size:24px;margin-bottom:0}.tag-icon svg{width:24px;height:24px}}.tag-text{color:#323e8b}@media (max-width: 768px){.tag-text{font-size:12px;font-weight:500;text-align:center;line-height:1.2}}.text-align-icon{color:#323e8b}.tag-item.active{background-color:#323e8b;color:#fff}.tag-item.active .tag-icon,.tag-item.active .tag-text{color:#fff}.tag-item.active svg{color:#fff}.tag-item:hover{color:#747ebf;box-shadow:0 0 4px #747ebf}.tag-item:hover .tag-icon,.tag-item:hover .tag-text{color:#747ebf}.tag-item:hover svg{color:#747ebf}@media (max-width: 768px){.tag-item:hover{color:inherit;box-shadow:none}.tag-item:hover svg{color:inherit}.tag-item:active{color:#747ebf;box-shadow:0 0 4px #747ebf}.tag-item:active svg{color:#747ebf}}.move-icon:hover{cursor:pointer;opacity:.7}.cdk-drag.cdk-drag-placeholder,.cdk-drag-preview{opacity:.5;transition:opacity .2s}.example-handle{color:#323e8b}\n"], dependencies: [{ kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: AddFilesBtnComponent, selector: "croco-html-add-files-btn", outputs: ["postFilesStarted", "filesTagsReady"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: MainEditorBlockComponent, selector: "croco-html-main-editor-block", inputs: ["tag"], outputs: ["onTagSaved", "onTagRemoved"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: SpriteIconPathPipe, name: "spriteIconPath" }, { kind: "component", type: CustomWidgetIconComponent, selector: "croco-html-custom-widget-icon", inputs: ["tagName"] }] }); }
3374
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: VisualEditorComponent, isStandalone: true, selector: "croco-visual-editor", inputs: { showMarkUp: "showMarkUp", useHtmlRaw: "useHtmlRaw", html: "html" }, outputs: { html: "html", onHtmlChanged: "onHtmlChanged", rendered: "rendered" }, viewQueries: [{ propertyName: "textArea", first: true, predicate: ["textArea"], descendants: true }], ngImport: i0, template: "@if (isLoading) {\n <div>\n <div>\n <mat-spinner style=\"margin:0 auto;\"></mat-spinner>\n <div style=\"text-align: center;\">{{loadingText}}</div>\n </div>\n <div style=\"height: 10px;\"></div>\n </div>\n}\n<div [hidden]=\"isLoading\">\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\">\n @for (tag of bodyTags; track tag; let i = $index) {\n <div cdkDrag>\n <mat-card style=\"margin: 2px;\" class=\"mat-card special\">\n <mat-card-content>\n <div class=\"d-flex justify-content-between\">\n <div class=\"example-handle\" cdkDragHandle>\n <svg width=\"24\" height=\"24\" class=\"move-icon\">\n <use [attr.xlink:href]=\"'move-icon' | spriteIconPath\"></use>\n </svg>\n </div>\n <div>\n <div class=\"badge\" [matTooltip]=\"tag.tagDescription.displayValue\">\n <span class=\"text-align-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: tag.tagDescription.tag}\">\n </ng-container>\n </span>\n </div>\n </div>\n </div>\n <div style=\"height: 15px;\"></div>\n <croco-html-main-editor-block [tag]=\"tag\" (onTagSaved)=\"onTagChangedHandler($event, i)\"\n (onTagRemoved)=\"onTagRemovedHandler(i)\">\n </croco-html-main-editor-block>\n </mat-card-content>\n </mat-card>\n </div>\n }\n </div>\n</div>\n<div style=\"height: 10px;\"></div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <div class=\"w-100\" style=\"margin-bottom: 22px\">\n <div class=\"tags\">\n @for (tag of tags; track tag.displayValue) {\n <div class=\"tag-item\"\n (click)=\"selectTag(tag)\"\n [class.active]=\"selectedValue === tag.tag\"\n >\n <div class=\"tag-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: tag.tag}\">\n </ng-container>\n </div>\n <div class=\"tag-text\">{{tag.displayValue}}</div>\n </div>\n }\n\n @if (useCustomWidgetsButton) {\n <div class=\"tag-item\"\n (click)=\"customWidgetsClickHandler()\"\n >\n <div class=\"tag-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: 'custom-widget'}\">\n </ng-container>\n </div>\n <div class=\"tag-text\">\u0414\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044B</div>\n </div>\n }\n </div>\n </div>\n </div>\n @if (selectedValue === ExternalVideoTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0438\u0434\u0435\u043E\u043F\u043B\u0435\u0435\u0440</mat-label>\n <mat-select [(ngModel)]=\"selectedVideoPlayer\">\n @for (videoPlayer of videoPlayers; track videoPlayer.type) {\n <mat-option [value]=\"videoPlayer.type\">\n {{videoPlayer.displayValue}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (selectedVideoPlayer === ExternalVideoSupportedTypes.Code) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\"\n [(ngModel)]=\"htmlRaw\"\n >\n </mat-form-field>\n </div>\n }\n }\n @if (selectedValue === HtmlRawTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430</mat-label>\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\"\n #textArea\n [(ngModel)]=\"htmlRaw\"\n ></textarea>\n </mat-form-field>\n </div>\n }\n @if (selectedValue === 'text') {\n <div style=\"display: flex; justify-content: space-between; flex-wrap: wrap\">\n <div style=\"margin-bottom: 22px; overflow-x: auto;\">\n <mat-button-toggle-group\n [(ngModel)]=\"textTag\"\n [hideSingleSelectionIndicator]=\"true\"\n >\n @for (option of textTagOptions; track option) {\n <mat-button-toggle value=\"{{ option.tag }}\">\n {{ option.displayValue }}\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n\n <div style=\"margin-bottom: 22px\">\n <mat-button-toggle-group\n [(ngModel)]=\"alignment\"\n [hideSingleSelectionIndicator]=\"true\"\n >\n @for (option of alignmentOptions; track option) {\n <mat-button-toggle value=\"{{ option.value }}\">\n <span class=\"text-align-icon\">\n <ng-container [ngTemplateOutlet]=\"textAlignToggleIcons\"\n [ngTemplateOutletContext]=\"{icon: option.value}\">\n </ng-container>\n </span>\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0422\u0435\u043A\u0441\u0442</mat-label>\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0422\u0435\u043A\u0441\u0442\"\n #textArea\n [(ngModel)]=\"text\"\n ></textarea>\n </mat-form-field>\n }\n\n <div class=\"col-12\">\n <button (click)=\"addTagClickHandler()\" class=\"w-100\" mat-stroked-button>\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\"></div>\n</div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <croco-html-add-files-btn (filesTagsReady)=\"filesTagsReadyHandler($event)\"\n (postFilesStarted)=\"postFilesStartedEventHandler()\" class=\"w-100\">\n </croco-html-add-files-btn>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n\n<ng-template #textAlignToggleIcons let-icon=\"icon\">\n <svg width=\"20\" height=\"20\">\n <use [attr.xlink:href]=\"setAlignButton(icon) | spriteIconPath\"></use>\n </svg>\n</ng-template>\n\n<ng-template #tagButtonIcons let-icon=\"icon\">\n @if (isDefinedCustomWidget(icon)) {\n <croco-html-custom-widget-icon [tagName]=\"icon\"></croco-html-custom-widget-icon>\n }\n @else if (icon.indexOf('h') === 0 && icon.length === 2) {\n {{icon.toUpperCase()}}\n }\n @else {\n <svg width=\"20\" height=\"20\">\n <use [attr.xlink:href]=\"setTagButton(icon) | spriteIconPath\"></use>\n </svg>\n }\n</ng-template>\n", styles: [":host{--mat-standard-button-toggle-selected-state-background-color: #323E8B;--mat-standard-button-toggle-text-color: #323E8B;--mat-standard-button-toggle-selected-state-text-color: white;--mat-standard-button-toggle-height: 36px;--mat-standard-button-toggle-divider-color: #323E8B;--mdc-outlined-button-label-text-weight: 400;--mdc-outlined-button-label-text-color: #333333 !important;--mdc-outlined-button-container-shape: 30px;--mdc-outlined-button-outline-width: 2px;--mdc-outlined-button-container-height: 44px}:host ::ng-deep .mat-button-toggle-appearance-standard span.mat-button-toggle-label-content{padding:0 8px;min-width:36px}.text-align-icon,.mat-button-toggle .text-align-icon{color:#323e8b}.mat-button-toggle:hover,.mat-button-toggle:hover .text-align-icon{color:#747ebf}.mat-button-toggle-checked .text-align-icon{color:#fff}.example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.badge{width:44px;height:44px;border-radius:50%;border:1px solid #323E8B;display:flex;align-items:center;justify-content:center;color:#323e8b}.mat-card.special{border:1px solid #747EBF;border-radius:8px;box-shadow:none;margin:2px 2px 10px}.tags{display:flex;gap:10px;flex-wrap:wrap}@media (max-width: 768px){.tags{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;padding:16px;background-color:#f5f5f5;border-radius:12px}}@media (max-width: 575px){.tags{grid-template-columns:repeat(2,1fr);gap:10px;padding:12px}}.tag-item{display:flex;align-items:center;gap:5px;cursor:pointer;padding:10px 20px;border:1px solid #323E8B;border-radius:30px;background-color:#fff;color:#23262a;transition:.2s ease-in-out}@media (max-width: 768px){.tag-item{flex-direction:column;justify-content:center;padding:16px 8px;border-radius:12px;min-height:80px;gap:8px}}.tag-icon{color:#323e8b;display:flex;align-items:center;justify-content:center}.tag-icon svg{width:20px;height:20px}@media (max-width: 768px){.tag-icon{font-size:24px;margin-bottom:0}.tag-icon svg{width:24px;height:24px}}.tag-text{color:#323e8b}@media (max-width: 768px){.tag-text{font-size:12px;font-weight:500;text-align:center;line-height:1.2}}.text-align-icon{color:#323e8b}.tag-item.active{background-color:#323e8b;color:#fff}.tag-item.active .tag-icon,.tag-item.active .tag-text{color:#fff}.tag-item.active svg{color:#fff}.tag-item:hover{color:#747ebf;box-shadow:0 0 4px #747ebf}.tag-item:hover .tag-icon,.tag-item:hover .tag-text{color:#747ebf}.tag-item:hover svg{color:#747ebf}@media (max-width: 768px){.tag-item:hover{color:inherit;box-shadow:none}.tag-item:hover svg{color:inherit}.tag-item:active{color:#747ebf;box-shadow:0 0 4px #747ebf}.tag-item:active svg{color:#747ebf}}.move-icon:hover{cursor:pointer;opacity:.7}.cdk-drag.cdk-drag-placeholder,.cdk-drag-preview{opacity:.5;transition:opacity .2s}.example-handle{color:#323e8b}\n"], dependencies: [{ kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: AddFilesBtnComponent, selector: "croco-html-add-files-btn", outputs: ["postFilesStarted", "filesTagsReady"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: MainEditorBlockComponent, selector: "croco-html-main-editor-block", inputs: ["tag"], outputs: ["onTagSaved", "onTagRemoved"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: SpriteIconPathPipe, name: "spriteIconPath" }, { kind: "component", type: CustomWidgetIconComponent, selector: "croco-html-custom-widget-icon", inputs: ["tagName"] }] }); }
3262
3375
  }
3263
3376
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VisualEditorComponent, decorators: [{
3264
3377
  type: Component,
@@ -3285,7 +3398,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
3285
3398
  MatTooltip,
3286
3399
  SpriteIconPathPipe,
3287
3400
  CustomWidgetIconComponent
3288
- ], template: "@if (isLoading) {\n <div>\n <div>\n <mat-spinner style=\"margin:0 auto;\"></mat-spinner>\n <div style=\"text-align: center;\">{{loadingText}}</div>\n </div>\n <div style=\"height: 10px;\"></div>\n </div>\n}\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <div class=\"w-100\" style=\"margin-bottom: 22px\">\n <div class=\"tags\">\n @for (tag of tags; track tag.displayValue) {\n <div class=\"tag-item\"\n (click)=\"selectTag(tag)\"\n [class.active]=\"selectedValue === tag.tag\"\n >\n <div class=\"tag-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: tag.tag}\">\n </ng-container>\n </div>\n <div class=\"tag-text\">{{tag.displayValue}}</div>\n </div>\n }\n\n @if (useCustomWidgetsButton) {\n <div class=\"tag-item\"\n (click)=\"customWidgetsClickHandler()\"\n >\n <div class=\"tag-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: 'custom-widget'}\">\n </ng-container>\n </div>\n <div class=\"tag-text\">\u0414\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044B</div>\n </div>\n }\n </div>\n </div>\n </div>\n @if (selectedValue === ExternalVideoTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0438\u0434\u0435\u043E\u043F\u043B\u0435\u0435\u0440</mat-label>\n <mat-select [(ngModel)]=\"selectedVideoPlayer\">\n @for (videoPlayer of videoPlayers; track videoPlayer.type) {\n <mat-option [value]=\"videoPlayer.type\">\n {{videoPlayer.displayValue}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (selectedVideoPlayer === ExternalVideoSupportedTypes.Code) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\"\n [(ngModel)]=\"htmlRaw\"\n >\n </mat-form-field>\n </div>\n }\n }\n @if (selectedValue === HtmlRawTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430</mat-label>\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\"\n #textArea\n [(ngModel)]=\"htmlRaw\"\n ></textarea>\n </mat-form-field>\n </div>\n }\n @if (selectedValue === 'text') {\n <div style=\"display: flex; justify-content: space-between; flex-wrap: wrap\">\n <div style=\"margin-bottom: 22px; overflow-x: auto;\">\n <mat-button-toggle-group\n [(ngModel)]=\"textTag\"\n [hideSingleSelectionIndicator]=\"true\"\n >\n @for (option of textTagOptions; track option) {\n <mat-button-toggle value=\"{{ option.tag }}\">\n {{ option.displayValue }}\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n\n <div style=\"margin-bottom: 22px\">\n <mat-button-toggle-group\n [(ngModel)]=\"alignment\"\n [hideSingleSelectionIndicator]=\"true\"\n >\n @for (option of alignmentOptions; track option) {\n <mat-button-toggle value=\"{{ option.value }}\">\n <span class=\"text-align-icon\">\n <ng-container [ngTemplateOutlet]=\"textAlignToggleIcons\"\n [ngTemplateOutletContext]=\"{icon: option.value}\">\n </ng-container>\n </span>\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0422\u0435\u043A\u0441\u0442</mat-label>\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0422\u0435\u043A\u0441\u0442\"\n #textArea\n [(ngModel)]=\"text\"\n ></textarea>\n </mat-form-field>\n }\n\n <div class=\"col-12\">\n <button (click)=\"addTagClickHandler()\" class=\"w-100\" mat-stroked-button>\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u0433\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <croco-html-add-files-btn (filesTagsReady)=\"filesTagsReadyHandler($event)\"\n (postFilesStarted)=\"postFilesStartedEventHandler()\" class=\"w-100\">\n </croco-html-add-files-btn>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\">\n @for (tag of bodyTags; track tag; let i = $index) {\n <div cdkDrag>\n <mat-card style=\"margin: 2px;\" class=\"mat-card special\">\n <mat-card-content>\n <div class=\"d-flex justify-content-between\">\n <div class=\"example-handle\" cdkDragHandle>\n <svg width=\"24\" height=\"24\" class=\"move-icon\">\n <use [attr.xlink:href]=\"'move-icon' | spriteIconPath\"></use>\n </svg>\n </div>\n <div>\n <div class=\"badge\" [matTooltip]=\"tag.tagDescription.displayValue\">\n <span class=\"text-align-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: tag.tagDescription.tag}\">\n </ng-container>\n </span>\n </div>\n </div>\n </div>\n <div style=\"height: 15px;\"></div>\n <croco-html-main-editor-block [tag]=\"tag\" (onTagSaved)=\"onTagChangedHandler($event, i)\"\n (onTagRemoved)=\"onTagRemovedHandler(i)\">\n </croco-html-main-editor-block>\n </mat-card-content>\n </mat-card>\n </div>\n }\n </div>\n</div>\n\n<ng-template #textAlignToggleIcons let-icon=\"icon\">\n <svg width=\"20\" height=\"20\">\n <use [attr.xlink:href]=\"setAlignButton(icon) | spriteIconPath\"></use>\n </svg>\n</ng-template>\n\n<ng-template #tagButtonIcons let-icon=\"icon\">\n @if (isDefinedCustomWidget(icon)) {\n <croco-html-custom-widget-icon [tagName]=\"icon\"></croco-html-custom-widget-icon>\n }\n @else if (icon.indexOf('h') === 0 && icon.length === 2) {\n {{icon.toUpperCase()}}\n }\n @else {\n <svg width=\"20\" height=\"20\">\n <use [attr.xlink:href]=\"setTagButton(icon) | spriteIconPath\"></use>\n </svg>\n }\n</ng-template>\n", styles: [":host{--mat-standard-button-toggle-selected-state-background-color: #323E8B;--mat-standard-button-toggle-text-color: #323E8B;--mat-standard-button-toggle-selected-state-text-color: white;--mat-standard-button-toggle-height: 36px;--mat-standard-button-toggle-divider-color: #323E8B;--mdc-outlined-button-label-text-weight: 400;--mdc-outlined-button-label-text-color: #333333 !important;--mdc-outlined-button-container-shape: 30px;--mdc-outlined-button-outline-width: 2px;--mdc-outlined-button-container-height: 44px}:host ::ng-deep .mat-button-toggle-appearance-standard span.mat-button-toggle-label-content{padding:0 8px;min-width:36px}.text-align-icon,.mat-button-toggle .text-align-icon{color:#323e8b}.mat-button-toggle:hover,.mat-button-toggle:hover .text-align-icon{color:#747ebf}.mat-button-toggle-checked .text-align-icon{color:#fff}.example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.badge{width:44px;height:44px;border-radius:50%;border:1px solid #323E8B;display:flex;align-items:center;justify-content:center;color:#323e8b}.mat-card.special{border:1px solid #747EBF;border-radius:8px;box-shadow:none;margin:2px 2px 10px}.tags{display:flex;gap:10px;flex-wrap:wrap}@media (max-width: 768px){.tags{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;padding:16px;background-color:#f5f5f5;border-radius:12px}}@media (max-width: 575px){.tags{grid-template-columns:repeat(2,1fr);gap:10px;padding:12px}}.tag-item{display:flex;align-items:center;gap:5px;cursor:pointer;padding:10px 20px;border:1px solid #323E8B;border-radius:30px;background-color:#fff;color:#23262a;transition:.2s ease-in-out}@media (max-width: 768px){.tag-item{flex-direction:column;justify-content:center;padding:16px 8px;border-radius:12px;min-height:80px;gap:8px}}.tag-icon{color:#323e8b;display:flex;align-items:center;justify-content:center}.tag-icon svg{width:20px;height:20px}@media (max-width: 768px){.tag-icon{font-size:24px;margin-bottom:0}.tag-icon svg{width:24px;height:24px}}.tag-text{color:#323e8b}@media (max-width: 768px){.tag-text{font-size:12px;font-weight:500;text-align:center;line-height:1.2}}.text-align-icon{color:#323e8b}.tag-item.active{background-color:#323e8b;color:#fff}.tag-item.active .tag-icon,.tag-item.active .tag-text{color:#fff}.tag-item.active svg{color:#fff}.tag-item:hover{color:#747ebf;box-shadow:0 0 4px #747ebf}.tag-item:hover .tag-icon,.tag-item:hover .tag-text{color:#747ebf}.tag-item:hover svg{color:#747ebf}@media (max-width: 768px){.tag-item:hover{color:inherit;box-shadow:none}.tag-item:hover svg{color:inherit}.tag-item:active{color:#747ebf;box-shadow:0 0 4px #747ebf}.tag-item:active svg{color:#747ebf}}.move-icon:hover{cursor:pointer;opacity:.7}.cdk-drag.cdk-drag-placeholder,.cdk-drag-preview{opacity:.5;transition:opacity .2s}.example-handle{color:#323e8b}\n"] }]
3401
+ ], template: "@if (isLoading) {\n <div>\n <div>\n <mat-spinner style=\"margin:0 auto;\"></mat-spinner>\n <div style=\"text-align: center;\">{{loadingText}}</div>\n </div>\n <div style=\"height: 10px;\"></div>\n </div>\n}\n<div [hidden]=\"isLoading\">\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\">\n @for (tag of bodyTags; track tag; let i = $index) {\n <div cdkDrag>\n <mat-card style=\"margin: 2px;\" class=\"mat-card special\">\n <mat-card-content>\n <div class=\"d-flex justify-content-between\">\n <div class=\"example-handle\" cdkDragHandle>\n <svg width=\"24\" height=\"24\" class=\"move-icon\">\n <use [attr.xlink:href]=\"'move-icon' | spriteIconPath\"></use>\n </svg>\n </div>\n <div>\n <div class=\"badge\" [matTooltip]=\"tag.tagDescription.displayValue\">\n <span class=\"text-align-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: tag.tagDescription.tag}\">\n </ng-container>\n </span>\n </div>\n </div>\n </div>\n <div style=\"height: 15px;\"></div>\n <croco-html-main-editor-block [tag]=\"tag\" (onTagSaved)=\"onTagChangedHandler($event, i)\"\n (onTagRemoved)=\"onTagRemovedHandler(i)\">\n </croco-html-main-editor-block>\n </mat-card-content>\n </mat-card>\n </div>\n }\n </div>\n</div>\n<div style=\"height: 10px;\"></div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <div class=\"w-100\" style=\"margin-bottom: 22px\">\n <div class=\"tags\">\n @for (tag of tags; track tag.displayValue) {\n <div class=\"tag-item\"\n (click)=\"selectTag(tag)\"\n [class.active]=\"selectedValue === tag.tag\"\n >\n <div class=\"tag-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: tag.tag}\">\n </ng-container>\n </div>\n <div class=\"tag-text\">{{tag.displayValue}}</div>\n </div>\n }\n\n @if (useCustomWidgetsButton) {\n <div class=\"tag-item\"\n (click)=\"customWidgetsClickHandler()\"\n >\n <div class=\"tag-icon\">\n <ng-container [ngTemplateOutlet]=\"tagButtonIcons\"\n [ngTemplateOutletContext]=\"{icon: 'custom-widget'}\">\n </ng-container>\n </div>\n <div class=\"tag-text\">\u0414\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044B</div>\n </div>\n }\n </div>\n </div>\n </div>\n @if (selectedValue === ExternalVideoTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0438\u0434\u0435\u043E\u043F\u043B\u0435\u0435\u0440</mat-label>\n <mat-select [(ngModel)]=\"selectedVideoPlayer\">\n @for (videoPlayer of videoPlayers; track videoPlayer.type) {\n <mat-option [value]=\"videoPlayer.type\">\n {{videoPlayer.displayValue}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (selectedVideoPlayer === ExternalVideoSupportedTypes.Code) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430</mat-label>\n <input\n matInput\n placeholder=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\"\n [(ngModel)]=\"htmlRaw\"\n >\n </mat-form-field>\n </div>\n }\n }\n @if (selectedValue === HtmlRawTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\">\n <mat-label>\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430</mat-label>\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\"\n #textArea\n [(ngModel)]=\"htmlRaw\"\n ></textarea>\n </mat-form-field>\n </div>\n }\n @if (selectedValue === 'text') {\n <div style=\"display: flex; justify-content: space-between; flex-wrap: wrap\">\n <div style=\"margin-bottom: 22px; overflow-x: auto;\">\n <mat-button-toggle-group\n [(ngModel)]=\"textTag\"\n [hideSingleSelectionIndicator]=\"true\"\n >\n @for (option of textTagOptions; track option) {\n <mat-button-toggle value=\"{{ option.tag }}\">\n {{ option.displayValue }}\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n\n <div style=\"margin-bottom: 22px\">\n <mat-button-toggle-group\n [(ngModel)]=\"alignment\"\n [hideSingleSelectionIndicator]=\"true\"\n >\n @for (option of alignmentOptions; track option) {\n <mat-button-toggle value=\"{{ option.value }}\">\n <span class=\"text-align-icon\">\n <ng-container [ngTemplateOutlet]=\"textAlignToggleIcons\"\n [ngTemplateOutletContext]=\"{icon: option.value}\">\n </ng-container>\n </span>\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0422\u0435\u043A\u0441\u0442</mat-label>\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0422\u0435\u043A\u0441\u0442\"\n #textArea\n [(ngModel)]=\"text\"\n ></textarea>\n </mat-form-field>\n }\n\n <div class=\"col-12\">\n <button (click)=\"addTagClickHandler()\" class=\"w-100\" mat-stroked-button>\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\"></div>\n</div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <croco-html-add-files-btn (filesTagsReady)=\"filesTagsReadyHandler($event)\"\n (postFilesStarted)=\"postFilesStartedEventHandler()\" class=\"w-100\">\n </croco-html-add-files-btn>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n\n<ng-template #textAlignToggleIcons let-icon=\"icon\">\n <svg width=\"20\" height=\"20\">\n <use [attr.xlink:href]=\"setAlignButton(icon) | spriteIconPath\"></use>\n </svg>\n</ng-template>\n\n<ng-template #tagButtonIcons let-icon=\"icon\">\n @if (isDefinedCustomWidget(icon)) {\n <croco-html-custom-widget-icon [tagName]=\"icon\"></croco-html-custom-widget-icon>\n }\n @else if (icon.indexOf('h') === 0 && icon.length === 2) {\n {{icon.toUpperCase()}}\n }\n @else {\n <svg width=\"20\" height=\"20\">\n <use [attr.xlink:href]=\"setTagButton(icon) | spriteIconPath\"></use>\n </svg>\n }\n</ng-template>\n", styles: [":host{--mat-standard-button-toggle-selected-state-background-color: #323E8B;--mat-standard-button-toggle-text-color: #323E8B;--mat-standard-button-toggle-selected-state-text-color: white;--mat-standard-button-toggle-height: 36px;--mat-standard-button-toggle-divider-color: #323E8B;--mdc-outlined-button-label-text-weight: 400;--mdc-outlined-button-label-text-color: #333333 !important;--mdc-outlined-button-container-shape: 30px;--mdc-outlined-button-outline-width: 2px;--mdc-outlined-button-container-height: 44px}:host ::ng-deep .mat-button-toggle-appearance-standard span.mat-button-toggle-label-content{padding:0 8px;min-width:36px}.text-align-icon,.mat-button-toggle .text-align-icon{color:#323e8b}.mat-button-toggle:hover,.mat-button-toggle:hover .text-align-icon{color:#747ebf}.mat-button-toggle-checked .text-align-icon{color:#fff}.example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.badge{width:44px;height:44px;border-radius:50%;border:1px solid #323E8B;display:flex;align-items:center;justify-content:center;color:#323e8b}.mat-card.special{border:1px solid #747EBF;border-radius:8px;box-shadow:none;margin:2px 2px 10px}.tags{display:flex;gap:10px;flex-wrap:wrap}@media (max-width: 768px){.tags{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;padding:16px;background-color:#f5f5f5;border-radius:12px}}@media (max-width: 575px){.tags{grid-template-columns:repeat(2,1fr);gap:10px;padding:12px}}.tag-item{display:flex;align-items:center;gap:5px;cursor:pointer;padding:10px 20px;border:1px solid #323E8B;border-radius:30px;background-color:#fff;color:#23262a;transition:.2s ease-in-out}@media (max-width: 768px){.tag-item{flex-direction:column;justify-content:center;padding:16px 8px;border-radius:12px;min-height:80px;gap:8px}}.tag-icon{color:#323e8b;display:flex;align-items:center;justify-content:center}.tag-icon svg{width:20px;height:20px}@media (max-width: 768px){.tag-icon{font-size:24px;margin-bottom:0}.tag-icon svg{width:24px;height:24px}}.tag-text{color:#323e8b}@media (max-width: 768px){.tag-text{font-size:12px;font-weight:500;text-align:center;line-height:1.2}}.text-align-icon{color:#323e8b}.tag-item.active{background-color:#323e8b;color:#fff}.tag-item.active .tag-icon,.tag-item.active .tag-text{color:#fff}.tag-item.active svg{color:#fff}.tag-item:hover{color:#747ebf;box-shadow:0 0 4px #747ebf}.tag-item:hover .tag-icon,.tag-item:hover .tag-text{color:#747ebf}.tag-item:hover svg{color:#747ebf}@media (max-width: 768px){.tag-item:hover{color:inherit;box-shadow:none}.tag-item:hover svg{color:inherit}.tag-item:active{color:#747ebf;box-shadow:0 0 4px #747ebf}.tag-item:active svg{color:#747ebf}}.move-icon:hover{cursor:pointer;opacity:.7}.cdk-drag.cdk-drag-placeholder,.cdk-drag-preview{opacity:.5;transition:opacity .2s}.example-handle{color:#323e8b}\n"] }]
3289
3402
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
3290
3403
  type: Inject,
3291
3404
  args: [CrocoHtmlOptionsToken]
@@ -3450,7 +3563,7 @@ class MainEditorComponent {
3450
3563
  });
3451
3564
  }
3452
3565
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MainEditorComponent, deps: [{ token: i1$5.ClipboardService }, { token: i2$3.MatSnackBar }, { token: i0.ChangeDetectorRef }, { token: i2$2.MatDialog }, { token: CrocoHtmlFileOptionsService }, { token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
3453
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: MainEditorComponent, isStandalone: true, selector: "croco-html-main-editor", inputs: { showMarkUp: "showMarkUp", useHtmlRaw: "useHtmlRaw", html: "html" }, outputs: { html: "html", onHtmlChanged: "onHtmlChanged" }, viewQueries: [{ propertyName: "visualEditor", first: true, predicate: ["visualEditor"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<mat-tab-group mat-stretch-tabs=\"false\" mat-align-tabs=\"start\" style=\"position: relative\">\n <mat-tab>\n <ng-template mat-tab-label>\n <svg class=\"custom-icon\" width=\"32\" height=\"26\">\n <use [attr.xlink:href]=\"'visual-editor-tab' | spriteIconPath\"></use>\n </svg>\n </ng-template>\n\n <div style=\"height: 20px;\"></div>\n\n <croco-visual-editor #visualEditor [useHtmlRaw]=\"true\" [html]=\"html\" (onHtmlChanged)=\"onHtmlChangedHandler($event)\"\n (rendered)=\"visualEditorRenderedHandler()\">\n </croco-visual-editor>\n\n <div style=\"height: 20px;\"></div>\n </mat-tab>\n\n <mat-tab>\n <ng-template mat-tab-label>\n <svg class=\"custom-icon\" width=\"32\" height=\"26\">\n <use [attr.xlink:href]=\"'source-code-tab' | spriteIconPath\"></use>\n </svg>\n </ng-template>\n\n <div style=\"height: 10px;\"></div>\n @if (visualEditorRendered) {\n <div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434</mat-label>\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\" cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434\" [(ngModel)]=\"html\" (ngModelChange)=\"textAreaModelChangedHandler()\"></textarea>\n </mat-form-field>\n </div>\n }\n\n <button (click)=\"copyMarkUp()\" mat-raised-button color=\"primary\">\n \u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0443\n </button>\n </mat-tab>\n <mat-tab>\n <ng-template mat-tab-label>\n <svg class=\"custom-icon\" width=\"32\" height=\"30\">\n <use [attr.xlink:href]=\"'viewer-tab' | spriteIconPath\"></use>\n </svg>\n </ng-template>\n\n\n <mat-card style=\"padding: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <croco-html-view [html]=\"html\">\n </croco-html-view>\n </mat-card-content>\n </mat-card>\n </mat-tab>\n</mat-tab-group>\n\n<div [hidden]=\"!showSettingsButton\">\n <mat-icon class=\"settings\" (click)=\"openSettingsModal()\">settings</mat-icon>\n</div>\n", styles: [":host ::ng-deep .mdc-tab.mat-mdc-tab{background-color:#f7f7fa}:host ::ng-deep .mdc-tab.mat-mdc-tab .custom-icon{fill:#323e8b}:host ::ng-deep .mdc-tab.mat-mdc-tab:hover{background-color:#f7f7fa}:host ::ng-deep .mdc-tab.mat-mdc-tab:hover .custom-icon{fill:#747ebf}:host ::ng-deep .mdc-tab.mat-mdc-tab.mdc-tab--active{background-color:#323e8b}:host ::ng-deep .mdc-tab.mat-mdc-tab.mdc-tab--active svg.custom-icon{fill:#fff}:host ::ng-deep div.mat-mdc-tab-labels{justify-content:center}:host{position:relative;width:100%;display:block;overflow-x:hidden}:host ::ng-deep .mat-expansion-panel,:host ::ng-deep .mat-mdc-tab-body-content,:host ::ng-deep .mat-mdc-tab-body,:host ::ng-deep .mat-mdc-tab-body-wrapper{overflow:visible}.example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.settings{position:absolute;top:20px;right:20px;cursor:pointer;z-index:1000}\n"], dependencies: [{ kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i5$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i5$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i5$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: VisualEditorComponent, selector: "croco-visual-editor", inputs: ["showMarkUp", "useHtmlRaw", "html"], outputs: ["html", "onHtmlChanged", "rendered"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: HtmlViewComponent, selector: "croco-html-view", inputs: ["html", "dataController"] }, { kind: "pipe", type: SpriteIconPathPipe, name: "spriteIconPath" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
3566
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: MainEditorComponent, isStandalone: true, selector: "croco-html-main-editor", inputs: { showMarkUp: "showMarkUp", useHtmlRaw: "useHtmlRaw", html: "html" }, outputs: { html: "html", onHtmlChanged: "onHtmlChanged" }, viewQueries: [{ propertyName: "visualEditor", first: true, predicate: ["visualEditor"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<mat-tab-group mat-stretch-tabs=\"false\" mat-align-tabs=\"start\" style=\"position: relative\">\n <mat-tab>\n <ng-template mat-tab-label>\n <svg class=\"custom-icon\" width=\"32\" height=\"26\">\n <use [attr.xlink:href]=\"'visual-editor-tab' | spriteIconPath\"></use>\n </svg>\n </ng-template>\n\n <div style=\"height: 20px;\"></div>\n\n <croco-visual-editor #visualEditor [useHtmlRaw]=\"true\" [html]=\"html\" (onHtmlChanged)=\"onHtmlChangedHandler($event)\"\n (rendered)=\"visualEditorRenderedHandler()\">\n </croco-visual-editor>\n\n <div style=\"height: 20px;\"></div>\n </mat-tab>\n\n <mat-tab>\n <ng-template mat-tab-label>\n <svg class=\"custom-icon\" width=\"32\" height=\"26\">\n <use [attr.xlink:href]=\"'source-code-tab' | spriteIconPath\"></use>\n </svg>\n </ng-template>\n\n <div style=\"height: 10px;\"></div>\n @if (visualEditorRendered) {\n <div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434</mat-label>\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\" cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434\" [(ngModel)]=\"html\" (ngModelChange)=\"textAreaModelChangedHandler()\"></textarea>\n </mat-form-field>\n </div>\n }\n\n <button (click)=\"copyMarkUp()\" mat-raised-button color=\"primary\">\n \u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0443\n </button>\n </mat-tab>\n <mat-tab>\n <ng-template mat-tab-label>\n <svg class=\"custom-icon\" width=\"32\" height=\"30\">\n <use [attr.xlink:href]=\"'viewer-tab' | spriteIconPath\"></use>\n </svg>\n </ng-template>\n\n\n <mat-card style=\"padding: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <croco-html-view [html]=\"html\">\n </croco-html-view>\n </mat-card-content>\n </mat-card>\n </mat-tab>\n</mat-tab-group>\n\n<div [hidden]=\"!showSettingsButton\">\n <mat-icon class=\"settings\" (click)=\"openSettingsModal()\">settings</mat-icon>\n</div>\n", styles: [":host ::ng-deep .mdc-tab.mat-mdc-tab{background-color:#f7f7fa}:host ::ng-deep .mdc-tab.mat-mdc-tab .custom-icon{fill:#323e8b}:host ::ng-deep .mdc-tab.mat-mdc-tab:hover{background-color:#f7f7fa}:host ::ng-deep .mdc-tab.mat-mdc-tab:hover .custom-icon{fill:#747ebf}:host ::ng-deep .mdc-tab.mat-mdc-tab.mdc-tab--active{background-color:#323e8b}:host ::ng-deep .mdc-tab.mat-mdc-tab.mdc-tab--active svg.custom-icon{fill:#fff}:host ::ng-deep div.mat-mdc-tab-labels{justify-content:center}:host{position:relative;width:100%;display:block;overflow-x:hidden}:host ::ng-deep .mat-expansion-panel,:host ::ng-deep .mat-mdc-tab-body-content,:host ::ng-deep .mat-mdc-tab-body,:host ::ng-deep .mat-mdc-tab-body-wrapper{overflow:visible}.example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.settings{position:absolute;top:20px;right:20px;cursor:pointer;z-index:1000}\n"], dependencies: [{ kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i5.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i5.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i5.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: VisualEditorComponent, selector: "croco-visual-editor", inputs: ["showMarkUp", "useHtmlRaw", "html"], outputs: ["html", "onHtmlChanged", "rendered"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i1$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i1$3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: HtmlViewComponent, selector: "croco-html-view", inputs: ["html", "dataController"] }, { kind: "pipe", type: SpriteIconPathPipe, name: "spriteIconPath" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
3454
3567
  }
3455
3568
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MainEditorComponent, decorators: [{
3456
3569
  type: Component,
@@ -3620,7 +3733,7 @@ class CrocoHtmlModule {
3620
3733
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: CrocoHtmlModule, imports: [CommonModule,
3621
3734
  FormsModule,
3622
3735
  ReactiveFormsModule,
3623
- NgSelectModule, i1$6.MatBadgeModule, i2$4.MatTableModule, i3$1.MatExpansionModule, i1$4.MatFormFieldModule, i2$3.MatSnackBarModule, i6.MatProgressBarModule, i7.MatProgressSpinnerModule, i5$1.MatTabsModule, i9.MatMenuModule, i1$3.MatCardModule, i11.MatSelectModule, i12.MatTooltipModule, i13.MatCheckboxModule, i14.MatChipsModule, i15.MatListModule, i2.MatButtonModule, i2$1.MatInputModule, i2$2.MatDialogModule, i19.MatPaginatorModule, i20.MatDatepickerModule, i21.MatGridListModule, i22.MatSlideToggleModule, i23.MatTreeModule, i24.MatNativeDateModule, i25.MatAutocompleteModule, i26.MatSidenavModule, i27.MatIconModule, i28.DragDropModule, i29.MatButtonToggleModule, ErrorBannerComponent,
3736
+ NgSelectModule, i1$6.MatBadgeModule, i2$4.MatTableModule, i3$1.MatExpansionModule, i1$4.MatFormFieldModule, i2$3.MatSnackBarModule, i6$1.MatProgressBarModule, i7.MatProgressSpinnerModule, i5.MatTabsModule, i9.MatMenuModule, i1$3.MatCardModule, i11.MatSelectModule, i12.MatTooltipModule, i13.MatCheckboxModule, i14.MatChipsModule, i15.MatListModule, i2.MatButtonModule, i2$1.MatInputModule, i2$2.MatDialogModule, i19.MatPaginatorModule, i20.MatDatepickerModule, i21.MatGridListModule, i22.MatSlideToggleModule, i23.MatTreeModule, i24.MatNativeDateModule, i25.MatAutocompleteModule, i26.MatSidenavModule, i27.MatIconModule, i28.DragDropModule, i29.MatButtonToggleModule, ErrorBannerComponent,
3624
3737
  VkVideoPlayerComponent,
3625
3738
  YoutubeVideoPlayerComponent,
3626
3739
  DownloadFileButtonEditorComponent,