@maro-tech/card 0.1.17 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import * as i1$1 from '@angular/common';
1
+ import * as i1 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
4
  import { input, inject, DestroyRef, signal, Component, computed, viewChild, viewChildren, output, effect, HostListener, Input, InjectionToken, forwardRef, Injectable, ViewChild, untracked } from '@angular/core';
@@ -6,14 +6,13 @@ import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
6
6
  import { EventBus, UiButtonComponent, UiToastService, UiModalComponent, UiConfirmService } from '@maro-tech/core';
7
7
  import { DomSanitizer } from '@angular/platform-browser';
8
8
  import Panzoom from '@panzoom/panzoom';
9
- import * as i1 from 'lucide-angular';
10
- import { Download, LucideAngularModule, Eye, FileText, Plus, Sparkles, Trash } from 'lucide-angular';
9
+ import { LucideDownload, LucideDynamicIcon, LucideEye, LucideFileText, LucidePlus, LucideSparkles, LucideTrash } from '@lucide/angular';
11
10
  import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
12
11
  import { map, shareReplay, forkJoin, switchMap, timer, of, firstValueFrom } from 'rxjs';
13
12
  import { UiTableComponent } from '@maro-tech/table';
14
13
  import { ActivatedRoute, Router, RouterLink } from '@angular/router';
15
14
  import { map as map$1, exhaustMap, catchError, takeWhile, takeUntil, finalize } from 'rxjs/operators';
16
- import * as i1$2 from '@angular/forms';
15
+ import * as i1$1 from '@angular/forms';
17
16
  import { FormsModule } from '@angular/forms';
18
17
  import { InputSelectComponent } from '@maro-tech/form';
19
18
 
@@ -117,8 +116,8 @@ class CardSectionHeaderComponent {
117
116
  return this.actions().some((action) => action.context?.entity === context.entity
118
117
  && (!context.recordId || action.context?.recordId === context.recordId));
119
118
  }
120
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardSectionHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
121
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CardSectionHeaderComponent, isStandalone: true, selector: "app-card-section-header", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
119
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardSectionHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
120
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: CardSectionHeaderComponent, isStandalone: true, selector: "app-card-section-header", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
122
121
  @if (variant() === 'tabs') {
123
122
  <header class="mb-4 flex justify-end">
124
123
  <div class="flex flex-wrap gap-2 md:justify-end">
@@ -170,7 +169,7 @@ class CardSectionHeaderComponent {
170
169
  }
171
170
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }] });
172
171
  }
173
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardSectionHeaderComponent, decorators: [{
172
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardSectionHeaderComponent, decorators: [{
174
173
  type: Component,
175
174
  args: [{
176
175
  selector: 'app-card-section-header',
@@ -281,16 +280,16 @@ class CardHtmlTabComponent {
281
280
  return null;
282
281
  }
283
282
  }
284
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardHtmlTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
285
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.20", type: CardHtmlTabComponent, isStandalone: true, selector: "app-card-html-tab", inputs: { html: { classPropertyName: "html", publicName: "html", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<section\n (click)=\"onClick($event)\"\n (keydown.enter)=\"onKeydown($event)\"\n (keydown.space)=\"onKeydown($event)\"\n>\n <div [innerHTML]=\"safeHtml()\"></div>\n</section>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
283
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardHtmlTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
284
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.24", type: CardHtmlTabComponent, isStandalone: true, selector: "app-card-html-tab", inputs: { html: { classPropertyName: "html", publicName: "html", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<section\n (click)=\"onClick($event)\"\n (keydown.enter)=\"onKeydown($event)\"\n (keydown.space)=\"onKeydown($event)\"\n>\n <div [innerHTML]=\"safeHtml()\"></div>\n</section>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
286
285
  }
287
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardHtmlTabComponent, decorators: [{
286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardHtmlTabComponent, decorators: [{
288
287
  type: Component,
289
288
  args: [{ selector: 'app-card-html-tab', standalone: true, imports: [CommonModule], template: "<section\n (click)=\"onClick($event)\"\n (keydown.enter)=\"onKeydown($event)\"\n (keydown.space)=\"onKeydown($event)\"\n>\n <div [innerHTML]=\"safeHtml()\"></div>\n</section>\n" }]
290
289
  }], propDecorators: { html: [{ type: i0.Input, args: [{ isSignal: true, alias: "html", required: false }] }] } });
291
290
 
292
291
  class ImagesViewerComponent {
293
- downloadIcon = Download;
292
+ downloadIcon = LucideDownload;
294
293
  urls = input([], ...(ngDevMode ? [{ debugName: "urls" }] : /* istanbul ignore next */ []));
295
294
  initialIndex = input(0, ...(ngDevMode ? [{ debugName: "initialIndex" }] : /* istanbul ignore next */ []));
296
295
  currentIndex = signal(0, ...(ngDevMode ? [{ debugName: "currentIndex" }] : /* istanbul ignore next */ []));
@@ -482,12 +481,12 @@ class ImagesViewerComponent {
482
481
  getOriginalUrl(url) {
483
482
  return String(url || '').replace(/\/preview(?:\?[^#]*)?$/i, '');
484
483
  }
485
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: ImagesViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
486
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: ImagesViewerComponent, isStandalone: true, selector: "app-images-viewer", inputs: { urls: { classPropertyName: "urls", publicName: "urls", isSignal: true, isRequired: false, transformFunction: null }, initialIndex: { classPropertyName: "initialIndex", publicName: "initialIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:keydown.arrowleft": "onArrowLeft()", "document:keydown.arrowright": "onArrowRight()" } }, viewQueries: [{ propertyName: "currentImage", first: true, predicate: ["currentImage"], descendants: true, isSignal: true }, { propertyName: "thumbnailButtons", predicate: ["thumbnailButton"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"fixed inset-0 z-[2300] flex items-center justify-center bg-black/80 p-3 md:p-4\" role=\"dialog\" aria-modal=\"true\" aria-label=\"\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0444\u043E\u0442\u043E\">\n <button type=\"button\" class=\"absolute inset-0\" aria-label=\"\u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\" (click)=\"closeViewer()\"></button>\n <div class=\"relative z-[1] flex h-full w-full max-w-[1500px] flex-col items-center justify-center gap-4\" (click)=\"$event.stopPropagation()\">\n <button\n type=\"button\"\n class=\"absolute right-2 top-2 z-20 inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white md:right-3 md:top-3\"\n aria-label=\"\u0417\u0430\u043A\u0440\u0438\u0442\u0438\"\n (click)=\"closeViewer()\">\n \u2715\n </button>\n\n <div\n class=\"relative flex min-h-0 w-full flex-1 items-center justify-center overflow-hidden rounded-[18px]\"\n (touchstart)=\"onTouchStart($event)\"\n (touchend)=\"onTouchEnd($event)\">\n <div class=\"h-full w-full overflow-hidden rounded-[18px]\">\n <div\n class=\"flex h-full w-full\"\n style=\"will-change: transform; backface-visibility: hidden;\"\n [style.transition]=\"imageViewerTransitionStyle\"\n [style.transform]=\"imageViewerTransform\">\n @for (url of urls(); track $index; let idx = $index) {\n <div class=\"flex h-full w-full min-w-full shrink-0 items-center justify-center overflow-hidden\" (wheel)=\"onWheel($event)\">\n @if (isPreloadIndex(idx)) {\n @if (idx === currentIndex() && isOriginalVisible() && originalPreviewUnavailable()) {\n <div class=\"max-w-md rounded-2xl bg-white/95 px-6 py-5 text-center text-sm text-slate-700 shadow-xl\">\n <p class=\"font-semibold text-slate-900\">\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u0443 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439</p>\n <p class=\"mt-1\">\u0426\u0435\u0439 \u0444\u0430\u0439\u043B \u043C\u043E\u0436\u043D\u0430 \u043B\u0438\u0448\u0435 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438.</p>\n </div>\n } @else {\n @if (idx === currentIndex()) {\n <img\n #currentImage\n [src]=\"getImageUrl(url, idx)\"\n [attr.alt]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n loading=\"eager\"\n decoding=\"async\"\n (load)=\"onImageLoad()\"\n (error)=\"onImageError(idx)\"\n (dblclick)=\"toggleZoom()\"\n class=\"block max-h-[74vh] max-w-[96vw] object-contain md:max-h-[78vh]\">\n } @else {\n <img\n [src]=\"getImageUrl(url, idx)\"\n [attr.alt]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n loading=\"lazy\"\n decoding=\"async\"\n (error)=\"onImageError(idx)\"\n class=\"block max-h-[74vh] max-w-[96vw] object-contain md:max-h-[78vh]\">\n }\n }\n }\n </div>\n }\n </div>\n </div>\n\n @if (urls().length > 1) {\n <button type=\"button\" class=\"absolute left-2 top-1/2 z-10 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full md:left-3\" aria-label=\"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0454 \u0444\u043E\u0442\u043E\" (click)=\"showPreviousImage()\">\n <span class=\"inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white\">\u2039</span>\n </button>\n <button type=\"button\" class=\"absolute right-2 top-1/2 z-10 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full md:right-3\" aria-label=\"\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0435 \u0444\u043E\u0442\u043E\" (click)=\"showNextImage()\">\n <span class=\"inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white\">\u203A</span>\n </button>\n }\n\n @if (currentUrl) {\n <div class=\"absolute bottom-3 right-3 z-20 inline-flex max-w-[calc(100%-1.5rem)] items-center gap-1.5 rounded-2xl bg-black/55 p-1.5 text-white shadow-[0_12px_28px_rgba(15,23,42,0.24)] backdrop-blur-md md:bottom-4 md:right-4\">\n <button type=\"button\" class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl text-lg transition hover:bg-white/10\" aria-label=\"\u0417\u0431\u0456\u043B\u044C\u0448\u0438\u0442\u0438 \u0444\u043E\u0442\u043E\" (click)=\"zoomIn()\">+</button>\n <button type=\"button\" class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl text-lg transition hover:bg-white/10\" aria-label=\"\u0417\u043C\u0435\u043D\u0448\u0438\u0442\u0438 \u0444\u043E\u0442\u043E\" (click)=\"zoomOut()\">\u2212</button>\n <button type=\"button\" class=\"inline-flex h-9 items-center justify-center rounded-xl px-2 text-xs font-semibold transition hover:bg-white/10\" aria-label=\"\u0421\u043A\u0438\u043D\u0443\u0442\u0438 \u043C\u0430\u0441\u0448\u0442\u0430\u0431\" (click)=\"resetZoom()\">100%</button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 items-center gap-2 rounded-xl px-2.5 text-xs font-semibold transition hover:bg-white/10\"\n [class.bg-emerald-500\\/20]=\"isOriginalVisible()\"\n [class.text-emerald-100]=\"isOriginalVisible()\"\n [attr.aria-pressed]=\"isOriginalVisible()\"\n aria-label=\"\u041F\u0435\u0440\u0435\u043C\u043A\u043D\u0443\u0442\u0438 \u043C\u0456\u0436 \u043F\u0440\u0435\u0432\u2019\u044E \u0442\u0430 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u043E\u043C\"\n (click)=\"toggleOriginal()\">\n <span>\u041E\u0440\u0438\u0433\u0456\u043D\u0430\u043B</span>\n <span\n class=\"relative inline-flex h-5 w-9 items-center rounded-full border p-0.5 transition-colors\"\n [class.bg-emerald-500]=\"isOriginalVisible()\"\n [class.bg-white\\/15]=\"!isOriginalVisible()\"\n [class.border-emerald-200]=\"isOriginalVisible()\"\n [class.border-white\\/45]=\"!isOriginalVisible()\"\n [class.ring-2]=\"isOriginalVisible()\"\n [class.ring-emerald-300\\/70]=\"isOriginalVisible()\">\n <span\n class=\"h-4 w-4 rounded-full bg-white shadow-sm transition-transform duration-200\"\n [class.translate-x-4]=\"isOriginalVisible()\">\n </span>\n </span>\n </button>\n <a\n class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl transition hover:bg-white/10\"\n [href]=\"getOriginalUrl(currentUrl)\"\n download\n aria-label=\"\u0421\u043A\u0430\u0447\u0430\u0442\u0438 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B \u0444\u043E\u0442\u043E\">\n <lucide-icon [img]=\"downloadIcon\" [size]=\"19\" [strokeWidth]=\"2.25\"></lucide-icon>\n </a>\n </div>\n }\n </div>\n\n @if (urls().length > 1) {\n <div class=\"flex w-full flex-col items-center gap-3 pb-1 md:pb-2\">\n <div class=\"flex w-full max-w-[92vw] flex-nowrap justify-start gap-2 overflow-x-auto overflow-y-hidden overscroll-x-contain px-2 py-3 md:max-w-[80vw]\">\n @for (url of urls(); track url; let idx = $index) {\n <button\n #thumbnailButton\n type=\"button\"\n class=\"h-14 w-14 shrink-0 overflow-hidden rounded-xl border-2 border-transparent bg-white p-1 transition-transform duration-200\"\n [class.border-slate-900]=\"idx === currentIndex()\"\n [class.mx-2]=\"idx === currentIndex()\"\n [style.transform]=\"idx === currentIndex() ? 'scale(1.4)' : 'scale(1)'\"\n [class.origin-center]=\"idx === currentIndex()\"\n [class.relative]=\"idx === currentIndex()\"\n [class.z-10]=\"idx === currentIndex()\"\n [attr.aria-current]=\"idx === currentIndex() ? 'true' : null\"\n [attr.aria-label]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n (click)=\"selectImage(idx, $event)\">\n <img class=\"block aspect-square w-full rounded-lg object-contain\" [src]=\"getThumbnailUrl(url)\" [attr.alt]=\"'\u041C\u0456\u043D\u0456\u0430\u0442\u044E\u0440\u0430 ' + (idx + 1)\" loading=\"lazy\" decoding=\"async\">\n </button>\n }\n </div>\n <div class=\"rounded-full bg-white/95 px-3 py-1.5 text-xs font-semibold text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.2)]\">\n {{ currentIndex() + 1 }} / {{ urls().length }}\n </div>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] });
484
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: ImagesViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
485
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: ImagesViewerComponent, isStandalone: true, selector: "app-images-viewer", inputs: { urls: { classPropertyName: "urls", publicName: "urls", isSignal: true, isRequired: false, transformFunction: null }, initialIndex: { classPropertyName: "initialIndex", publicName: "initialIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:keydown.arrowleft": "onArrowLeft()", "document:keydown.arrowright": "onArrowRight()" } }, viewQueries: [{ propertyName: "currentImage", first: true, predicate: ["currentImage"], descendants: true, isSignal: true }, { propertyName: "thumbnailButtons", predicate: ["thumbnailButton"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"fixed inset-0 z-[2300] flex items-center justify-center bg-black/80 p-3 md:p-4\" role=\"dialog\" aria-modal=\"true\" aria-label=\"\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0444\u043E\u0442\u043E\">\n <button type=\"button\" class=\"absolute inset-0\" aria-label=\"\u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\" (click)=\"closeViewer()\"></button>\n <div class=\"relative z-[1] flex h-full w-full max-w-[1500px] flex-col items-center justify-center gap-4\" (click)=\"$event.stopPropagation()\">\n <button\n type=\"button\"\n class=\"absolute right-2 top-2 z-20 inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white md:right-3 md:top-3\"\n aria-label=\"\u0417\u0430\u043A\u0440\u0438\u0442\u0438\"\n (click)=\"closeViewer()\">\n \u2715\n </button>\n\n <div\n class=\"relative flex min-h-0 w-full flex-1 items-center justify-center overflow-hidden rounded-[18px]\"\n (touchstart)=\"onTouchStart($event)\"\n (touchend)=\"onTouchEnd($event)\">\n <div class=\"h-full w-full overflow-hidden rounded-[18px]\">\n <div\n class=\"flex h-full w-full\"\n style=\"will-change: transform; backface-visibility: hidden;\"\n [style.transition]=\"imageViewerTransitionStyle\"\n [style.transform]=\"imageViewerTransform\">\n @for (url of urls(); track $index; let idx = $index) {\n <div class=\"flex h-full w-full min-w-full shrink-0 items-center justify-center overflow-hidden\" (wheel)=\"onWheel($event)\">\n @if (isPreloadIndex(idx)) {\n @if (idx === currentIndex() && isOriginalVisible() && originalPreviewUnavailable()) {\n <div class=\"max-w-md rounded-2xl bg-white/95 px-6 py-5 text-center text-sm text-slate-700 shadow-xl\">\n <p class=\"font-semibold text-slate-900\">\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u0443 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439</p>\n <p class=\"mt-1\">\u0426\u0435\u0439 \u0444\u0430\u0439\u043B \u043C\u043E\u0436\u043D\u0430 \u043B\u0438\u0448\u0435 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438.</p>\n </div>\n } @else {\n @if (idx === currentIndex()) {\n <img\n #currentImage\n [src]=\"getImageUrl(url, idx)\"\n [attr.alt]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n loading=\"eager\"\n decoding=\"async\"\n (load)=\"onImageLoad()\"\n (error)=\"onImageError(idx)\"\n (dblclick)=\"toggleZoom()\"\n class=\"block max-h-[74vh] max-w-[96vw] object-contain md:max-h-[78vh]\">\n } @else {\n <img\n [src]=\"getImageUrl(url, idx)\"\n [attr.alt]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n loading=\"lazy\"\n decoding=\"async\"\n (error)=\"onImageError(idx)\"\n class=\"block max-h-[74vh] max-w-[96vw] object-contain md:max-h-[78vh]\">\n }\n }\n }\n </div>\n }\n </div>\n </div>\n\n @if (urls().length > 1) {\n <button type=\"button\" class=\"absolute left-2 top-1/2 z-10 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full md:left-3\" aria-label=\"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0454 \u0444\u043E\u0442\u043E\" (click)=\"showPreviousImage()\">\n <span class=\"inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white\">\u2039</span>\n </button>\n <button type=\"button\" class=\"absolute right-2 top-1/2 z-10 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full md:right-3\" aria-label=\"\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0435 \u0444\u043E\u0442\u043E\" (click)=\"showNextImage()\">\n <span class=\"inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white\">\u203A</span>\n </button>\n }\n\n @if (currentUrl) {\n <div class=\"absolute bottom-3 right-3 z-20 inline-flex max-w-[calc(100%-1.5rem)] items-center gap-1.5 rounded-2xl bg-black/55 p-1.5 text-white shadow-[0_12px_28px_rgba(15,23,42,0.24)] backdrop-blur-md md:bottom-4 md:right-4\">\n <button type=\"button\" class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl text-lg transition hover:bg-white/10\" aria-label=\"\u0417\u0431\u0456\u043B\u044C\u0448\u0438\u0442\u0438 \u0444\u043E\u0442\u043E\" (click)=\"zoomIn()\">+</button>\n <button type=\"button\" class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl text-lg transition hover:bg-white/10\" aria-label=\"\u0417\u043C\u0435\u043D\u0448\u0438\u0442\u0438 \u0444\u043E\u0442\u043E\" (click)=\"zoomOut()\">\u2212</button>\n <button type=\"button\" class=\"inline-flex h-9 items-center justify-center rounded-xl px-2 text-xs font-semibold transition hover:bg-white/10\" aria-label=\"\u0421\u043A\u0438\u043D\u0443\u0442\u0438 \u043C\u0430\u0441\u0448\u0442\u0430\u0431\" (click)=\"resetZoom()\">100%</button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 items-center gap-2 rounded-xl px-2.5 text-xs font-semibold transition hover:bg-white/10\"\n [class.bg-emerald-500\\/20]=\"isOriginalVisible()\"\n [class.text-emerald-100]=\"isOriginalVisible()\"\n [attr.aria-pressed]=\"isOriginalVisible()\"\n aria-label=\"\u041F\u0435\u0440\u0435\u043C\u043A\u043D\u0443\u0442\u0438 \u043C\u0456\u0436 \u043F\u0440\u0435\u0432\u2019\u044E \u0442\u0430 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u043E\u043C\"\n (click)=\"toggleOriginal()\">\n <span>\u041E\u0440\u0438\u0433\u0456\u043D\u0430\u043B</span>\n <span\n class=\"relative inline-flex h-5 w-9 items-center rounded-full border p-0.5 transition-colors\"\n [class.bg-emerald-500]=\"isOriginalVisible()\"\n [class.bg-white\\/15]=\"!isOriginalVisible()\"\n [class.border-emerald-200]=\"isOriginalVisible()\"\n [class.border-white\\/45]=\"!isOriginalVisible()\"\n [class.ring-2]=\"isOriginalVisible()\"\n [class.ring-emerald-300\\/70]=\"isOriginalVisible()\">\n <span\n class=\"h-4 w-4 rounded-full bg-white shadow-sm transition-transform duration-200\"\n [class.translate-x-4]=\"isOriginalVisible()\">\n </span>\n </span>\n </button>\n <a\n class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl transition hover:bg-white/10\"\n [href]=\"getOriginalUrl(currentUrl)\"\n download\n aria-label=\"\u0421\u043A\u0430\u0447\u0430\u0442\u0438 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B \u0444\u043E\u0442\u043E\">\n <svg [lucideIcon]=\"downloadIcon\" [size]=\"19\" [strokeWidth]=\"2.25\"></svg>\n </a>\n </div>\n }\n </div>\n\n @if (urls().length > 1) {\n <div class=\"flex w-full flex-col items-center gap-3 pb-1 md:pb-2\">\n <div class=\"flex w-full max-w-[92vw] flex-nowrap justify-start gap-2 overflow-x-auto overflow-y-hidden overscroll-x-contain px-2 py-3 md:max-w-[80vw]\">\n @for (url of urls(); track url; let idx = $index) {\n <button\n #thumbnailButton\n type=\"button\"\n class=\"h-14 w-14 shrink-0 overflow-hidden rounded-xl border-2 border-transparent bg-white p-1 transition-transform duration-200\"\n [class.border-slate-900]=\"idx === currentIndex()\"\n [class.mx-2]=\"idx === currentIndex()\"\n [style.transform]=\"idx === currentIndex() ? 'scale(1.4)' : 'scale(1)'\"\n [class.origin-center]=\"idx === currentIndex()\"\n [class.relative]=\"idx === currentIndex()\"\n [class.z-10]=\"idx === currentIndex()\"\n [attr.aria-current]=\"idx === currentIndex() ? 'true' : null\"\n [attr.aria-label]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n (click)=\"selectImage(idx, $event)\">\n <img class=\"block aspect-square w-full rounded-lg object-contain\" [src]=\"getThumbnailUrl(url)\" [attr.alt]=\"'\u041C\u0456\u043D\u0456\u0430\u0442\u044E\u0440\u0430 ' + (idx + 1)\" loading=\"lazy\" decoding=\"async\">\n </button>\n }\n </div>\n <div class=\"rounded-full bg-white/95 px-3 py-1.5 text-xs font-semibold text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.2)]\">\n {{ currentIndex() + 1 }} / {{ urls().length }}\n </div>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }] });
487
486
  }
488
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: ImagesViewerComponent, decorators: [{
487
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: ImagesViewerComponent, decorators: [{
489
488
  type: Component,
490
- args: [{ selector: 'app-images-viewer', standalone: true, imports: [CommonModule, LucideAngularModule], template: "<div class=\"fixed inset-0 z-[2300] flex items-center justify-center bg-black/80 p-3 md:p-4\" role=\"dialog\" aria-modal=\"true\" aria-label=\"\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0444\u043E\u0442\u043E\">\n <button type=\"button\" class=\"absolute inset-0\" aria-label=\"\u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\" (click)=\"closeViewer()\"></button>\n <div class=\"relative z-[1] flex h-full w-full max-w-[1500px] flex-col items-center justify-center gap-4\" (click)=\"$event.stopPropagation()\">\n <button\n type=\"button\"\n class=\"absolute right-2 top-2 z-20 inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white md:right-3 md:top-3\"\n aria-label=\"\u0417\u0430\u043A\u0440\u0438\u0442\u0438\"\n (click)=\"closeViewer()\">\n \u2715\n </button>\n\n <div\n class=\"relative flex min-h-0 w-full flex-1 items-center justify-center overflow-hidden rounded-[18px]\"\n (touchstart)=\"onTouchStart($event)\"\n (touchend)=\"onTouchEnd($event)\">\n <div class=\"h-full w-full overflow-hidden rounded-[18px]\">\n <div\n class=\"flex h-full w-full\"\n style=\"will-change: transform; backface-visibility: hidden;\"\n [style.transition]=\"imageViewerTransitionStyle\"\n [style.transform]=\"imageViewerTransform\">\n @for (url of urls(); track $index; let idx = $index) {\n <div class=\"flex h-full w-full min-w-full shrink-0 items-center justify-center overflow-hidden\" (wheel)=\"onWheel($event)\">\n @if (isPreloadIndex(idx)) {\n @if (idx === currentIndex() && isOriginalVisible() && originalPreviewUnavailable()) {\n <div class=\"max-w-md rounded-2xl bg-white/95 px-6 py-5 text-center text-sm text-slate-700 shadow-xl\">\n <p class=\"font-semibold text-slate-900\">\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u0443 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439</p>\n <p class=\"mt-1\">\u0426\u0435\u0439 \u0444\u0430\u0439\u043B \u043C\u043E\u0436\u043D\u0430 \u043B\u0438\u0448\u0435 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438.</p>\n </div>\n } @else {\n @if (idx === currentIndex()) {\n <img\n #currentImage\n [src]=\"getImageUrl(url, idx)\"\n [attr.alt]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n loading=\"eager\"\n decoding=\"async\"\n (load)=\"onImageLoad()\"\n (error)=\"onImageError(idx)\"\n (dblclick)=\"toggleZoom()\"\n class=\"block max-h-[74vh] max-w-[96vw] object-contain md:max-h-[78vh]\">\n } @else {\n <img\n [src]=\"getImageUrl(url, idx)\"\n [attr.alt]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n loading=\"lazy\"\n decoding=\"async\"\n (error)=\"onImageError(idx)\"\n class=\"block max-h-[74vh] max-w-[96vw] object-contain md:max-h-[78vh]\">\n }\n }\n }\n </div>\n }\n </div>\n </div>\n\n @if (urls().length > 1) {\n <button type=\"button\" class=\"absolute left-2 top-1/2 z-10 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full md:left-3\" aria-label=\"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0454 \u0444\u043E\u0442\u043E\" (click)=\"showPreviousImage()\">\n <span class=\"inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white\">\u2039</span>\n </button>\n <button type=\"button\" class=\"absolute right-2 top-1/2 z-10 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full md:right-3\" aria-label=\"\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0435 \u0444\u043E\u0442\u043E\" (click)=\"showNextImage()\">\n <span class=\"inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white\">\u203A</span>\n </button>\n }\n\n @if (currentUrl) {\n <div class=\"absolute bottom-3 right-3 z-20 inline-flex max-w-[calc(100%-1.5rem)] items-center gap-1.5 rounded-2xl bg-black/55 p-1.5 text-white shadow-[0_12px_28px_rgba(15,23,42,0.24)] backdrop-blur-md md:bottom-4 md:right-4\">\n <button type=\"button\" class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl text-lg transition hover:bg-white/10\" aria-label=\"\u0417\u0431\u0456\u043B\u044C\u0448\u0438\u0442\u0438 \u0444\u043E\u0442\u043E\" (click)=\"zoomIn()\">+</button>\n <button type=\"button\" class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl text-lg transition hover:bg-white/10\" aria-label=\"\u0417\u043C\u0435\u043D\u0448\u0438\u0442\u0438 \u0444\u043E\u0442\u043E\" (click)=\"zoomOut()\">\u2212</button>\n <button type=\"button\" class=\"inline-flex h-9 items-center justify-center rounded-xl px-2 text-xs font-semibold transition hover:bg-white/10\" aria-label=\"\u0421\u043A\u0438\u043D\u0443\u0442\u0438 \u043C\u0430\u0441\u0448\u0442\u0430\u0431\" (click)=\"resetZoom()\">100%</button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 items-center gap-2 rounded-xl px-2.5 text-xs font-semibold transition hover:bg-white/10\"\n [class.bg-emerald-500\\/20]=\"isOriginalVisible()\"\n [class.text-emerald-100]=\"isOriginalVisible()\"\n [attr.aria-pressed]=\"isOriginalVisible()\"\n aria-label=\"\u041F\u0435\u0440\u0435\u043C\u043A\u043D\u0443\u0442\u0438 \u043C\u0456\u0436 \u043F\u0440\u0435\u0432\u2019\u044E \u0442\u0430 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u043E\u043C\"\n (click)=\"toggleOriginal()\">\n <span>\u041E\u0440\u0438\u0433\u0456\u043D\u0430\u043B</span>\n <span\n class=\"relative inline-flex h-5 w-9 items-center rounded-full border p-0.5 transition-colors\"\n [class.bg-emerald-500]=\"isOriginalVisible()\"\n [class.bg-white\\/15]=\"!isOriginalVisible()\"\n [class.border-emerald-200]=\"isOriginalVisible()\"\n [class.border-white\\/45]=\"!isOriginalVisible()\"\n [class.ring-2]=\"isOriginalVisible()\"\n [class.ring-emerald-300\\/70]=\"isOriginalVisible()\">\n <span\n class=\"h-4 w-4 rounded-full bg-white shadow-sm transition-transform duration-200\"\n [class.translate-x-4]=\"isOriginalVisible()\">\n </span>\n </span>\n </button>\n <a\n class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl transition hover:bg-white/10\"\n [href]=\"getOriginalUrl(currentUrl)\"\n download\n aria-label=\"\u0421\u043A\u0430\u0447\u0430\u0442\u0438 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B \u0444\u043E\u0442\u043E\">\n <lucide-icon [img]=\"downloadIcon\" [size]=\"19\" [strokeWidth]=\"2.25\"></lucide-icon>\n </a>\n </div>\n }\n </div>\n\n @if (urls().length > 1) {\n <div class=\"flex w-full flex-col items-center gap-3 pb-1 md:pb-2\">\n <div class=\"flex w-full max-w-[92vw] flex-nowrap justify-start gap-2 overflow-x-auto overflow-y-hidden overscroll-x-contain px-2 py-3 md:max-w-[80vw]\">\n @for (url of urls(); track url; let idx = $index) {\n <button\n #thumbnailButton\n type=\"button\"\n class=\"h-14 w-14 shrink-0 overflow-hidden rounded-xl border-2 border-transparent bg-white p-1 transition-transform duration-200\"\n [class.border-slate-900]=\"idx === currentIndex()\"\n [class.mx-2]=\"idx === currentIndex()\"\n [style.transform]=\"idx === currentIndex() ? 'scale(1.4)' : 'scale(1)'\"\n [class.origin-center]=\"idx === currentIndex()\"\n [class.relative]=\"idx === currentIndex()\"\n [class.z-10]=\"idx === currentIndex()\"\n [attr.aria-current]=\"idx === currentIndex() ? 'true' : null\"\n [attr.aria-label]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n (click)=\"selectImage(idx, $event)\">\n <img class=\"block aspect-square w-full rounded-lg object-contain\" [src]=\"getThumbnailUrl(url)\" [attr.alt]=\"'\u041C\u0456\u043D\u0456\u0430\u0442\u044E\u0440\u0430 ' + (idx + 1)\" loading=\"lazy\" decoding=\"async\">\n </button>\n }\n </div>\n <div class=\"rounded-full bg-white/95 px-3 py-1.5 text-xs font-semibold text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.2)]\">\n {{ currentIndex() + 1 }} / {{ urls().length }}\n </div>\n </div>\n }\n </div>\n</div>\n" }]
489
+ args: [{ selector: 'app-images-viewer', standalone: true, imports: [CommonModule, LucideDynamicIcon], template: "<div class=\"fixed inset-0 z-[2300] flex items-center justify-center bg-black/80 p-3 md:p-4\" role=\"dialog\" aria-modal=\"true\" aria-label=\"\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0444\u043E\u0442\u043E\">\n <button type=\"button\" class=\"absolute inset-0\" aria-label=\"\u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\" (click)=\"closeViewer()\"></button>\n <div class=\"relative z-[1] flex h-full w-full max-w-[1500px] flex-col items-center justify-center gap-4\" (click)=\"$event.stopPropagation()\">\n <button\n type=\"button\"\n class=\"absolute right-2 top-2 z-20 inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white md:right-3 md:top-3\"\n aria-label=\"\u0417\u0430\u043A\u0440\u0438\u0442\u0438\"\n (click)=\"closeViewer()\">\n \u2715\n </button>\n\n <div\n class=\"relative flex min-h-0 w-full flex-1 items-center justify-center overflow-hidden rounded-[18px]\"\n (touchstart)=\"onTouchStart($event)\"\n (touchend)=\"onTouchEnd($event)\">\n <div class=\"h-full w-full overflow-hidden rounded-[18px]\">\n <div\n class=\"flex h-full w-full\"\n style=\"will-change: transform; backface-visibility: hidden;\"\n [style.transition]=\"imageViewerTransitionStyle\"\n [style.transform]=\"imageViewerTransform\">\n @for (url of urls(); track $index; let idx = $index) {\n <div class=\"flex h-full w-full min-w-full shrink-0 items-center justify-center overflow-hidden\" (wheel)=\"onWheel($event)\">\n @if (isPreloadIndex(idx)) {\n @if (idx === currentIndex() && isOriginalVisible() && originalPreviewUnavailable()) {\n <div class=\"max-w-md rounded-2xl bg-white/95 px-6 py-5 text-center text-sm text-slate-700 shadow-xl\">\n <p class=\"font-semibold text-slate-900\">\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u0443 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439</p>\n <p class=\"mt-1\">\u0426\u0435\u0439 \u0444\u0430\u0439\u043B \u043C\u043E\u0436\u043D\u0430 \u043B\u0438\u0448\u0435 \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438.</p>\n </div>\n } @else {\n @if (idx === currentIndex()) {\n <img\n #currentImage\n [src]=\"getImageUrl(url, idx)\"\n [attr.alt]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n loading=\"eager\"\n decoding=\"async\"\n (load)=\"onImageLoad()\"\n (error)=\"onImageError(idx)\"\n (dblclick)=\"toggleZoom()\"\n class=\"block max-h-[74vh] max-w-[96vw] object-contain md:max-h-[78vh]\">\n } @else {\n <img\n [src]=\"getImageUrl(url, idx)\"\n [attr.alt]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n loading=\"lazy\"\n decoding=\"async\"\n (error)=\"onImageError(idx)\"\n class=\"block max-h-[74vh] max-w-[96vw] object-contain md:max-h-[78vh]\">\n }\n }\n }\n </div>\n }\n </div>\n </div>\n\n @if (urls().length > 1) {\n <button type=\"button\" class=\"absolute left-2 top-1/2 z-10 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full md:left-3\" aria-label=\"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0454 \u0444\u043E\u0442\u043E\" (click)=\"showPreviousImage()\">\n <span class=\"inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white\">\u2039</span>\n </button>\n <button type=\"button\" class=\"absolute right-2 top-1/2 z-10 inline-flex h-11 w-11 -translate-y-1/2 items-center justify-center rounded-full md:right-3\" aria-label=\"\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0435 \u0444\u043E\u0442\u043E\" (click)=\"showNextImage()\">\n <span class=\"inline-flex h-11 w-11 items-center justify-center rounded-full bg-white/90 text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.22)] transition hover:bg-white\">\u203A</span>\n </button>\n }\n\n @if (currentUrl) {\n <div class=\"absolute bottom-3 right-3 z-20 inline-flex max-w-[calc(100%-1.5rem)] items-center gap-1.5 rounded-2xl bg-black/55 p-1.5 text-white shadow-[0_12px_28px_rgba(15,23,42,0.24)] backdrop-blur-md md:bottom-4 md:right-4\">\n <button type=\"button\" class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl text-lg transition hover:bg-white/10\" aria-label=\"\u0417\u0431\u0456\u043B\u044C\u0448\u0438\u0442\u0438 \u0444\u043E\u0442\u043E\" (click)=\"zoomIn()\">+</button>\n <button type=\"button\" class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl text-lg transition hover:bg-white/10\" aria-label=\"\u0417\u043C\u0435\u043D\u0448\u0438\u0442\u0438 \u0444\u043E\u0442\u043E\" (click)=\"zoomOut()\">\u2212</button>\n <button type=\"button\" class=\"inline-flex h-9 items-center justify-center rounded-xl px-2 text-xs font-semibold transition hover:bg-white/10\" aria-label=\"\u0421\u043A\u0438\u043D\u0443\u0442\u0438 \u043C\u0430\u0441\u0448\u0442\u0430\u0431\" (click)=\"resetZoom()\">100%</button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 items-center gap-2 rounded-xl px-2.5 text-xs font-semibold transition hover:bg-white/10\"\n [class.bg-emerald-500\\/20]=\"isOriginalVisible()\"\n [class.text-emerald-100]=\"isOriginalVisible()\"\n [attr.aria-pressed]=\"isOriginalVisible()\"\n aria-label=\"\u041F\u0435\u0440\u0435\u043C\u043A\u043D\u0443\u0442\u0438 \u043C\u0456\u0436 \u043F\u0440\u0435\u0432\u2019\u044E \u0442\u0430 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B\u043E\u043C\"\n (click)=\"toggleOriginal()\">\n <span>\u041E\u0440\u0438\u0433\u0456\u043D\u0430\u043B</span>\n <span\n class=\"relative inline-flex h-5 w-9 items-center rounded-full border p-0.5 transition-colors\"\n [class.bg-emerald-500]=\"isOriginalVisible()\"\n [class.bg-white\\/15]=\"!isOriginalVisible()\"\n [class.border-emerald-200]=\"isOriginalVisible()\"\n [class.border-white\\/45]=\"!isOriginalVisible()\"\n [class.ring-2]=\"isOriginalVisible()\"\n [class.ring-emerald-300\\/70]=\"isOriginalVisible()\">\n <span\n class=\"h-4 w-4 rounded-full bg-white shadow-sm transition-transform duration-200\"\n [class.translate-x-4]=\"isOriginalVisible()\">\n </span>\n </span>\n </button>\n <a\n class=\"inline-flex h-9 w-9 items-center justify-center rounded-xl transition hover:bg-white/10\"\n [href]=\"getOriginalUrl(currentUrl)\"\n download\n aria-label=\"\u0421\u043A\u0430\u0447\u0430\u0442\u0438 \u043E\u0440\u0438\u0433\u0456\u043D\u0430\u043B \u0444\u043E\u0442\u043E\">\n <svg [lucideIcon]=\"downloadIcon\" [size]=\"19\" [strokeWidth]=\"2.25\"></svg>\n </a>\n </div>\n }\n </div>\n\n @if (urls().length > 1) {\n <div class=\"flex w-full flex-col items-center gap-3 pb-1 md:pb-2\">\n <div class=\"flex w-full max-w-[92vw] flex-nowrap justify-start gap-2 overflow-x-auto overflow-y-hidden overscroll-x-contain px-2 py-3 md:max-w-[80vw]\">\n @for (url of urls(); track url; let idx = $index) {\n <button\n #thumbnailButton\n type=\"button\"\n class=\"h-14 w-14 shrink-0 overflow-hidden rounded-xl border-2 border-transparent bg-white p-1 transition-transform duration-200\"\n [class.border-slate-900]=\"idx === currentIndex()\"\n [class.mx-2]=\"idx === currentIndex()\"\n [style.transform]=\"idx === currentIndex() ? 'scale(1.4)' : 'scale(1)'\"\n [class.origin-center]=\"idx === currentIndex()\"\n [class.relative]=\"idx === currentIndex()\"\n [class.z-10]=\"idx === currentIndex()\"\n [attr.aria-current]=\"idx === currentIndex() ? 'true' : null\"\n [attr.aria-label]=\"'\u0424\u043E\u0442\u043E ' + (idx + 1)\"\n (click)=\"selectImage(idx, $event)\">\n <img class=\"block aspect-square w-full rounded-lg object-contain\" [src]=\"getThumbnailUrl(url)\" [attr.alt]=\"'\u041C\u0456\u043D\u0456\u0430\u0442\u044E\u0440\u0430 ' + (idx + 1)\" loading=\"lazy\" decoding=\"async\">\n </button>\n }\n </div>\n <div class=\"rounded-full bg-white/95 px-3 py-1.5 text-xs font-semibold text-slate-900 shadow-[0_12px_28px_rgba(15,23,42,0.2)]\">\n {{ currentIndex() + 1 }} / {{ urls().length }}\n </div>\n </div>\n }\n </div>\n</div>\n" }]
491
490
  }], ctorParameters: () => [], propDecorators: { urls: [{ type: i0.Input, args: [{ isSignal: true, alias: "urls", required: false }] }], initialIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialIndex", required: false }] }], currentImage: [{ type: i0.ViewChild, args: ['currentImage', { isSignal: true }] }], thumbnailButtons: [{ type: i0.ViewChildren, args: ['thumbnailButton', { isSignal: true }] }], closed: [{ type: i0.Output, args: ["closed"] }], onEscape: [{
492
491
  type: HostListener,
493
492
  args: ['document:keydown.escape']
@@ -611,10 +610,10 @@ class DetailsGridComponent {
611
610
  ? { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }
612
611
  : { day: '2-digit', month: '2-digit', year: 'numeric' }).format(date);
613
612
  }
614
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DetailsGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
615
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DetailsGridComponent, isStandalone: true, selector: "app-details-grid", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"grid gap-4\" [class.grid-cols-1]=\"!hasExplicitColumns()\" [class.sm:grid-cols-3]=\"!hasExplicitColumns()\" [class.sm:grid-cols-12]=\"hasExplicitColumns()\">\n @for (field of displayFields(); track $index) {\n <div class=\"rounded-2xl border border-slate-100 bg-slate-200 p-4\" [ngClass]=\"getFieldColumnClass(field)\" [class.flex]=\"field.type === 'image'\" [class.flex-col]=\"field.type === 'image'\" [class.min-h-64]=\"field.type === 'image'\">\n <p class=\"text-xs uppercase tracking-[0.18em] text-slate-500\">{{ field.label }}</p>\n @if (field.type === 'image') {\n @if (field.imageSrc) {\n <button type=\"button\" class=\"mt-2 block flex-1 cursor-zoom-in overflow-hidden rounded-xl border border-slate-200 bg-white\" [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 ' + field.label\" (click)=\"openViewer(field.imageSrc)\">\n <img [src]=\"field.imageSrc\" [alt]=\"field.label\" class=\"h-full w-full object-cover\" />\n </button>\n } @else {\n <p class=\"mt-2 text-base font-semibold text-slate-900\">-</p>\n }\n } @else {\n <p class=\"mt-2 text-base font-semibold text-slate-900\">{{ field.displayValue ?? '-' }}</p>\n }\n </div>\n }\n</div>\n\n@if (selectedImageSrc(); as imageSrc) {\n <app-images-viewer [urls]=\"[imageSrc]\" (closed)=\"closeViewer()\" />\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ImagesViewerComponent, selector: "app-images-viewer", inputs: ["urls", "initialIndex"], outputs: ["closed"] }] });
613
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DetailsGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
614
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: DetailsGridComponent, isStandalone: true, selector: "app-details-grid", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"grid gap-4\" [class.grid-cols-1]=\"!hasExplicitColumns()\" [class.sm:grid-cols-3]=\"!hasExplicitColumns()\" [class.sm:grid-cols-12]=\"hasExplicitColumns()\">\n @for (field of displayFields(); track $index) {\n <div class=\"rounded-2xl border border-slate-100 bg-slate-200 p-4\" [ngClass]=\"getFieldColumnClass(field)\" [class.flex]=\"field.type === 'image'\" [class.flex-col]=\"field.type === 'image'\" [class.min-h-64]=\"field.type === 'image'\">\n <p class=\"text-xs uppercase tracking-[0.18em] text-slate-500\">{{ field.label }}</p>\n @if (field.type === 'image') {\n @if (field.imageSrc) {\n <button type=\"button\" class=\"mt-2 block flex-1 cursor-zoom-in overflow-hidden rounded-xl border border-slate-200 bg-white\" [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 ' + field.label\" (click)=\"openViewer(field.imageSrc)\">\n <img [src]=\"field.imageSrc\" [alt]=\"field.label\" class=\"h-full w-full object-cover\" />\n </button>\n } @else {\n <p class=\"mt-2 text-base font-semibold text-slate-900\">-</p>\n }\n } @else {\n <p class=\"mt-2 text-base font-semibold text-slate-900\">{{ field.displayValue ?? '-' }}</p>\n }\n </div>\n }\n</div>\n\n@if (selectedImageSrc(); as imageSrc) {\n <app-images-viewer [urls]=\"[imageSrc]\" (closed)=\"closeViewer()\" />\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ImagesViewerComponent, selector: "app-images-viewer", inputs: ["urls", "initialIndex"], outputs: ["closed"] }] });
616
615
  }
617
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DetailsGridComponent, decorators: [{
616
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DetailsGridComponent, decorators: [{
618
617
  type: Component,
619
618
  args: [{ selector: 'app-details-grid', standalone: true, imports: [CommonModule, ImagesViewerComponent], template: "<div class=\"grid gap-4\" [class.grid-cols-1]=\"!hasExplicitColumns()\" [class.sm:grid-cols-3]=\"!hasExplicitColumns()\" [class.sm:grid-cols-12]=\"hasExplicitColumns()\">\n @for (field of displayFields(); track $index) {\n <div class=\"rounded-2xl border border-slate-100 bg-slate-200 p-4\" [ngClass]=\"getFieldColumnClass(field)\" [class.flex]=\"field.type === 'image'\" [class.flex-col]=\"field.type === 'image'\" [class.min-h-64]=\"field.type === 'image'\">\n <p class=\"text-xs uppercase tracking-[0.18em] text-slate-500\">{{ field.label }}</p>\n @if (field.type === 'image') {\n @if (field.imageSrc) {\n <button type=\"button\" class=\"mt-2 block flex-1 cursor-zoom-in overflow-hidden rounded-xl border border-slate-200 bg-white\" [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 ' + field.label\" (click)=\"openViewer(field.imageSrc)\">\n <img [src]=\"field.imageSrc\" [alt]=\"field.label\" class=\"h-full w-full object-cover\" />\n </button>\n } @else {\n <p class=\"mt-2 text-base font-semibold text-slate-900\">-</p>\n }\n } @else {\n <p class=\"mt-2 text-base font-semibold text-slate-900\">{{ field.displayValue ?? '-' }}</p>\n }\n </div>\n }\n</div>\n\n@if (selectedImageSrc(); as imageSrc) {\n <app-images-viewer [urls]=\"[imageSrc]\" (closed)=\"closeViewer()\" />\n}\n" }]
620
619
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
@@ -659,10 +658,10 @@ class ImagesComponent {
659
658
  .map((item) => String(item || '').trim())
660
659
  .filter(Boolean)));
661
660
  }
662
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: ImagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
663
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: ImagesComponent, isStandalone: true, selector: "app-images", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (resolvedImageUrls().length === 0) {\n <p class=\"text-sm text-slate-500\">\u0424\u043E\u0442\u043E \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0456</p>\n} @else {\n <div\n class=\"grid gap-3 lg:h-[400px] lg:max-h-[400px]\"\n [ngClass]=\"resolvedImageUrls().length === 1 ? 'grid-cols-1' : 'grid-cols-1 lg:grid-cols-2'\"\n >\n @let previewUrls = resolvedImagePreviewUrls();\n <button\n type=\"button\"\n class=\"group relative block h-full min-h-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 text-left\"\n [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0444\u043E\u0442\u043E 1'\"\n (click)=\"openViewer(0)\"\n >\n <img\n [src]=\"previewUrls[0]\"\n [alt]=\"'\u0424\u043E\u0442\u043E 1'\"\n loading=\"lazy\"\n decoding=\"async\"\n class=\"h-56 w-full object-cover transition duration-200 group-hover:scale-[1.02] lg:h-full\"\n [style.max-height.px]=\"resolvedImageMaxHeight()\"\n />\n </button>\n\n @if (previewUrls.length > 1) {\n <div class=\"grid grid-cols-2 grid-rows-2 gap-3 lg:h-full lg:min-h-0\">\n @for (image of previewUrls.slice(1, 5); track image; let i = $index) {\n <button\n type=\"button\"\n class=\"group relative block h-full min-h-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 text-left\"\n [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0444\u043E\u0442\u043E ' + (i + 2)\"\n (click)=\"openViewer(i + 1)\"\n >\n <img\n [src]=\"image\"\n [alt]=\"'\u0424\u043E\u0442\u043E ' + (i + 2)\"\n loading=\"lazy\"\n decoding=\"async\"\n class=\"h-28 w-full object-cover transition duration-200 group-hover:scale-[1.02] lg:h-full\"\n [style.max-height.px]=\"resolvedImageMaxHeight()\"\n />\n @if (i === 3 && resolvedImageUrls().length > 5) {\n <span class=\"absolute inset-0 flex items-center justify-center bg-slate-950/55 text-2xl font-semibold text-white transition group-hover:bg-slate-950/65\">\n +{{ resolvedImageUrls().length - 5 }}\n </span>\n }\n </button>\n }\n </div>\n }\n </div>\n\n @if (isViewerOpen()) {\n <app-images-viewer\n [urls]=\"resolvedImageUrls()\"\n [initialIndex]=\"viewerStartIndex()\"\n (closed)=\"closeViewer()\"\n ></app-images-viewer>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ImagesViewerComponent, selector: "app-images-viewer", inputs: ["urls", "initialIndex"], outputs: ["closed"] }] });
661
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: ImagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
662
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: ImagesComponent, isStandalone: true, selector: "app-images", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (resolvedImageUrls().length === 0) {\n <p class=\"text-sm text-slate-500\">\u0424\u043E\u0442\u043E \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0456</p>\n} @else {\n <div\n class=\"grid gap-3 lg:h-[400px] lg:max-h-[400px]\"\n [ngClass]=\"resolvedImageUrls().length === 1 ? 'grid-cols-1' : 'grid-cols-1 lg:grid-cols-2'\"\n >\n @let previewUrls = resolvedImagePreviewUrls();\n <button\n type=\"button\"\n class=\"group relative block h-full min-h-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 text-left\"\n [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0444\u043E\u0442\u043E 1'\"\n (click)=\"openViewer(0)\"\n >\n <img\n [src]=\"previewUrls[0]\"\n [alt]=\"'\u0424\u043E\u0442\u043E 1'\"\n loading=\"lazy\"\n decoding=\"async\"\n class=\"h-56 w-full object-cover transition duration-200 group-hover:scale-[1.02] lg:h-full\"\n [style.max-height.px]=\"resolvedImageMaxHeight()\"\n />\n </button>\n\n @if (previewUrls.length > 1) {\n <div class=\"grid grid-cols-2 grid-rows-2 gap-3 lg:h-full lg:min-h-0\">\n @for (image of previewUrls.slice(1, 5); track image; let i = $index) {\n <button\n type=\"button\"\n class=\"group relative block h-full min-h-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 text-left\"\n [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0444\u043E\u0442\u043E ' + (i + 2)\"\n (click)=\"openViewer(i + 1)\"\n >\n <img\n [src]=\"image\"\n [alt]=\"'\u0424\u043E\u0442\u043E ' + (i + 2)\"\n loading=\"lazy\"\n decoding=\"async\"\n class=\"h-28 w-full object-cover transition duration-200 group-hover:scale-[1.02] lg:h-full\"\n [style.max-height.px]=\"resolvedImageMaxHeight()\"\n />\n @if (i === 3 && resolvedImageUrls().length > 5) {\n <span class=\"absolute inset-0 flex items-center justify-center bg-slate-950/55 text-2xl font-semibold text-white transition group-hover:bg-slate-950/65\">\n +{{ resolvedImageUrls().length - 5 }}\n </span>\n }\n </button>\n }\n </div>\n }\n </div>\n\n @if (isViewerOpen()) {\n <app-images-viewer\n [urls]=\"resolvedImageUrls()\"\n [initialIndex]=\"viewerStartIndex()\"\n (closed)=\"closeViewer()\"\n ></app-images-viewer>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ImagesViewerComponent, selector: "app-images-viewer", inputs: ["urls", "initialIndex"], outputs: ["closed"] }] });
664
663
  }
665
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: ImagesComponent, decorators: [{
664
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: ImagesComponent, decorators: [{
666
665
  type: Component,
667
666
  args: [{ selector: 'app-images', standalone: true, imports: [CommonModule, ImagesViewerComponent], template: "@if (resolvedImageUrls().length === 0) {\n <p class=\"text-sm text-slate-500\">\u0424\u043E\u0442\u043E \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0456</p>\n} @else {\n <div\n class=\"grid gap-3 lg:h-[400px] lg:max-h-[400px]\"\n [ngClass]=\"resolvedImageUrls().length === 1 ? 'grid-cols-1' : 'grid-cols-1 lg:grid-cols-2'\"\n >\n @let previewUrls = resolvedImagePreviewUrls();\n <button\n type=\"button\"\n class=\"group relative block h-full min-h-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 text-left\"\n [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0444\u043E\u0442\u043E 1'\"\n (click)=\"openViewer(0)\"\n >\n <img\n [src]=\"previewUrls[0]\"\n [alt]=\"'\u0424\u043E\u0442\u043E 1'\"\n loading=\"lazy\"\n decoding=\"async\"\n class=\"h-56 w-full object-cover transition duration-200 group-hover:scale-[1.02] lg:h-full\"\n [style.max-height.px]=\"resolvedImageMaxHeight()\"\n />\n </button>\n\n @if (previewUrls.length > 1) {\n <div class=\"grid grid-cols-2 grid-rows-2 gap-3 lg:h-full lg:min-h-0\">\n @for (image of previewUrls.slice(1, 5); track image; let i = $index) {\n <button\n type=\"button\"\n class=\"group relative block h-full min-h-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 text-left\"\n [attr.aria-label]=\"'\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0444\u043E\u0442\u043E ' + (i + 2)\"\n (click)=\"openViewer(i + 1)\"\n >\n <img\n [src]=\"image\"\n [alt]=\"'\u0424\u043E\u0442\u043E ' + (i + 2)\"\n loading=\"lazy\"\n decoding=\"async\"\n class=\"h-28 w-full object-cover transition duration-200 group-hover:scale-[1.02] lg:h-full\"\n [style.max-height.px]=\"resolvedImageMaxHeight()\"\n />\n @if (i === 3 && resolvedImageUrls().length > 5) {\n <span class=\"absolute inset-0 flex items-center justify-center bg-slate-950/55 text-2xl font-semibold text-white transition group-hover:bg-slate-950/65\">\n +{{ resolvedImageUrls().length - 5 }}\n </span>\n }\n </button>\n }\n </div>\n }\n </div>\n\n @if (isViewerOpen()) {\n <app-images-viewer\n [urls]=\"resolvedImageUrls()\"\n [initialIndex]=\"viewerStartIndex()\"\n (closed)=\"closeViewer()\"\n ></app-images-viewer>\n }\n}\n" }]
668
667
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
@@ -838,6 +837,15 @@ class TableComponent {
838
837
  }, { id: String(raw[0] || '') })
839
838
  : { ...(raw || {}) };
840
839
  row['id'] = String(row['id'] || '');
840
+ for (const column of columns) {
841
+ const type = String(column['type'] || '').toLowerCase();
842
+ if (type !== 'date' && type !== 'datetime')
843
+ continue;
844
+ const key = String(column['id'] || '').trim();
845
+ if (!key || row[key] == null || row[key] === '')
846
+ continue;
847
+ row[key] = this.formatDate(String(row[key]), type === 'datetime');
848
+ }
841
849
  if (!Array.isArray(row['actions'])) {
842
850
  const actions = configured.filter((action) => this.matchesRowCondition(action, row));
843
851
  const actionIds = new Set(actions.map((action) => String(action.id || '').trim()).filter(Boolean));
@@ -868,6 +876,14 @@ class TableComponent {
868
876
  return false;
869
877
  }
870
878
  }
879
+ formatDate(value, withTime) {
880
+ const date = new Date(value);
881
+ if (Number.isNaN(date.getTime()))
882
+ return value;
883
+ return new Intl.DateTimeFormat('uk-UA', withTime
884
+ ? { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }
885
+ : { day: '2-digit', month: '2-digit', year: 'numeric' }).format(date);
886
+ }
871
887
  tableName() {
872
888
  return String(this.config?.props?.['table'] || this.config?.props?.['entity'] || '').trim();
873
889
  }
@@ -913,10 +929,10 @@ class TableComponent {
913
929
  return this.resolveObject(value, row);
914
930
  return value;
915
931
  }
916
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
917
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: TableComponent, isStandalone: true, selector: "app-card-table", inputs: { config: "config", data: "data" }, usesOnChanges: true, ngImport: i0, template: "<section class=\"space-y-4\">\n @if (headerActions().length) {\n <div class=\"flex justify-end gap-2\">\n @for (action of headerActions(); track action.id) {\n <button type=\"button\" class=\"rounded-lg border border-slate-200 px-3 py-1.5 text-sm\" (click)=\"onHeaderAction(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n\n <app-ui-table\n class=\"flex min-h-0 max-h-[80dvh] flex-col overflow-hidden\"\n [data]=\"tableData()\"\n [columns]=\"columns()\"\n [pageSizeOptions]=\"pageSizeOptionsSignal()\"\n [isLoading]=\"isLoading()\"\n [disablePaging]=\"disablePaging\"\n (pageChange)=\"onPageChange($event)\"\n (actionClick)=\"onAction($event)\"\n (cellChange)=\"onCellChange($event)\"\n ></app-ui-table>\n</section>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiTableComponent, selector: "app-ui-table", inputs: ["pageSizeOptions", "columns", "isLoading", "data", "disablePaging", "rowClickable", "imageResolver"], outputs: ["pageChange", "rowClick", "actionClick", "cellChange"] }] });
932
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
933
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: TableComponent, isStandalone: true, selector: "app-card-table", inputs: { config: "config", data: "data" }, usesOnChanges: true, ngImport: i0, template: "<section class=\"space-y-4\">\n @if (headerActions().length) {\n <div class=\"flex justify-end gap-2\">\n @for (action of headerActions(); track action.id) {\n <button type=\"button\" class=\"rounded-lg border border-slate-200 px-3 py-1.5 text-sm\" (click)=\"onHeaderAction(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n\n <app-ui-table\n class=\"flex min-h-0 max-h-[80dvh] flex-col overflow-hidden\"\n [data]=\"tableData()\"\n [columns]=\"columns()\"\n [pageSizeOptions]=\"pageSizeOptionsSignal()\"\n [isLoading]=\"isLoading()\"\n [disablePaging]=\"disablePaging\"\n (pageChange)=\"onPageChange($event)\"\n (actionClick)=\"onAction($event)\"\n (cellChange)=\"onCellChange($event)\"\n ></app-ui-table>\n</section>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiTableComponent, selector: "app-ui-table", inputs: ["pageSizeOptions", "columns", "isLoading", "data", "disablePaging", "rowClickable", "imageResolver"], outputs: ["pageChange", "rowClick", "actionClick", "cellChange"] }] });
918
934
  }
919
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: TableComponent, decorators: [{
935
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: TableComponent, decorators: [{
920
936
  type: Component,
921
937
  args: [{ selector: 'app-card-table', standalone: true, imports: [CommonModule, UiTableComponent], template: "<section class=\"space-y-4\">\n @if (headerActions().length) {\n <div class=\"flex justify-end gap-2\">\n @for (action of headerActions(); track action.id) {\n <button type=\"button\" class=\"rounded-lg border border-slate-200 px-3 py-1.5 text-sm\" (click)=\"onHeaderAction(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n\n <app-ui-table\n class=\"flex min-h-0 max-h-[80dvh] flex-col overflow-hidden\"\n [data]=\"tableData()\"\n [columns]=\"columns()\"\n [pageSizeOptions]=\"pageSizeOptionsSignal()\"\n [isLoading]=\"isLoading()\"\n [disablePaging]=\"disablePaging\"\n (pageChange)=\"onPageChange($event)\"\n (actionClick)=\"onAction($event)\"\n (cellChange)=\"onCellChange($event)\"\n ></app-ui-table>\n</section>\n" }]
922
938
  }], ctorParameters: () => [], propDecorators: { config: [{
@@ -1005,10 +1021,10 @@ class UiCardPanelsLayoutComponent {
1005
1021
  return { tab };
1006
1022
  return found.resolveInputs(tab, this.data());
1007
1023
  }
1008
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiCardPanelsLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1009
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: UiCardPanelsLayoutComponent, isStandalone: true, selector: "app-ui-card-panels-layout", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (tabs().length) {\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-12\">\n @for (tab of tabs(); track tab.id) {\n <section\n [class.rounded-3xl]=\"!embedded()\"\n [class.border]=\"!embedded()\"\n [class.border-slate-200]=\"!embedded()\"\n [class.bg-white]=\"!embedded()\"\n [class.p-6]=\"!embedded()\"\n [class.min-w-0]=\"embedded()\"\n [ngClass]=\"getColSpanClass(tab)\"\n [attr.data-card-panel-id]=\"tab.id\"\n >\n @if (shouldShowPanelHeader(tab)) {\n <app-card-section-header\n [data]=\"data()\"\n [title]=\"tab.title\"\n [actions]=\"getVisibleActions(tab)\"\n ></app-card-section-header>\n }\n\n @if (getNestedCardConfig(tab); as nestedCard) {\n <app-card [tabs]=\"nestedCard.tabs\" [data]=\"data()\" [layout]=\"nestedCard.layout\"></app-card>\n } @else if (getNestedPanels(tab); as nestedPanels) {\n <app-card [tabs]=\"nestedPanels\" [data]=\"data()\" layout=\"panels\" [embedded]=\"true\"></app-card>\n } @else if (tab.component === 'detailsGrid') {\n <app-details-grid [config]=\"tab\" [data]=\"data()\"></app-details-grid>\n } @else if (tab.component === 'table') {\n <app-card-table [config]=\"tab\" [data]=\"data()\"></app-card-table>\n } @else if (tab.component === 'images') {\n <app-images [config]=\"tab\" [data]=\"data()\"></app-images>\n } @else if (tab.component === 'html') {\n <app-card-html-tab [html]=\"tab.html || ''\"></app-card-html-tab>\n } @else if (getRegisteredComponent(tab); as customComponent) {\n <ng-container *ngComponentOutlet=\"customComponent; inputs: getRegisteredInputs(tab)\"></ng-container>\n }\n </section>\n }\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "directive", type: i0.forwardRef(() => i1$1.NgClass), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(() => i1$1.NgComponentOutlet), selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: i0.forwardRef(() => CardComponent), selector: "app-card", inputs: ["tabs", "data", "layout", "embedded"] }, { kind: "component", type: i0.forwardRef(() => CardSectionHeaderComponent), selector: "app-card-section-header", inputs: ["variant", "title", "actions", "data"] }, { kind: "component", type: i0.forwardRef(() => CardHtmlTabComponent), selector: "app-card-html-tab", inputs: ["html"] }, { kind: "component", type: i0.forwardRef(() => DetailsGridComponent), selector: "app-details-grid", inputs: ["config", "data"] }, { kind: "component", type: i0.forwardRef(() => ImagesComponent), selector: "app-images", inputs: ["config", "data"] }, { kind: "component", type: i0.forwardRef(() => TableComponent), selector: "app-card-table", inputs: ["config", "data"] }] });
1024
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: UiCardPanelsLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1025
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: UiCardPanelsLayoutComponent, isStandalone: true, selector: "app-ui-card-panels-layout", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (tabs().length) {\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-12\">\n @for (tab of tabs(); track tab.id) {\n <section\n [class.rounded-3xl]=\"!embedded()\"\n [class.border]=\"!embedded()\"\n [class.border-slate-200]=\"!embedded()\"\n [class.bg-white]=\"!embedded()\"\n [class.p-6]=\"!embedded()\"\n [class.min-w-0]=\"embedded()\"\n [ngClass]=\"getColSpanClass(tab)\"\n [attr.data-card-panel-id]=\"tab.id\"\n >\n @if (shouldShowPanelHeader(tab)) {\n <app-card-section-header\n [data]=\"data()\"\n [title]=\"tab.title\"\n [actions]=\"getVisibleActions(tab)\"\n ></app-card-section-header>\n }\n\n @if (getNestedCardConfig(tab); as nestedCard) {\n <app-card [tabs]=\"nestedCard.tabs\" [data]=\"data()\" [layout]=\"nestedCard.layout\"></app-card>\n } @else if (getNestedPanels(tab); as nestedPanels) {\n <app-card [tabs]=\"nestedPanels\" [data]=\"data()\" layout=\"panels\" [embedded]=\"true\"></app-card>\n } @else if (tab.component === 'detailsGrid') {\n <app-details-grid [config]=\"tab\" [data]=\"data()\"></app-details-grid>\n } @else if (tab.component === 'table') {\n <app-card-table [config]=\"tab\" [data]=\"data()\"></app-card-table>\n } @else if (tab.component === 'images') {\n <app-images [config]=\"tab\" [data]=\"data()\"></app-images>\n } @else if (tab.component === 'html') {\n <app-card-html-tab [html]=\"tab.html || ''\"></app-card-html-tab>\n } @else if (getRegisteredComponent(tab); as customComponent) {\n <ng-container *ngComponentOutlet=\"customComponent; inputs: getRegisteredInputs(tab)\"></ng-container>\n }\n </section>\n }\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "directive", type: i0.forwardRef(() => i1.NgClass), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(() => i1.NgComponentOutlet), selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: i0.forwardRef(() => CardComponent), selector: "app-card", inputs: ["tabs", "data", "layout", "embedded"] }, { kind: "component", type: i0.forwardRef(() => CardSectionHeaderComponent), selector: "app-card-section-header", inputs: ["variant", "title", "actions", "data"] }, { kind: "component", type: i0.forwardRef(() => CardHtmlTabComponent), selector: "app-card-html-tab", inputs: ["html"] }, { kind: "component", type: i0.forwardRef(() => DetailsGridComponent), selector: "app-details-grid", inputs: ["config", "data"] }, { kind: "component", type: i0.forwardRef(() => ImagesComponent), selector: "app-images", inputs: ["config", "data"] }, { kind: "component", type: i0.forwardRef(() => TableComponent), selector: "app-card-table", inputs: ["config", "data"] }] });
1010
1026
  }
1011
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiCardPanelsLayoutComponent, decorators: [{
1027
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: UiCardPanelsLayoutComponent, decorators: [{
1012
1028
  type: Component,
1013
1029
  args: [{ selector: 'app-ui-card-panels-layout', standalone: true, imports: [CommonModule, forwardRef(() => CardComponent), CardSectionHeaderComponent, CardHtmlTabComponent, DetailsGridComponent, ImagesComponent, TableComponent], template: "@if (tabs().length) {\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-12\">\n @for (tab of tabs(); track tab.id) {\n <section\n [class.rounded-3xl]=\"!embedded()\"\n [class.border]=\"!embedded()\"\n [class.border-slate-200]=\"!embedded()\"\n [class.bg-white]=\"!embedded()\"\n [class.p-6]=\"!embedded()\"\n [class.min-w-0]=\"embedded()\"\n [ngClass]=\"getColSpanClass(tab)\"\n [attr.data-card-panel-id]=\"tab.id\"\n >\n @if (shouldShowPanelHeader(tab)) {\n <app-card-section-header\n [data]=\"data()\"\n [title]=\"tab.title\"\n [actions]=\"getVisibleActions(tab)\"\n ></app-card-section-header>\n }\n\n @if (getNestedCardConfig(tab); as nestedCard) {\n <app-card [tabs]=\"nestedCard.tabs\" [data]=\"data()\" [layout]=\"nestedCard.layout\"></app-card>\n } @else if (getNestedPanels(tab); as nestedPanels) {\n <app-card [tabs]=\"nestedPanels\" [data]=\"data()\" layout=\"panels\" [embedded]=\"true\"></app-card>\n } @else if (tab.component === 'detailsGrid') {\n <app-details-grid [config]=\"tab\" [data]=\"data()\"></app-details-grid>\n } @else if (tab.component === 'table') {\n <app-card-table [config]=\"tab\" [data]=\"data()\"></app-card-table>\n } @else if (tab.component === 'images') {\n <app-images [config]=\"tab\" [data]=\"data()\"></app-images>\n } @else if (tab.component === 'html') {\n <app-card-html-tab [html]=\"tab.html || ''\"></app-card-html-tab>\n } @else if (getRegisteredComponent(tab); as customComponent) {\n <ng-container *ngComponentOutlet=\"customComponent; inputs: getRegisteredInputs(tab)\"></ng-container>\n }\n </section>\n }\n </div>\n}\n" }]
1014
1030
  }], propDecorators: { tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], embedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "embedded", required: false }] }] } });
@@ -1075,10 +1091,10 @@ class UiCardTabsLayoutComponent {
1075
1091
  return { tab };
1076
1092
  return found.resolveInputs(tab, this.data());
1077
1093
  }
1078
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiCardTabsLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1079
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: UiCardTabsLayoutComponent, isStandalone: true, selector: "app-ui-card-tabs-layout", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (tabs().length) {\n <section class=\"space-y-4\">\n <nav class=\"flex flex-wrap gap-2\" aria-label=\"Card tabs\">\n @for (tab of tabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"rounded-xl border px-4 py-2 text-sm font-medium transition\"\n [class.border-slate-900]=\"activeTab()?.id === tab.id\"\n [class.bg-slate-900]=\"activeTab()?.id === tab.id\"\n [class.text-white]=\"activeTab()?.id === tab.id\"\n [class.border-slate-200]=\"activeTab()?.id !== tab.id\"\n [class.bg-white]=\"activeTab()?.id !== tab.id\"\n [class.text-slate-700]=\"activeTab()?.id !== tab.id\"\n (click)=\"setActiveTab(tab.id)\"\n >\n {{ tab.title }}\n </button>\n }\n </nav>\n\n @if (activeTab(); as tab) {\n <section\n [attr.data-card-tab-id]=\"tab.id\"\n >\n @if (getVisibleActions(tab).length) {\n <app-card-section-header\n variant=\"tabs\"\n [data]=\"data()\"\n [actions]=\"getVisibleActions(tab)\"\n ></app-card-section-header>\n }\n\n @if (tab.tabs?.length) {\n <app-card [tabs]=\"tab.tabs || []\" [data]=\"data()\" [layout]=\"tab.layout || 'panels'\"></app-card>\n } @else if (tab.component === 'images') {\n <app-images\n [config]=\"tab\"\n [data]=\"data()\"\n ></app-images>\n } @else if (tab.component === 'detailsGrid') {\n <app-details-grid [config]=\"tab\" [data]=\"data()\"></app-details-grid>\n } @else if (tab.component === 'table') {\n <app-card-table [config]=\"tab\" [data]=\"data()\"></app-card-table>\n } @else if (tab.component === 'html') {\n <app-card-html-tab [html]=\"tab.html || ''\"></app-card-html-tab>\n } @else if (getRegisteredComponent(tab); as customComponent) {\n <ng-container *ngComponentOutlet=\"customComponent; inputs: getRegisteredInputs(tab)\"></ng-container>\n }\n </section>\n }\n </section>\n}\n", dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "directive", type: i0.forwardRef(() => i1$1.NgComponentOutlet), selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: i0.forwardRef(() => CardComponent), selector: "app-card", inputs: ["tabs", "data", "layout", "embedded"] }, { kind: "component", type: i0.forwardRef(() => CardSectionHeaderComponent), selector: "app-card-section-header", inputs: ["variant", "title", "actions", "data"] }, { kind: "component", type: i0.forwardRef(() => CardHtmlTabComponent), selector: "app-card-html-tab", inputs: ["html"] }, { kind: "component", type: i0.forwardRef(() => ImagesComponent), selector: "app-images", inputs: ["config", "data"] }, { kind: "component", type: i0.forwardRef(() => DetailsGridComponent), selector: "app-details-grid", inputs: ["config", "data"] }, { kind: "component", type: i0.forwardRef(() => TableComponent), selector: "app-card-table", inputs: ["config", "data"] }] });
1094
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: UiCardTabsLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1095
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: UiCardTabsLayoutComponent, isStandalone: true, selector: "app-ui-card-tabs-layout", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (tabs().length) {\n <section class=\"space-y-4\">\n <nav class=\"flex flex-wrap gap-2\" aria-label=\"Card tabs\">\n @for (tab of tabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"rounded-xl border px-4 py-2 text-sm font-medium transition\"\n [class.border-slate-900]=\"activeTab()?.id === tab.id\"\n [class.bg-slate-900]=\"activeTab()?.id === tab.id\"\n [class.text-white]=\"activeTab()?.id === tab.id\"\n [class.border-slate-200]=\"activeTab()?.id !== tab.id\"\n [class.bg-white]=\"activeTab()?.id !== tab.id\"\n [class.text-slate-700]=\"activeTab()?.id !== tab.id\"\n (click)=\"setActiveTab(tab.id)\"\n >\n {{ tab.title }}\n </button>\n }\n </nav>\n\n @if (activeTab(); as tab) {\n <section\n [attr.data-card-tab-id]=\"tab.id\"\n >\n @if (getVisibleActions(tab).length) {\n <app-card-section-header\n variant=\"tabs\"\n [data]=\"data()\"\n [actions]=\"getVisibleActions(tab)\"\n ></app-card-section-header>\n }\n\n @if (tab.tabs?.length) {\n <app-card [tabs]=\"tab.tabs || []\" [data]=\"data()\" [layout]=\"tab.layout || 'panels'\"></app-card>\n } @else if (tab.component === 'images') {\n <app-images\n [config]=\"tab\"\n [data]=\"data()\"\n ></app-images>\n } @else if (tab.component === 'detailsGrid') {\n <app-details-grid [config]=\"tab\" [data]=\"data()\"></app-details-grid>\n } @else if (tab.component === 'table') {\n <app-card-table [config]=\"tab\" [data]=\"data()\"></app-card-table>\n } @else if (tab.component === 'html') {\n <app-card-html-tab [html]=\"tab.html || ''\"></app-card-html-tab>\n } @else if (getRegisteredComponent(tab); as customComponent) {\n <ng-container *ngComponentOutlet=\"customComponent; inputs: getRegisteredInputs(tab)\"></ng-container>\n }\n </section>\n }\n </section>\n}\n", dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "directive", type: i0.forwardRef(() => i1.NgComponentOutlet), selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: i0.forwardRef(() => CardComponent), selector: "app-card", inputs: ["tabs", "data", "layout", "embedded"] }, { kind: "component", type: i0.forwardRef(() => CardSectionHeaderComponent), selector: "app-card-section-header", inputs: ["variant", "title", "actions", "data"] }, { kind: "component", type: i0.forwardRef(() => CardHtmlTabComponent), selector: "app-card-html-tab", inputs: ["html"] }, { kind: "component", type: i0.forwardRef(() => ImagesComponent), selector: "app-images", inputs: ["config", "data"] }, { kind: "component", type: i0.forwardRef(() => DetailsGridComponent), selector: "app-details-grid", inputs: ["config", "data"] }, { kind: "component", type: i0.forwardRef(() => TableComponent), selector: "app-card-table", inputs: ["config", "data"] }] });
1080
1096
  }
1081
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiCardTabsLayoutComponent, decorators: [{
1097
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: UiCardTabsLayoutComponent, decorators: [{
1082
1098
  type: Component,
1083
1099
  args: [{ selector: 'app-ui-card-tabs-layout', standalone: true, imports: [CommonModule, forwardRef(() => CardComponent), CardSectionHeaderComponent, CardHtmlTabComponent, ImagesComponent, DetailsGridComponent, TableComponent], template: "@if (tabs().length) {\n <section class=\"space-y-4\">\n <nav class=\"flex flex-wrap gap-2\" aria-label=\"Card tabs\">\n @for (tab of tabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"rounded-xl border px-4 py-2 text-sm font-medium transition\"\n [class.border-slate-900]=\"activeTab()?.id === tab.id\"\n [class.bg-slate-900]=\"activeTab()?.id === tab.id\"\n [class.text-white]=\"activeTab()?.id === tab.id\"\n [class.border-slate-200]=\"activeTab()?.id !== tab.id\"\n [class.bg-white]=\"activeTab()?.id !== tab.id\"\n [class.text-slate-700]=\"activeTab()?.id !== tab.id\"\n (click)=\"setActiveTab(tab.id)\"\n >\n {{ tab.title }}\n </button>\n }\n </nav>\n\n @if (activeTab(); as tab) {\n <section\n [attr.data-card-tab-id]=\"tab.id\"\n >\n @if (getVisibleActions(tab).length) {\n <app-card-section-header\n variant=\"tabs\"\n [data]=\"data()\"\n [actions]=\"getVisibleActions(tab)\"\n ></app-card-section-header>\n }\n\n @if (tab.tabs?.length) {\n <app-card [tabs]=\"tab.tabs || []\" [data]=\"data()\" [layout]=\"tab.layout || 'panels'\"></app-card>\n } @else if (tab.component === 'images') {\n <app-images\n [config]=\"tab\"\n [data]=\"data()\"\n ></app-images>\n } @else if (tab.component === 'detailsGrid') {\n <app-details-grid [config]=\"tab\" [data]=\"data()\"></app-details-grid>\n } @else if (tab.component === 'table') {\n <app-card-table [config]=\"tab\" [data]=\"data()\"></app-card-table>\n } @else if (tab.component === 'html') {\n <app-card-html-tab [html]=\"tab.html || ''\"></app-card-html-tab>\n } @else if (getRegisteredComponent(tab); as customComponent) {\n <ng-container *ngComponentOutlet=\"customComponent; inputs: getRegisteredInputs(tab)\"></ng-container>\n }\n </section>\n }\n </section>\n}\n" }]
1084
1100
  }], propDecorators: { tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
@@ -1088,10 +1104,10 @@ class CardComponent {
1088
1104
  data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
1089
1105
  layout = input('panels', ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
1090
1106
  embedded = input(false, ...(ngDevMode ? [{ debugName: "embedded" }] : /* istanbul ignore next */ []));
1091
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1092
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CardComponent, isStandalone: true, selector: "app-card", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (layout() === 'panels') {\n <app-ui-card-panels-layout\n [tabs]=\"tabs()\"\n [data]=\"data()\"\n [embedded]=\"embedded()\"\n ></app-ui-card-panels-layout>\n} @else {\n <app-ui-card-tabs-layout\n [tabs]=\"tabs()\"\n [data]=\"data()\"\n ></app-ui-card-tabs-layout>\n}\n", dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "component", type: i0.forwardRef(() => UiCardTabsLayoutComponent), selector: "app-ui-card-tabs-layout", inputs: ["tabs", "data"] }, { kind: "component", type: i0.forwardRef(() => UiCardPanelsLayoutComponent), selector: "app-ui-card-panels-layout", inputs: ["tabs", "data", "embedded"] }] });
1107
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1108
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: CardComponent, isStandalone: true, selector: "app-card", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (layout() === 'panels') {\n <app-ui-card-panels-layout\n [tabs]=\"tabs()\"\n [data]=\"data()\"\n [embedded]=\"embedded()\"\n ></app-ui-card-panels-layout>\n} @else {\n <app-ui-card-tabs-layout\n [tabs]=\"tabs()\"\n [data]=\"data()\"\n ></app-ui-card-tabs-layout>\n}\n", dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "component", type: i0.forwardRef(() => UiCardTabsLayoutComponent), selector: "app-ui-card-tabs-layout", inputs: ["tabs", "data"] }, { kind: "component", type: i0.forwardRef(() => UiCardPanelsLayoutComponent), selector: "app-ui-card-panels-layout", inputs: ["tabs", "data", "embedded"] }] });
1093
1109
  }
1094
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardComponent, decorators: [{
1110
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardComponent, decorators: [{
1095
1111
  type: Component,
1096
1112
  args: [{ selector: 'app-card', standalone: true, imports: [CommonModule, forwardRef(() => UiCardTabsLayoutComponent), forwardRef(() => UiCardPanelsLayoutComponent)], template: "@if (layout() === 'panels') {\n <app-ui-card-panels-layout\n [tabs]=\"tabs()\"\n [data]=\"data()\"\n [embedded]=\"embedded()\"\n ></app-ui-card-panels-layout>\n} @else {\n <app-ui-card-tabs-layout\n [tabs]=\"tabs()\"\n [data]=\"data()\"\n ></app-ui-card-tabs-layout>\n}\n" }]
1097
1113
  }], propDecorators: { tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], embedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "embedded", required: false }] }] } });
@@ -1106,10 +1122,10 @@ class CardDictionaryService {
1106
1122
  getSuggestByName(name) {
1107
1123
  return this.http.get(apiUrl(this.baseUrl, `/api/suggest/${encodeURIComponent(name)}`));
1108
1124
  }
1109
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardDictionaryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1110
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardDictionaryService, providedIn: 'root' });
1125
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardDictionaryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1126
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardDictionaryService, providedIn: 'root' });
1111
1127
  }
1112
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardDictionaryService, decorators: [{
1128
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardDictionaryService, decorators: [{
1113
1129
  type: Injectable,
1114
1130
  args: [{ providedIn: 'root' }]
1115
1131
  }] });
@@ -1118,10 +1134,10 @@ class CardCurrentUserService {
1118
1134
  baseUrl = inject(UI_CARD_API_BASE_URL);
1119
1135
  user$ = this.http.get(apiUrl(this.baseUrl, '/api/users/me'), { withCredentials: true }).pipe(shareReplay(1));
1120
1136
  getCurrentUser() { return this.user$; }
1121
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardCurrentUserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1122
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardCurrentUserService, providedIn: 'root' });
1137
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardCurrentUserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1138
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardCurrentUserService, providedIn: 'root' });
1123
1139
  }
1124
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardCurrentUserService, decorators: [{
1140
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardCurrentUserService, decorators: [{
1125
1141
  type: Injectable,
1126
1142
  args: [{ providedIn: 'root' }]
1127
1143
  }] });
@@ -1130,10 +1146,10 @@ class CardImageService {
1130
1146
  getPhotoLink(id) {
1131
1147
  return id ? apiUrl(this.baseUrl, `/api/files/${encodeURIComponent(id)}/preview?scale=25`) : undefined;
1132
1148
  }
1133
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1134
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardImageService, providedIn: 'root' });
1149
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1150
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardImageService, providedIn: 'root' });
1135
1151
  }
1136
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CardImageService, decorators: [{
1152
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: CardImageService, decorators: [{
1137
1153
  type: Injectable,
1138
1154
  args: [{ providedIn: 'root' }]
1139
1155
  }] });
@@ -1171,10 +1187,10 @@ class UiEntityDocumentsService {
1171
1187
  resolveDownloadUrl(fileId) {
1172
1188
  return cardApiResourceUrl(this.baseUrl, `/api/files/${encodeURIComponent(fileId)}`);
1173
1189
  }
1174
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiEntityDocumentsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1175
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiEntityDocumentsService, providedIn: 'root' });
1190
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: UiEntityDocumentsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1191
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: UiEntityDocumentsService, providedIn: 'root' });
1176
1192
  }
1177
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: UiEntityDocumentsService, decorators: [{
1193
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: UiEntityDocumentsService, decorators: [{
1178
1194
  type: Injectable,
1179
1195
  args: [{ providedIn: 'root' }]
1180
1196
  }] });
@@ -1248,12 +1264,12 @@ class DocumentsUploadModalComponent {
1248
1264
  this.uploadFileInput.nativeElement.value = '';
1249
1265
  }
1250
1266
  }
1251
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DocumentsUploadModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1252
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DocumentsUploadModalComponent, isStandalone: true, selector: "app-documents-upload-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", saved: "saved" }, viewQueries: [{ propertyName: "uploadFileInput", first: true, predicate: ["uploadFileInput"], descendants: true }], ngImport: i0, template: "<core-modal\n title=\"\u0414\u043E\u0434\u0430\u0442\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n <div class=\"space-y-4\">\n <input-select\n [data]=\"'doc_type'\"\n name=\"uploadDocumentTypeId\"\n label=\"\u0422\u0438\u043F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\"\n hint=\"\u041D\u0435\u043E\u0431\u043E\u0432'\u044F\u0437\u043A\u043E\u0432\u043E\"\n [ngModel]=\"documentTypeId()\"\n (ngModelChange)=\"onDocumentTypeChange($event)\"\n placeholder=\"\u0422\u0438\u043F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\"\n [fullWidth]=\"true\"\n [searchable]=\"true\"\n ></input-select>\n\n <div class=\"space-y-2\">\n <label class=\"block text-sm font-medium text-slate-700\" for=\"document-files\">\u0424\u0430\u0439\u043B\u0438</label>\n <input\n #uploadFileInput\n id=\"document-files\"\n type=\"file\"\n class=\"block w-full rounded-xl border border-slate-200 bg-white px-3 py-2.5 text-sm text-slate-900 outline-none transition file:mr-3 file:rounded-lg file:border-0 file:bg-slate-900 file:px-3 file:py-2 file:text-sm file:font-medium file:text-white focus:border-slate-400 focus:ring-2 focus:ring-slate-200\"\n multiple\n (change)=\"onFilesSelected($event)\"\n />\n @if (fileNames().length) {\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-600\">\n @for (fileName of fileNames(); track fileName) {\n <div class=\"truncate\">{{ fileName }}</div>\n }\n </div>\n } @else {\n <p class=\"text-xs text-slate-500\">\u041C\u043E\u0436\u043D\u0430 \u043E\u0431\u0440\u0430\u0442\u0438 \u043E\u0434\u0438\u043D \u0430\u0431\u043E \u0434\u0435\u043A\u0456\u043B\u044C\u043A\u0430 \u0444\u0430\u0439\u043B\u0456\u0432.</p>\n }\n </div>\n </div>\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n <ui-button variant=\"ghost\" [disabled]=\"isUploading()\" (click)=\"close()\">\u0421\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438</ui-button>\n <ui-button variant=\"primary\" [disabled]=\"isUploading()\" (click)=\"submitUpload()\">\n {{ isUploading() ? '\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F...' : '\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438' }}\n </ui-button>\n </div>\n</core-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: UiModalComponent, selector: "core-modal", inputs: ["isOpen", "title", "size", "position", "closable", "closeOnBackdrop", "closeOnEscape"], outputs: ["closed"] }, { kind: "component", type: InputSelectComponent, selector: "input-select", inputs: ["label", "placeholder", "name", "data", "required", "fullWidth", "disabled", "multiple", "includeBlankOption", "blankOptionLabel", "emptyStateLabel", "searchable", "remoteSearch", "searchPlaceholder", "options", "error", "hint", "triggerClass", "panelClass"], outputs: ["valueChange", "searchChange"] }] });
1267
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DocumentsUploadModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1268
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: DocumentsUploadModalComponent, isStandalone: true, selector: "app-documents-upload-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", saved: "saved" }, viewQueries: [{ propertyName: "uploadFileInput", first: true, predicate: ["uploadFileInput"], descendants: true }], ngImport: i0, template: "<core-modal\n title=\"\u0414\u043E\u0434\u0430\u0442\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n <div class=\"space-y-4\">\n <input-select\n [data]=\"'doc_type'\"\n name=\"uploadDocumentTypeId\"\n label=\"\u0422\u0438\u043F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\"\n hint=\"\u041D\u0435\u043E\u0431\u043E\u0432'\u044F\u0437\u043A\u043E\u0432\u043E\"\n [ngModel]=\"documentTypeId()\"\n (ngModelChange)=\"onDocumentTypeChange($event)\"\n placeholder=\"\u0422\u0438\u043F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\"\n [searchable]=\"true\"\n ></input-select>\n\n <div class=\"space-y-2\">\n <label class=\"block text-sm font-medium text-slate-700\" for=\"document-files\">\u0424\u0430\u0439\u043B\u0438</label>\n <input\n #uploadFileInput\n id=\"document-files\"\n type=\"file\"\n class=\"block w-full rounded-xl border border-slate-200 bg-white px-3 py-2.5 text-sm text-slate-900 outline-none transition file:mr-3 file:rounded-lg file:border-0 file:bg-slate-900 file:px-3 file:py-2 file:text-sm file:font-medium file:text-white focus:border-slate-400 focus:ring-2 focus:ring-slate-200\"\n multiple\n (change)=\"onFilesSelected($event)\"\n />\n @if (fileNames().length) {\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-600\">\n @for (fileName of fileNames(); track fileName) {\n <div class=\"truncate\">{{ fileName }}</div>\n }\n </div>\n } @else {\n <p class=\"text-xs text-slate-500\">\u041C\u043E\u0436\u043D\u0430 \u043E\u0431\u0440\u0430\u0442\u0438 \u043E\u0434\u0438\u043D \u0430\u0431\u043E \u0434\u0435\u043A\u0456\u043B\u044C\u043A\u0430 \u0444\u0430\u0439\u043B\u0456\u0432.</p>\n }\n </div>\n </div>\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n <ui-button variant=\"ghost\" [disabled]=\"isUploading()\" (click)=\"close()\">\u0421\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438</ui-button>\n <ui-button variant=\"primary\" [disabled]=\"isUploading()\" (click)=\"submitUpload()\">\n {{ isUploading() ? '\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F...' : '\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438' }}\n </ui-button>\n </div>\n</core-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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"] }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: UiModalComponent, selector: "core-modal", inputs: ["isOpen", "title", "size", "position", "closable", "closeOnBackdrop", "closeOnEscape"], outputs: ["closed"] }, { kind: "component", type: InputSelectComponent, selector: "input-select", inputs: ["label", "hint", "error", "placeholder", "name", "data", "dataParams", "required", "disabled", "multiple", "emptyStateLabel", "searchable", "options", "triggerClass", "panelClass"], outputs: ["valueChange", "searchChange"] }] });
1253
1269
  }
1254
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DocumentsUploadModalComponent, decorators: [{
1270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DocumentsUploadModalComponent, decorators: [{
1255
1271
  type: Component,
1256
- args: [{ selector: 'app-documents-upload-modal', standalone: true, imports: [CommonModule, FormsModule, LucideAngularModule, UiButtonComponent, UiModalComponent, InputSelectComponent], template: "<core-modal\n title=\"\u0414\u043E\u0434\u0430\u0442\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n <div class=\"space-y-4\">\n <input-select\n [data]=\"'doc_type'\"\n name=\"uploadDocumentTypeId\"\n label=\"\u0422\u0438\u043F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\"\n hint=\"\u041D\u0435\u043E\u0431\u043E\u0432'\u044F\u0437\u043A\u043E\u0432\u043E\"\n [ngModel]=\"documentTypeId()\"\n (ngModelChange)=\"onDocumentTypeChange($event)\"\n placeholder=\"\u0422\u0438\u043F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\"\n [fullWidth]=\"true\"\n [searchable]=\"true\"\n ></input-select>\n\n <div class=\"space-y-2\">\n <label class=\"block text-sm font-medium text-slate-700\" for=\"document-files\">\u0424\u0430\u0439\u043B\u0438</label>\n <input\n #uploadFileInput\n id=\"document-files\"\n type=\"file\"\n class=\"block w-full rounded-xl border border-slate-200 bg-white px-3 py-2.5 text-sm text-slate-900 outline-none transition file:mr-3 file:rounded-lg file:border-0 file:bg-slate-900 file:px-3 file:py-2 file:text-sm file:font-medium file:text-white focus:border-slate-400 focus:ring-2 focus:ring-slate-200\"\n multiple\n (change)=\"onFilesSelected($event)\"\n />\n @if (fileNames().length) {\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-600\">\n @for (fileName of fileNames(); track fileName) {\n <div class=\"truncate\">{{ fileName }}</div>\n }\n </div>\n } @else {\n <p class=\"text-xs text-slate-500\">\u041C\u043E\u0436\u043D\u0430 \u043E\u0431\u0440\u0430\u0442\u0438 \u043E\u0434\u0438\u043D \u0430\u0431\u043E \u0434\u0435\u043A\u0456\u043B\u044C\u043A\u0430 \u0444\u0430\u0439\u043B\u0456\u0432.</p>\n }\n </div>\n </div>\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n <ui-button variant=\"ghost\" [disabled]=\"isUploading()\" (click)=\"close()\">\u0421\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438</ui-button>\n <ui-button variant=\"primary\" [disabled]=\"isUploading()\" (click)=\"submitUpload()\">\n {{ isUploading() ? '\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F...' : '\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438' }}\n </ui-button>\n </div>\n</core-modal>\n" }]
1272
+ args: [{ selector: 'app-documents-upload-modal', standalone: true, imports: [CommonModule, FormsModule, LucideDynamicIcon, UiButtonComponent, UiModalComponent, InputSelectComponent], template: "<core-modal\n title=\"\u0414\u043E\u0434\u0430\u0442\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n <div class=\"space-y-4\">\n <input-select\n [data]=\"'doc_type'\"\n name=\"uploadDocumentTypeId\"\n label=\"\u0422\u0438\u043F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\"\n hint=\"\u041D\u0435\u043E\u0431\u043E\u0432'\u044F\u0437\u043A\u043E\u0432\u043E\"\n [ngModel]=\"documentTypeId()\"\n (ngModelChange)=\"onDocumentTypeChange($event)\"\n placeholder=\"\u0422\u0438\u043F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\"\n [searchable]=\"true\"\n ></input-select>\n\n <div class=\"space-y-2\">\n <label class=\"block text-sm font-medium text-slate-700\" for=\"document-files\">\u0424\u0430\u0439\u043B\u0438</label>\n <input\n #uploadFileInput\n id=\"document-files\"\n type=\"file\"\n class=\"block w-full rounded-xl border border-slate-200 bg-white px-3 py-2.5 text-sm text-slate-900 outline-none transition file:mr-3 file:rounded-lg file:border-0 file:bg-slate-900 file:px-3 file:py-2 file:text-sm file:font-medium file:text-white focus:border-slate-400 focus:ring-2 focus:ring-slate-200\"\n multiple\n (change)=\"onFilesSelected($event)\"\n />\n @if (fileNames().length) {\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 px-3 py-2 text-sm text-slate-600\">\n @for (fileName of fileNames(); track fileName) {\n <div class=\"truncate\">{{ fileName }}</div>\n }\n </div>\n } @else {\n <p class=\"text-xs text-slate-500\">\u041C\u043E\u0436\u043D\u0430 \u043E\u0431\u0440\u0430\u0442\u0438 \u043E\u0434\u0438\u043D \u0430\u0431\u043E \u0434\u0435\u043A\u0456\u043B\u044C\u043A\u0430 \u0444\u0430\u0439\u043B\u0456\u0432.</p>\n }\n </div>\n </div>\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n <ui-button variant=\"ghost\" [disabled]=\"isUploading()\" (click)=\"close()\">\u0421\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438</ui-button>\n <ui-button variant=\"primary\" [disabled]=\"isUploading()\" (click)=\"submitUpload()\">\n {{ isUploading() ? '\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F...' : '\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438' }}\n </ui-button>\n </div>\n</core-modal>\n" }]
1257
1273
  }], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], entity: [{ type: i0.Input, args: [{ isSignal: true, alias: "entity", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], saved: [{ type: i0.Output, args: ["saved"] }], uploadFileInput: [{
1258
1274
  type: ViewChild,
1259
1275
  args: ['uploadFileInput']
@@ -1297,10 +1313,10 @@ class DocumentsTextModalComponent {
1297
1313
  .replace(/"/g, '&quot;')
1298
1314
  .replace(/'/g, '&#39;');
1299
1315
  }
1300
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DocumentsTextModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1301
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DocumentsTextModalComponent, isStandalone: true, selector: "app-documents-text-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, document: { classPropertyName: "document", publicName: "document", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", recognizeRequested: "recognizeRequested" }, ngImport: i0, template: "<core-modal\n title=\"\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u043D\u0456 \u0434\u0430\u043D\u0456\"\n size=\"lg\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n <div class=\"space-y-3\">\n @if (hasDocumentHtml()) {\n <div\n class=\"max-h-[32rem] overflow-auto rounded-xl border border-slate-200 bg-slate-50 px-4 py-4 text-sm text-slate-900\"\n [innerHTML]=\"getDocumentHtml()\"\n ></div>\n } @else {\n <div class=\"rounded-xl border border-dashed border-slate-200 bg-slate-50 px-4 py-6 text-sm text-slate-500\">\n \u0414\u0430\u043D\u0456 \u0449\u0435 \u043D\u0435 \u0440\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u043D\u0456. \u041D\u0430\u0442\u0438\u0441\u043D\u0438 \u201C\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0434\u0430\u043D\u0456\u201D.\n </div>\n }\n </div>\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n @if (isImage()) {\n <ui-button variant=\"secondary\" (click)=\"requestRecognize()\">\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0449\u0435 \u0440\u0430\u0437</ui-button>\n }\n <ui-button variant=\"primary\" (click)=\"close()\">\u0417\u0430\u043A\u0440\u0438\u0442\u0438</ui-button>\n </div>\n</core-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: UiModalComponent, selector: "core-modal", inputs: ["isOpen", "title", "size", "position", "closable", "closeOnBackdrop", "closeOnEscape"], outputs: ["closed"] }] });
1316
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DocumentsTextModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1317
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: DocumentsTextModalComponent, isStandalone: true, selector: "app-documents-text-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, document: { classPropertyName: "document", publicName: "document", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", recognizeRequested: "recognizeRequested" }, ngImport: i0, template: "<core-modal\n title=\"\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u043D\u0456 \u0434\u0430\u043D\u0456\"\n size=\"lg\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n <div class=\"space-y-3\">\n @if (hasDocumentHtml()) {\n <div\n class=\"max-h-[32rem] overflow-auto rounded-xl border border-slate-200 bg-slate-50 px-4 py-4 text-sm text-slate-900\"\n [innerHTML]=\"getDocumentHtml()\"\n ></div>\n } @else {\n <div class=\"rounded-xl border border-dashed border-slate-200 bg-slate-50 px-4 py-6 text-sm text-slate-500\">\n \u0414\u0430\u043D\u0456 \u0449\u0435 \u043D\u0435 \u0440\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u043D\u0456. \u041D\u0430\u0442\u0438\u0441\u043D\u0438 \u201C\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0434\u0430\u043D\u0456\u201D.\n </div>\n }\n </div>\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n @if (isImage()) {\n <ui-button variant=\"secondary\" (click)=\"requestRecognize()\">\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0449\u0435 \u0440\u0430\u0437</ui-button>\n }\n <ui-button variant=\"primary\" (click)=\"close()\">\u0417\u0430\u043A\u0440\u0438\u0442\u0438</ui-button>\n </div>\n</core-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: UiModalComponent, selector: "core-modal", inputs: ["isOpen", "title", "size", "position", "closable", "closeOnBackdrop", "closeOnEscape"], outputs: ["closed"] }] });
1302
1318
  }
1303
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DocumentsTextModalComponent, decorators: [{
1319
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DocumentsTextModalComponent, decorators: [{
1304
1320
  type: Component,
1305
1321
  args: [{ selector: 'app-documents-text-modal', standalone: true, imports: [CommonModule, UiButtonComponent, UiModalComponent], template: "<core-modal\n title=\"\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u043D\u0456 \u0434\u0430\u043D\u0456\"\n size=\"lg\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n <div class=\"space-y-3\">\n @if (hasDocumentHtml()) {\n <div\n class=\"max-h-[32rem] overflow-auto rounded-xl border border-slate-200 bg-slate-50 px-4 py-4 text-sm text-slate-900\"\n [innerHTML]=\"getDocumentHtml()\"\n ></div>\n } @else {\n <div class=\"rounded-xl border border-dashed border-slate-200 bg-slate-50 px-4 py-6 text-sm text-slate-500\">\n \u0414\u0430\u043D\u0456 \u0449\u0435 \u043D\u0435 \u0440\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u043D\u0456. \u041D\u0430\u0442\u0438\u0441\u043D\u0438 \u201C\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0434\u0430\u043D\u0456\u201D.\n </div>\n }\n </div>\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n @if (isImage()) {\n <ui-button variant=\"secondary\" (click)=\"requestRecognize()\">\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0449\u0435 \u0440\u0430\u0437</ui-button>\n }\n <ui-button variant=\"primary\" (click)=\"close()\">\u0417\u0430\u043A\u0440\u0438\u0442\u0438</ui-button>\n </div>\n</core-modal>\n" }]
1306
1322
  }], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], document: [{ type: i0.Input, args: [{ isSignal: true, alias: "document", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], recognizeRequested: [{ type: i0.Output, args: ["recognizeRequested"] }] } });
@@ -1316,10 +1332,10 @@ class DocumentsImagePreviewModalComponent {
1316
1332
  const match = String(url || '').match(/^(.*\/api\/files\/[^/?#]+)(?:\?.*)?$/i);
1317
1333
  return match ? `${match[1]}/preview?scale=25` : url;
1318
1334
  }
1319
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DocumentsImagePreviewModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1320
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DocumentsImagePreviewModalComponent, isStandalone: true, selector: "app-documents-image-preview-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, document: { classPropertyName: "document", publicName: "document", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "<core-modal\n [title]=\"document()?.name || '\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430'\"\n size=\"lg\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n @if (document()) {\n <div class=\"overflow-hidden rounded-2xl bg-slate-100\">\n <img\n [src]=\"getPreviewUrl(document()!.downloadUrl)\"\n [alt]=\"document()!.name || '\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442'\"\n decoding=\"async\"\n class=\"max-h-[75vh] w-full object-contain\"\n >\n </div>\n }\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n <ui-button variant=\"primary\" (click)=\"close()\">\u0417\u0430\u043A\u0440\u0438\u0442\u0438</ui-button>\n </div>\n</core-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: UiModalComponent, selector: "core-modal", inputs: ["isOpen", "title", "size", "position", "closable", "closeOnBackdrop", "closeOnEscape"], outputs: ["closed"] }] });
1335
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DocumentsImagePreviewModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1336
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: DocumentsImagePreviewModalComponent, isStandalone: true, selector: "app-documents-image-preview-modal", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, document: { classPropertyName: "document", publicName: "document", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "<core-modal\n [title]=\"document()?.name || '\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430'\"\n size=\"lg\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n @if (document()) {\n <div class=\"overflow-hidden rounded-2xl bg-slate-100\">\n <img\n [src]=\"getPreviewUrl(document()!.downloadUrl)\"\n [alt]=\"document()!.name || '\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442'\"\n decoding=\"async\"\n class=\"max-h-[75vh] w-full object-contain\"\n >\n </div>\n }\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n <ui-button variant=\"primary\" (click)=\"close()\">\u0417\u0430\u043A\u0440\u0438\u0442\u0438</ui-button>\n </div>\n</core-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: UiModalComponent, selector: "core-modal", inputs: ["isOpen", "title", "size", "position", "closable", "closeOnBackdrop", "closeOnEscape"], outputs: ["closed"] }] });
1321
1337
  }
1322
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DocumentsImagePreviewModalComponent, decorators: [{
1338
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DocumentsImagePreviewModalComponent, decorators: [{
1323
1339
  type: Component,
1324
1340
  args: [{ selector: 'app-documents-image-preview-modal', standalone: true, imports: [CommonModule, UiButtonComponent, UiModalComponent], template: "<core-modal\n [title]=\"document()?.name || '\u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430'\"\n size=\"lg\"\n [isOpen]=\"isOpen()\"\n (closed)=\"close()\"\n>\n @if (document()) {\n <div class=\"overflow-hidden rounded-2xl bg-slate-100\">\n <img\n [src]=\"getPreviewUrl(document()!.downloadUrl)\"\n [alt]=\"document()!.name || '\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442'\"\n decoding=\"async\"\n class=\"max-h-[75vh] w-full object-contain\"\n >\n </div>\n }\n\n <div slot=\"footer\" class=\"flex justify-end gap-2\">\n <ui-button variant=\"primary\" (click)=\"close()\">\u0417\u0430\u043A\u0440\u0438\u0442\u0438</ui-button>\n </div>\n</core-modal>\n" }]
1325
1341
  }], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], document: [{ type: i0.Input, args: [{ isSignal: true, alias: "document", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
@@ -1340,11 +1356,11 @@ class DocumentsComponent {
1340
1356
  textTarget = signal(null, ...(ngDevMode ? [{ debugName: "textTarget" }] : /* istanbul ignore next */ []));
1341
1357
  imagePreviewTarget = signal(null, ...(ngDevMode ? [{ debugName: "imagePreviewTarget" }] : /* istanbul ignore next */ []));
1342
1358
  deletingDocumentId = signal(null, ...(ngDevMode ? [{ debugName: "deletingDocumentId" }] : /* istanbul ignore next */ []));
1343
- eyeIcon = Eye;
1344
- fileIcon = FileText;
1345
- plusIcon = Plus;
1346
- sparkleIcon = Sparkles;
1347
- deleteIcon = Trash;
1359
+ eyeIcon = LucideEye;
1360
+ fileIcon = LucideFileText;
1361
+ plusIcon = LucidePlus;
1362
+ sparkleIcon = LucideSparkles;
1363
+ deleteIcon = LucideTrash;
1348
1364
  isAdmin = toSignal(inject(CardCurrentUserService).getCurrentUser().pipe(map$1((user) => String(user.role || '').trim().toUpperCase() === 'ADMIN')), { initialValue: false });
1349
1365
  documentsService = inject(UiEntityDocumentsService);
1350
1366
  dictionaryService = inject(CardDictionaryService);
@@ -1596,19 +1612,19 @@ class DocumentsComponent {
1596
1612
  }))
1597
1613
  .subscribe();
1598
1614
  }
1599
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DocumentsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1600
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: DocumentsComponent, isStandalone: true, selector: "app-documents", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"space-y-4\">\n <div>\n @if (isLoading()) {\n <div class=\"rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500\">\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432...\n </div>\n } @else if (documents().length === 0) {\n <div class=\"rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500\">\n \u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0438 \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0456\n </div>\n } @else {\n <div class=\"grid gap-3\">\n @for (document of documents(); track trackDocument($index, document)) {\n <article class=\"flex flex-col gap-4 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm sm:flex-row sm:items-center sm:justify-between\">\n @if (isImage(document)) {\n <button\n type=\"button\"\n class=\"block shrink-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 transition hover:border-slate-300 hover:bg-slate-100 h-28 w-40\"\n (click)=\"openImagePreview(document)\"\n >\n <img [src]=\"getImagePreviewUrl(document)\" [alt]=\"document.name || '\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442'\" loading=\"lazy\" decoding=\"async\" class=\"h-full w-full object-cover\">\n </button>\n } @else {\n <a\n class=\"block shrink-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 transition hover:border-slate-300 hover:bg-slate-100\"\n [href]=\"document.downloadUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [class.h-28]=\"isPdf(document)\"\n [class.w-40]=\"isPdf(document)\"\n [class.h-20]=\"!isPdf(document)\"\n [class.w-24]=\"!isPdf(document)\"\n >\n @if (isPdf(document)) {\n <div class=\"flex h-full w-full flex-col items-center justify-center gap-2 px-3 py-4 text-slate-700\">\n <div class=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-white text-slate-900 shadow-sm\">\n <lucide-icon [img]=\"fileIcon\"></lucide-icon>\n </div>\n <span class=\"text-xs font-semibold uppercase tracking-[0.18em] text-slate-600\">PDF</span>\n </div>\n } @else {\n <div class=\"flex h-full w-full flex-col items-center justify-center gap-2 px-3 py-4 text-slate-700\">\n <div class=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-white text-slate-900 shadow-sm\">\n <lucide-icon [img]=\"fileIcon\"></lucide-icon>\n </div>\n <span class=\"text-[10px] font-semibold uppercase tracking-[0.18em] text-slate-500\">\n {{ getFileBadge(document) }}\n </span>\n </div>\n }\n </a>\n }\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex flex-col gap-2 lg:flex-row lg:items-start lg:justify-between\">\n <div class=\"min-w-0\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <h4 class=\"truncate text-sm font-semibold text-slate-900\">\n {{ document.name || '\u0411\u0435\u0437 \u043D\u0430\u0437\u0432\u0438' }}\n </h4>\n @if (getDocumentTypeLabel(document)) {\n <span class=\"inline-flex shrink-0 items-center rounded-full border border-sky-200 bg-sky-50 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.18em] text-sky-700\">\n {{ getDocumentTypeLabel(document) }}\n </span>\n }\n </div>\n <p class=\"mt-1 text-xs text-slate-500\">\n {{ formatSize(document.size) }} \u00B7 {{ document.type }}\n </p>\n </div>\n\n <div class=\"flex flex-wrap items-center gap-2\">\n <ui-button variant=\"ghost\" size=\"sm\" (click)=\"openTextModal(document)\">\n <lucide-icon [img]=\"eyeIcon\"></lucide-icon>\n \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\n </ui-button>\n @if (isImage(document)) {\n <ui-button variant=\"ghost\" size=\"sm\" [disabled]=\"isDocumentRecognizing(document) || isRecognitionPending(document) || isRecognitionCompleted(document)\" (click)=\"recognizeText(document)\">\n <lucide-icon [img]=\"sparkleIcon\"></lucide-icon>\n {{ isDocumentRecognizing(document) ? '\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0432\u0430\u043D\u043D\u044F...' : '\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0434\u0430\u043D\u0456' }}\n </ui-button>\n }\n @if (isAdmin()) {\n <ui-button variant=\"ghost\" size=\"sm\" [disabled]=\"deletingDocumentId() === document.id\" (click)=\"removeDocument(document)\">\n <lucide-icon [img]=\"deleteIcon\"></lucide-icon>\n {{ deletingDocumentId() === document.id ? '\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F...' : '\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438' }}\n </ui-button>\n }\n </div>\n </div>\n\n <div class=\"mt-3 flex flex-wrap items-center justify-between gap-2\">\n <a\n class=\"inline-flex items-center rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm font-medium text-slate-700 transition hover:border-slate-300 hover:bg-slate-50\"\n [href]=\"document.downloadUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438\n </a>\n @if (isImage(document) && getRecognitionStatusLabel(document)) {\n <span\n class=\"inline-flex items-center rounded-full border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.12em]\"\n [class.border-amber-200]=\"isRecognitionPending(document)\"\n [class.bg-amber-50]=\"isRecognitionPending(document)\"\n [class.text-amber-700]=\"isRecognitionPending(document)\"\n [class.border-rose-200]=\"document.recognitionStatus === 'FAILED'\"\n [class.bg-rose-50]=\"document.recognitionStatus === 'FAILED'\"\n [class.text-rose-700]=\"document.recognitionStatus === 'FAILED'\"\n [class.border-emerald-200]=\"document.recognitionStatus === 'COMPLETED'\"\n [class.bg-emerald-50]=\"document.recognitionStatus === 'COMPLETED'\"\n [class.text-emerald-700]=\"document.recognitionStatus === 'COMPLETED'\"\n >\n {{ getRecognitionStatusLabel(document) }}\n </span>\n }\n </div>\n </div>\n </article>\n }\n </div>\n }\n </div>\n\n <div class=\"flex flex-col gap-3 rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-4\">\n <div>\n <h4 class=\"text-sm font-semibold text-slate-900\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432 \u0443 \u0444\u0430\u0439\u043B\u043E\u0432\u0435 \u0441\u0445\u043E\u0432\u0438\u0449\u0435</h4>\n <p class=\"mt-1 text-xs text-slate-500\">\u0414\u043E\u0434\u0430\u0439\u0442\u0435 \u043D\u043E\u0432\u0456 \u0444\u0430\u0439\u043B\u0438 \u0434\u043E \u043A\u0430\u0440\u0442\u043A\u0438 \u0431\u0435\u0437\u043F\u043E\u0441\u0435\u0440\u0435\u0434\u043D\u044C\u043E \u0442\u0443\u0442.</p>\n </div>\n\n <div class=\"flex w-full flex-col gap-2 sm:w-auto\">\n <ui-button variant=\"secondary\" size=\"sm\" (click)=\"openUploadModal()\">\n <lucide-icon [img]=\"plusIcon\"></lucide-icon>\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\n </ui-button>\n </div>\n </div>\n</div>\n\n<app-documents-text-modal\n [isOpen]=\"isTextOpen()\"\n [document]=\"textTarget()\"\n (closed)=\"closeTextModal()\"\n (recognizeRequested)=\"textTarget() && recognizeText(textTarget()!)\"\n></app-documents-text-modal>\n\n<app-documents-upload-modal\n [isOpen]=\"isUploadOpen()\"\n [entity]=\"entity()\"\n [id]=\"id()\"\n (closed)=\"closeUploadModal()\"\n (saved)=\"reloadDocuments()\"\n></app-documents-upload-modal>\n\n<app-documents-image-preview-modal\n [isOpen]=\"isImagePreviewOpen()\"\n [document]=\"imagePreviewTarget()\"\n (closed)=\"closeImagePreview()\"\n></app-documents-image-preview-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: DocumentsUploadModalComponent, selector: "app-documents-upload-modal", inputs: ["isOpen", "entity", "id"], outputs: ["closed", "saved"] }, { kind: "component", type: DocumentsTextModalComponent, selector: "app-documents-text-modal", inputs: ["isOpen", "document"], outputs: ["closed", "recognizeRequested"] }, { kind: "component", type: DocumentsImagePreviewModalComponent, selector: "app-documents-image-preview-modal", inputs: ["isOpen", "document"], outputs: ["closed"] }] });
1615
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DocumentsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1616
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: DocumentsComponent, isStandalone: true, selector: "app-documents", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"space-y-4\">\n <div>\n @if (isLoading()) {\n <div class=\"rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500\">\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432...\n </div>\n } @else if (documents().length === 0) {\n <div class=\"rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500\">\n \u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0438 \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0456\n </div>\n } @else {\n <div class=\"grid gap-3\">\n @for (document of documents(); track trackDocument($index, document)) {\n <article class=\"flex flex-col gap-4 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm sm:flex-row sm:items-center sm:justify-between\">\n @if (isImage(document)) {\n <button\n type=\"button\"\n class=\"block shrink-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 transition hover:border-slate-300 hover:bg-slate-100 h-28 w-40\"\n (click)=\"openImagePreview(document)\"\n >\n <img [src]=\"getImagePreviewUrl(document)\" [alt]=\"document.name || '\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442'\" loading=\"lazy\" decoding=\"async\" class=\"h-full w-full object-cover\">\n </button>\n } @else {\n <a\n class=\"block shrink-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 transition hover:border-slate-300 hover:bg-slate-100\"\n [href]=\"document.downloadUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [class.h-28]=\"isPdf(document)\"\n [class.w-40]=\"isPdf(document)\"\n [class.h-20]=\"!isPdf(document)\"\n [class.w-24]=\"!isPdf(document)\"\n >\n @if (isPdf(document)) {\n <div class=\"flex h-full w-full flex-col items-center justify-center gap-2 px-3 py-4 text-slate-700\">\n <div class=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-white text-slate-900 shadow-sm\">\n <svg [lucideIcon]=\"fileIcon\"></svg>\n </div>\n <span class=\"text-xs font-semibold uppercase tracking-[0.18em] text-slate-600\">PDF</span>\n </div>\n } @else {\n <div class=\"flex h-full w-full flex-col items-center justify-center gap-2 px-3 py-4 text-slate-700\">\n <div class=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-white text-slate-900 shadow-sm\">\n <svg [lucideIcon]=\"fileIcon\"></svg>\n </div>\n <span class=\"text-[10px] font-semibold uppercase tracking-[0.18em] text-slate-500\">\n {{ getFileBadge(document) }}\n </span>\n </div>\n }\n </a>\n }\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex flex-col gap-2 lg:flex-row lg:items-start lg:justify-between\">\n <div class=\"min-w-0\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <h4 class=\"truncate text-sm font-semibold text-slate-900\">\n {{ document.name || '\u0411\u0435\u0437 \u043D\u0430\u0437\u0432\u0438' }}\n </h4>\n @if (getDocumentTypeLabel(document)) {\n <span class=\"inline-flex shrink-0 items-center rounded-full border border-sky-200 bg-sky-50 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.18em] text-sky-700\">\n {{ getDocumentTypeLabel(document) }}\n </span>\n }\n </div>\n <p class=\"mt-1 text-xs text-slate-500\">\n {{ formatSize(document.size) }} \u00B7 {{ document.type }}\n </p>\n </div>\n\n <div class=\"flex flex-wrap items-center gap-2\">\n <ui-button variant=\"ghost\" size=\"sm\" (click)=\"openTextModal(document)\">\n <svg [lucideIcon]=\"eyeIcon\"></svg>\n \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\n </ui-button>\n @if (isImage(document)) {\n <ui-button variant=\"ghost\" size=\"sm\" [disabled]=\"isDocumentRecognizing(document) || isRecognitionPending(document) || isRecognitionCompleted(document)\" (click)=\"recognizeText(document)\">\n <svg [lucideIcon]=\"sparkleIcon\"></svg>\n {{ isDocumentRecognizing(document) ? '\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0432\u0430\u043D\u043D\u044F...' : '\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0434\u0430\u043D\u0456' }}\n </ui-button>\n }\n @if (isAdmin()) {\n <ui-button variant=\"ghost\" size=\"sm\" [disabled]=\"deletingDocumentId() === document.id\" (click)=\"removeDocument(document)\">\n <svg [lucideIcon]=\"deleteIcon\"></svg>\n {{ deletingDocumentId() === document.id ? '\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F...' : '\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438' }}\n </ui-button>\n }\n </div>\n </div>\n\n <div class=\"mt-3 flex flex-wrap items-center justify-between gap-2\">\n <a\n class=\"inline-flex items-center rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm font-medium text-slate-700 transition hover:border-slate-300 hover:bg-slate-50\"\n [href]=\"document.downloadUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438\n </a>\n @if (isImage(document) && getRecognitionStatusLabel(document)) {\n <span\n class=\"inline-flex items-center rounded-full border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.12em]\"\n [class.border-amber-200]=\"isRecognitionPending(document)\"\n [class.bg-amber-50]=\"isRecognitionPending(document)\"\n [class.text-amber-700]=\"isRecognitionPending(document)\"\n [class.border-rose-200]=\"document.recognitionStatus === 'FAILED'\"\n [class.bg-rose-50]=\"document.recognitionStatus === 'FAILED'\"\n [class.text-rose-700]=\"document.recognitionStatus === 'FAILED'\"\n [class.border-emerald-200]=\"document.recognitionStatus === 'COMPLETED'\"\n [class.bg-emerald-50]=\"document.recognitionStatus === 'COMPLETED'\"\n [class.text-emerald-700]=\"document.recognitionStatus === 'COMPLETED'\"\n >\n {{ getRecognitionStatusLabel(document) }}\n </span>\n }\n </div>\n </div>\n </article>\n }\n </div>\n }\n </div>\n\n <div class=\"flex flex-col gap-3 rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-4\">\n <div>\n <h4 class=\"text-sm font-semibold text-slate-900\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432 \u0443 \u0444\u0430\u0439\u043B\u043E\u0432\u0435 \u0441\u0445\u043E\u0432\u0438\u0449\u0435</h4>\n <p class=\"mt-1 text-xs text-slate-500\">\u0414\u043E\u0434\u0430\u0439\u0442\u0435 \u043D\u043E\u0432\u0456 \u0444\u0430\u0439\u043B\u0438 \u0434\u043E \u043A\u0430\u0440\u0442\u043A\u0438 \u0431\u0435\u0437\u043F\u043E\u0441\u0435\u0440\u0435\u0434\u043D\u044C\u043E \u0442\u0443\u0442.</p>\n </div>\n\n <div class=\"flex w-full flex-col gap-2 sm:w-auto\">\n <ui-button variant=\"secondary\" size=\"sm\" (click)=\"openUploadModal()\">\n <svg [lucideIcon]=\"plusIcon\"></svg>\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\n </ui-button>\n </div>\n </div>\n</div>\n\n<app-documents-text-modal\n [isOpen]=\"isTextOpen()\"\n [document]=\"textTarget()\"\n (closed)=\"closeTextModal()\"\n (recognizeRequested)=\"textTarget() && recognizeText(textTarget()!)\"\n></app-documents-text-modal>\n\n<app-documents-upload-modal\n [isOpen]=\"isUploadOpen()\"\n [entity]=\"entity()\"\n [id]=\"id()\"\n (closed)=\"closeUploadModal()\"\n (saved)=\"reloadDocuments()\"\n></app-documents-upload-modal>\n\n<app-documents-image-preview-modal\n [isOpen]=\"isImagePreviewOpen()\"\n [document]=\"imagePreviewTarget()\"\n (closed)=\"closeImagePreview()\"\n></app-documents-image-preview-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: DocumentsUploadModalComponent, selector: "app-documents-upload-modal", inputs: ["isOpen", "entity", "id"], outputs: ["closed", "saved"] }, { kind: "component", type: DocumentsTextModalComponent, selector: "app-documents-text-modal", inputs: ["isOpen", "document"], outputs: ["closed", "recognizeRequested"] }, { kind: "component", type: DocumentsImagePreviewModalComponent, selector: "app-documents-image-preview-modal", inputs: ["isOpen", "document"], outputs: ["closed"] }] });
1601
1617
  }
1602
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: DocumentsComponent, decorators: [{
1618
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DocumentsComponent, decorators: [{
1603
1619
  type: Component,
1604
1620
  args: [{ selector: 'app-documents', standalone: true, imports: [
1605
1621
  CommonModule,
1606
- LucideAngularModule,
1622
+ LucideDynamicIcon,
1607
1623
  UiButtonComponent,
1608
1624
  DocumentsUploadModalComponent,
1609
1625
  DocumentsTextModalComponent,
1610
1626
  DocumentsImagePreviewModalComponent,
1611
- ], template: "<div class=\"space-y-4\">\n <div>\n @if (isLoading()) {\n <div class=\"rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500\">\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432...\n </div>\n } @else if (documents().length === 0) {\n <div class=\"rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500\">\n \u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0438 \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0456\n </div>\n } @else {\n <div class=\"grid gap-3\">\n @for (document of documents(); track trackDocument($index, document)) {\n <article class=\"flex flex-col gap-4 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm sm:flex-row sm:items-center sm:justify-between\">\n @if (isImage(document)) {\n <button\n type=\"button\"\n class=\"block shrink-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 transition hover:border-slate-300 hover:bg-slate-100 h-28 w-40\"\n (click)=\"openImagePreview(document)\"\n >\n <img [src]=\"getImagePreviewUrl(document)\" [alt]=\"document.name || '\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442'\" loading=\"lazy\" decoding=\"async\" class=\"h-full w-full object-cover\">\n </button>\n } @else {\n <a\n class=\"block shrink-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 transition hover:border-slate-300 hover:bg-slate-100\"\n [href]=\"document.downloadUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [class.h-28]=\"isPdf(document)\"\n [class.w-40]=\"isPdf(document)\"\n [class.h-20]=\"!isPdf(document)\"\n [class.w-24]=\"!isPdf(document)\"\n >\n @if (isPdf(document)) {\n <div class=\"flex h-full w-full flex-col items-center justify-center gap-2 px-3 py-4 text-slate-700\">\n <div class=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-white text-slate-900 shadow-sm\">\n <lucide-icon [img]=\"fileIcon\"></lucide-icon>\n </div>\n <span class=\"text-xs font-semibold uppercase tracking-[0.18em] text-slate-600\">PDF</span>\n </div>\n } @else {\n <div class=\"flex h-full w-full flex-col items-center justify-center gap-2 px-3 py-4 text-slate-700\">\n <div class=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-white text-slate-900 shadow-sm\">\n <lucide-icon [img]=\"fileIcon\"></lucide-icon>\n </div>\n <span class=\"text-[10px] font-semibold uppercase tracking-[0.18em] text-slate-500\">\n {{ getFileBadge(document) }}\n </span>\n </div>\n }\n </a>\n }\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex flex-col gap-2 lg:flex-row lg:items-start lg:justify-between\">\n <div class=\"min-w-0\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <h4 class=\"truncate text-sm font-semibold text-slate-900\">\n {{ document.name || '\u0411\u0435\u0437 \u043D\u0430\u0437\u0432\u0438' }}\n </h4>\n @if (getDocumentTypeLabel(document)) {\n <span class=\"inline-flex shrink-0 items-center rounded-full border border-sky-200 bg-sky-50 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.18em] text-sky-700\">\n {{ getDocumentTypeLabel(document) }}\n </span>\n }\n </div>\n <p class=\"mt-1 text-xs text-slate-500\">\n {{ formatSize(document.size) }} \u00B7 {{ document.type }}\n </p>\n </div>\n\n <div class=\"flex flex-wrap items-center gap-2\">\n <ui-button variant=\"ghost\" size=\"sm\" (click)=\"openTextModal(document)\">\n <lucide-icon [img]=\"eyeIcon\"></lucide-icon>\n \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\n </ui-button>\n @if (isImage(document)) {\n <ui-button variant=\"ghost\" size=\"sm\" [disabled]=\"isDocumentRecognizing(document) || isRecognitionPending(document) || isRecognitionCompleted(document)\" (click)=\"recognizeText(document)\">\n <lucide-icon [img]=\"sparkleIcon\"></lucide-icon>\n {{ isDocumentRecognizing(document) ? '\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0432\u0430\u043D\u043D\u044F...' : '\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0434\u0430\u043D\u0456' }}\n </ui-button>\n }\n @if (isAdmin()) {\n <ui-button variant=\"ghost\" size=\"sm\" [disabled]=\"deletingDocumentId() === document.id\" (click)=\"removeDocument(document)\">\n <lucide-icon [img]=\"deleteIcon\"></lucide-icon>\n {{ deletingDocumentId() === document.id ? '\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F...' : '\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438' }}\n </ui-button>\n }\n </div>\n </div>\n\n <div class=\"mt-3 flex flex-wrap items-center justify-between gap-2\">\n <a\n class=\"inline-flex items-center rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm font-medium text-slate-700 transition hover:border-slate-300 hover:bg-slate-50\"\n [href]=\"document.downloadUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438\n </a>\n @if (isImage(document) && getRecognitionStatusLabel(document)) {\n <span\n class=\"inline-flex items-center rounded-full border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.12em]\"\n [class.border-amber-200]=\"isRecognitionPending(document)\"\n [class.bg-amber-50]=\"isRecognitionPending(document)\"\n [class.text-amber-700]=\"isRecognitionPending(document)\"\n [class.border-rose-200]=\"document.recognitionStatus === 'FAILED'\"\n [class.bg-rose-50]=\"document.recognitionStatus === 'FAILED'\"\n [class.text-rose-700]=\"document.recognitionStatus === 'FAILED'\"\n [class.border-emerald-200]=\"document.recognitionStatus === 'COMPLETED'\"\n [class.bg-emerald-50]=\"document.recognitionStatus === 'COMPLETED'\"\n [class.text-emerald-700]=\"document.recognitionStatus === 'COMPLETED'\"\n >\n {{ getRecognitionStatusLabel(document) }}\n </span>\n }\n </div>\n </div>\n </article>\n }\n </div>\n }\n </div>\n\n <div class=\"flex flex-col gap-3 rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-4\">\n <div>\n <h4 class=\"text-sm font-semibold text-slate-900\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432 \u0443 \u0444\u0430\u0439\u043B\u043E\u0432\u0435 \u0441\u0445\u043E\u0432\u0438\u0449\u0435</h4>\n <p class=\"mt-1 text-xs text-slate-500\">\u0414\u043E\u0434\u0430\u0439\u0442\u0435 \u043D\u043E\u0432\u0456 \u0444\u0430\u0439\u043B\u0438 \u0434\u043E \u043A\u0430\u0440\u0442\u043A\u0438 \u0431\u0435\u0437\u043F\u043E\u0441\u0435\u0440\u0435\u0434\u043D\u044C\u043E \u0442\u0443\u0442.</p>\n </div>\n\n <div class=\"flex w-full flex-col gap-2 sm:w-auto\">\n <ui-button variant=\"secondary\" size=\"sm\" (click)=\"openUploadModal()\">\n <lucide-icon [img]=\"plusIcon\"></lucide-icon>\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\n </ui-button>\n </div>\n </div>\n</div>\n\n<app-documents-text-modal\n [isOpen]=\"isTextOpen()\"\n [document]=\"textTarget()\"\n (closed)=\"closeTextModal()\"\n (recognizeRequested)=\"textTarget() && recognizeText(textTarget()!)\"\n></app-documents-text-modal>\n\n<app-documents-upload-modal\n [isOpen]=\"isUploadOpen()\"\n [entity]=\"entity()\"\n [id]=\"id()\"\n (closed)=\"closeUploadModal()\"\n (saved)=\"reloadDocuments()\"\n></app-documents-upload-modal>\n\n<app-documents-image-preview-modal\n [isOpen]=\"isImagePreviewOpen()\"\n [document]=\"imagePreviewTarget()\"\n (closed)=\"closeImagePreview()\"\n></app-documents-image-preview-modal>\n" }]
1627
+ ], template: "<div class=\"space-y-4\">\n <div>\n @if (isLoading()) {\n <div class=\"rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500\">\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432...\n </div>\n } @else if (documents().length === 0) {\n <div class=\"rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500\">\n \u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0438 \u0432\u0456\u0434\u0441\u0443\u0442\u043D\u0456\n </div>\n } @else {\n <div class=\"grid gap-3\">\n @for (document of documents(); track trackDocument($index, document)) {\n <article class=\"flex flex-col gap-4 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm sm:flex-row sm:items-center sm:justify-between\">\n @if (isImage(document)) {\n <button\n type=\"button\"\n class=\"block shrink-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 transition hover:border-slate-300 hover:bg-slate-100 h-28 w-40\"\n (click)=\"openImagePreview(document)\"\n >\n <img [src]=\"getImagePreviewUrl(document)\" [alt]=\"document.name || '\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442'\" loading=\"lazy\" decoding=\"async\" class=\"h-full w-full object-cover\">\n </button>\n } @else {\n <a\n class=\"block shrink-0 overflow-hidden rounded-2xl border border-slate-200 bg-slate-50 transition hover:border-slate-300 hover:bg-slate-100\"\n [href]=\"document.downloadUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n [class.h-28]=\"isPdf(document)\"\n [class.w-40]=\"isPdf(document)\"\n [class.h-20]=\"!isPdf(document)\"\n [class.w-24]=\"!isPdf(document)\"\n >\n @if (isPdf(document)) {\n <div class=\"flex h-full w-full flex-col items-center justify-center gap-2 px-3 py-4 text-slate-700\">\n <div class=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-white text-slate-900 shadow-sm\">\n <svg [lucideIcon]=\"fileIcon\"></svg>\n </div>\n <span class=\"text-xs font-semibold uppercase tracking-[0.18em] text-slate-600\">PDF</span>\n </div>\n } @else {\n <div class=\"flex h-full w-full flex-col items-center justify-center gap-2 px-3 py-4 text-slate-700\">\n <div class=\"flex h-11 w-11 items-center justify-center rounded-2xl bg-white text-slate-900 shadow-sm\">\n <svg [lucideIcon]=\"fileIcon\"></svg>\n </div>\n <span class=\"text-[10px] font-semibold uppercase tracking-[0.18em] text-slate-500\">\n {{ getFileBadge(document) }}\n </span>\n </div>\n }\n </a>\n }\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex flex-col gap-2 lg:flex-row lg:items-start lg:justify-between\">\n <div class=\"min-w-0\">\n <div class=\"flex flex-wrap items-center gap-2\">\n <h4 class=\"truncate text-sm font-semibold text-slate-900\">\n {{ document.name || '\u0411\u0435\u0437 \u043D\u0430\u0437\u0432\u0438' }}\n </h4>\n @if (getDocumentTypeLabel(document)) {\n <span class=\"inline-flex shrink-0 items-center rounded-full border border-sky-200 bg-sky-50 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.18em] text-sky-700\">\n {{ getDocumentTypeLabel(document) }}\n </span>\n }\n </div>\n <p class=\"mt-1 text-xs text-slate-500\">\n {{ formatSize(document.size) }} \u00B7 {{ document.type }}\n </p>\n </div>\n\n <div class=\"flex flex-wrap items-center gap-2\">\n <ui-button variant=\"ghost\" size=\"sm\" (click)=\"openTextModal(document)\">\n <svg [lucideIcon]=\"eyeIcon\"></svg>\n \u041F\u0435\u0440\u0435\u0433\u043B\u044F\u0434\n </ui-button>\n @if (isImage(document)) {\n <ui-button variant=\"ghost\" size=\"sm\" [disabled]=\"isDocumentRecognizing(document) || isRecognitionPending(document) || isRecognitionCompleted(document)\" (click)=\"recognizeText(document)\">\n <svg [lucideIcon]=\"sparkleIcon\"></svg>\n {{ isDocumentRecognizing(document) ? '\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0432\u0430\u043D\u043D\u044F...' : '\u0420\u043E\u0437\u043F\u0456\u0437\u043D\u0430\u0442\u0438 \u0434\u0430\u043D\u0456' }}\n </ui-button>\n }\n @if (isAdmin()) {\n <ui-button variant=\"ghost\" size=\"sm\" [disabled]=\"deletingDocumentId() === document.id\" (click)=\"removeDocument(document)\">\n <svg [lucideIcon]=\"deleteIcon\"></svg>\n {{ deletingDocumentId() === document.id ? '\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F...' : '\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438' }}\n </ui-button>\n }\n </div>\n </div>\n\n <div class=\"mt-3 flex flex-wrap items-center justify-between gap-2\">\n <a\n class=\"inline-flex items-center rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm font-medium text-slate-700 transition hover:border-slate-300 hover:bg-slate-50\"\n [href]=\"document.downloadUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438\n </a>\n @if (isImage(document) && getRecognitionStatusLabel(document)) {\n <span\n class=\"inline-flex items-center rounded-full border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.12em]\"\n [class.border-amber-200]=\"isRecognitionPending(document)\"\n [class.bg-amber-50]=\"isRecognitionPending(document)\"\n [class.text-amber-700]=\"isRecognitionPending(document)\"\n [class.border-rose-200]=\"document.recognitionStatus === 'FAILED'\"\n [class.bg-rose-50]=\"document.recognitionStatus === 'FAILED'\"\n [class.text-rose-700]=\"document.recognitionStatus === 'FAILED'\"\n [class.border-emerald-200]=\"document.recognitionStatus === 'COMPLETED'\"\n [class.bg-emerald-50]=\"document.recognitionStatus === 'COMPLETED'\"\n [class.text-emerald-700]=\"document.recognitionStatus === 'COMPLETED'\"\n >\n {{ getRecognitionStatusLabel(document) }}\n </span>\n }\n </div>\n </div>\n </article>\n }\n </div>\n }\n </div>\n\n <div class=\"flex flex-col gap-3 rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-4\">\n <div>\n <h4 class=\"text-sm font-semibold text-slate-900\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432 \u0443 \u0444\u0430\u0439\u043B\u043E\u0432\u0435 \u0441\u0445\u043E\u0432\u0438\u0449\u0435</h4>\n <p class=\"mt-1 text-xs text-slate-500\">\u0414\u043E\u0434\u0430\u0439\u0442\u0435 \u043D\u043E\u0432\u0456 \u0444\u0430\u0439\u043B\u0438 \u0434\u043E \u043A\u0430\u0440\u0442\u043A\u0438 \u0431\u0435\u0437\u043F\u043E\u0441\u0435\u0440\u0435\u0434\u043D\u044C\u043E \u0442\u0443\u0442.</p>\n </div>\n\n <div class=\"flex w-full flex-col gap-2 sm:w-auto\">\n <ui-button variant=\"secondary\" size=\"sm\" (click)=\"openUploadModal()\">\n <svg [lucideIcon]=\"plusIcon\"></svg>\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\n </ui-button>\n </div>\n </div>\n</div>\n\n<app-documents-text-modal\n [isOpen]=\"isTextOpen()\"\n [document]=\"textTarget()\"\n (closed)=\"closeTextModal()\"\n (recognizeRequested)=\"textTarget() && recognizeText(textTarget()!)\"\n></app-documents-text-modal>\n\n<app-documents-upload-modal\n [isOpen]=\"isUploadOpen()\"\n [entity]=\"entity()\"\n [id]=\"id()\"\n (closed)=\"closeUploadModal()\"\n (saved)=\"reloadDocuments()\"\n></app-documents-upload-modal>\n\n<app-documents-image-preview-modal\n [isOpen]=\"isImagePreviewOpen()\"\n [document]=\"imagePreviewTarget()\"\n (closed)=\"closeImagePreview()\"\n></app-documents-image-preview-modal>\n" }]
1612
1628
  }], propDecorators: { entity: [{ type: i0.Input, args: [{ isSignal: true, alias: "entity", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
1613
1629
 
1614
1630
  class HistoryTabComponent {
@@ -1870,10 +1886,10 @@ class HistoryTabComponent {
1870
1886
  ? (operation.changes || []).filter((change) => !primaryTypes.has(change.entityType))
1871
1887
  : operation.changes || [];
1872
1888
  }
1873
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: HistoryTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1874
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: HistoryTabComponent, isStandalone: true, selector: "app-history-tab", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<section class=\"space-y-4\">\n @if (isLoading()) {\n <div class=\"rounded-2xl border border-slate-200 bg-white p-6 text-sm text-slate-500\">\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0456\u0441\u0442\u043E\u0440\u0456\u0457\u2026\n </div>\n } @else if (hasError()) {\n <div class=\"rounded-2xl border border-red-200 bg-red-50 p-6 text-sm text-red-700\">\n \u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0456\u0441\u0442\u043E\u0440\u0456\u044E \u0437\u043C\u0456\u043D.\n </div>\n } @else if (!operations().length) {\n <div class=\"rounded-2xl border border-slate-200 bg-white p-6 text-sm text-slate-500\">\n \u0406\u0441\u0442\u043E\u0440\u0456\u044F \u0437\u043C\u0456\u043D \u043F\u043E\u043A\u0438 \u043F\u043E\u0440\u043E\u0436\u043D\u044F.\n </div>\n } @else {\n <div class=\"space-y-3\">\n @for (operation of operations(); track operation.id) {\n <article class=\"rounded-2xl border border-slate-200 bg-white p-5 shadow-sm\">\n <div class=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h3 class=\"text-sm font-semibold text-slate-900\">{{ operation.description }}</h3>\n @if (operation.actorName) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ operation.actorName }}</p>\n }\n </div>\n <time class=\"text-xs text-slate-400\" [dateTime]=\"operation.createdAt\">\n {{ operation.createdAt | date: 'dd.MM.yyyy HH:mm' }}\n </time>\n </div>\n\n @if (getPrimaryChanges(operation).length) {\n <div class=\"mt-4 space-y-2 border-t border-slate-100 pt-4\">\n @for (change of getPrimaryChanges(operation); track change.entityId + change.entityType) {\n @for (field of (change.changedFields | keyvalue); track field.key) {\n <div class=\"flex flex-wrap items-center gap-2 text-sm\">\n <span class=\"font-medium text-slate-700\">{{ field.value.label }}</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.from).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0411\u0443\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.from); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.from.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.from.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-slate-100\" (click)=\"openImageViewer(getImageUrls(field.value.from.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u0421\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.from.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.from.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.from.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-500\" [innerHTML]=\"field.value.from.display\"></div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.from.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.from.url\">{{ field.value.from.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.from.display }}</span>\n }\n }\n <span class=\"mx-1 shrink-0 text-lg font-semibold text-slate-500\">\u2192</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.to).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0421\u0442\u0430\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.to); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.to.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.to.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-slate-100\" (click)=\"openImageViewer(getImageUrls(field.value.to.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u041D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.to.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.to.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-900\" [innerHTML]=\"field.value.to.display\"></div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.to.url\">{{ field.value.to.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.to.display }}</span>\n }\n }\n </div>\n }\n }\n </div>\n }\n\n @if (getRelatedChanges(operation).length) {\n <div class=\"mt-4 border-t border-slate-100 pt-4\">\n <button\n type=\"button\"\n class=\"flex w-full items-center justify-between gap-3 text-left text-sm text-slate-600\"\n [attr.aria-expanded]=\"isExpanded(operation.id)\"\n (click)=\"toggleOperation(operation.id)\"\n >\n <span>\n \u0414\u0435\u0442\u0430\u043B\u0456 \u0437\u043C\u0456\u043D:\n <span class=\"font-medium text-slate-900\">{{ getAffectedSummary(operation) }}</span>\n </span>\n <span class=\"text-lg leading-none text-slate-400\">{{ isExpanded(operation.id) ? '\u2212' : '+' }}</span>\n </button>\n\n @if (isExpanded(operation.id)) {\n <div class=\"mt-4 space-y-4\">\n @for (change of getRelatedChanges(operation); track change.entityId + change.entityType) {\n <div class=\"rounded-xl bg-slate-50 p-3\">\n <p class=\"mb-2 text-xs font-semibold uppercase tracking-[0.16em] text-slate-500\">\n {{ getEntityLabel(change.entityType) }} \u00B7 {{ getActionLabel(change.action) }}\n </p>\n @for (field of (change.changedFields | keyvalue); track field.key) {\n <div class=\"flex flex-wrap items-center gap-2 text-sm\">\n <span class=\"font-medium text-slate-700\">{{ field.value.label }}</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.from).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0411\u0443\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.from); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-white px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.from.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.from.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-white\" (click)=\"openImageViewer(getImageUrls(field.value.from.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u0421\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.from.url) {\n <a class=\"text-sky-700 underline\" [href]=\"field.value.from.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.from.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-500\" [innerHTML]=\"field.value.from.display\"></div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.from.url) {\n <a class=\"text-sky-700 underline\" [routerLink]=\"field.value.from.url\">{{ field.value.from.display }}</a>\n } @else {\n <span class=\"text-slate-400\">{{ field.value.from.display }}</span>\n }\n }\n <span class=\"mx-1 shrink-0 text-lg font-semibold text-slate-500\">\u2192</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.to).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0421\u0442\u0430\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.to); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.to.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.to.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-white\" (click)=\"openImageViewer(getImageUrls(field.value.to.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u041D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.to.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.to.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-900\" [innerHTML]=\"field.value.to.display\"></div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.to.url\">{{ field.value.to.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.to.display }}</span>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </article>\n }\n </div>\n }\n</section>\n\n@if (isViewerOpen()) {\n <app-images-viewer [urls]=\"viewerUrls()\" (closed)=\"closeImageViewer()\" />\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ImagesViewerComponent, selector: "app-images-viewer", inputs: ["urls", "initialIndex"], outputs: ["closed"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }, { kind: "pipe", type: i1$1.KeyValuePipe, name: "keyvalue" }] });
1889
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: HistoryTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1890
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: HistoryTabComponent, isStandalone: true, selector: "app-history-tab", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<section class=\"space-y-4\">\n @if (isLoading()) {\n <div class=\"rounded-2xl border border-slate-200 bg-white p-6 text-sm text-slate-500\">\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0456\u0441\u0442\u043E\u0440\u0456\u0457\u2026\n </div>\n } @else if (hasError()) {\n <div class=\"rounded-2xl border border-red-200 bg-red-50 p-6 text-sm text-red-700\">\n \u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0456\u0441\u0442\u043E\u0440\u0456\u044E \u0437\u043C\u0456\u043D.\n </div>\n } @else if (!operations().length) {\n <div class=\"rounded-2xl border border-slate-200 bg-white p-6 text-sm text-slate-500\">\n \u0406\u0441\u0442\u043E\u0440\u0456\u044F \u0437\u043C\u0456\u043D \u043F\u043E\u043A\u0438 \u043F\u043E\u0440\u043E\u0436\u043D\u044F.\n </div>\n } @else {\n <div class=\"space-y-3\">\n @for (operation of operations(); track operation.id) {\n <article class=\"rounded-2xl border border-slate-200 bg-white p-5 shadow-sm\">\n <div class=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h3 class=\"text-sm font-semibold text-slate-900\">{{ operation.description }}</h3>\n @if (operation.actorName) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ operation.actorName }}</p>\n }\n </div>\n <time class=\"text-xs text-slate-400\" [dateTime]=\"operation.createdAt\">\n {{ operation.createdAt | date: 'dd.MM.yyyy HH:mm' }}\n </time>\n </div>\n\n @if (getPrimaryChanges(operation).length) {\n <div class=\"mt-4 space-y-2 border-t border-slate-100 pt-4\">\n @for (change of getPrimaryChanges(operation); track change.entityId + change.entityType) {\n @for (field of (change.changedFields | keyvalue); track field.key) {\n <div class=\"flex flex-wrap items-center gap-2 text-sm\">\n <span class=\"font-medium text-slate-700\">{{ field.value.label }}</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.from).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0411\u0443\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.from); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.from.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.from.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-slate-100\" (click)=\"openImageViewer(getImageUrls(field.value.from.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u0421\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.from.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.from.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.from.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-500\" [innerHTML]=\"field.value.from.display\"></div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.from.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.from.url\">{{ field.value.from.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.from.display }}</span>\n }\n }\n <span class=\"mx-1 shrink-0 text-lg font-semibold text-slate-500\">\u2192</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.to).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0421\u0442\u0430\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.to); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.to.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.to.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-slate-100\" (click)=\"openImageViewer(getImageUrls(field.value.to.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u041D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.to.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.to.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-900\" [innerHTML]=\"field.value.to.display\"></div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.to.url\">{{ field.value.to.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.to.display }}</span>\n }\n }\n </div>\n }\n }\n </div>\n }\n\n @if (getRelatedChanges(operation).length) {\n <div class=\"mt-4 border-t border-slate-100 pt-4\">\n <button\n type=\"button\"\n class=\"flex w-full items-center justify-between gap-3 text-left text-sm text-slate-600\"\n [attr.aria-expanded]=\"isExpanded(operation.id)\"\n (click)=\"toggleOperation(operation.id)\"\n >\n <span>\n \u0414\u0435\u0442\u0430\u043B\u0456 \u0437\u043C\u0456\u043D:\n <span class=\"font-medium text-slate-900\">{{ getAffectedSummary(operation) }}</span>\n </span>\n <span class=\"text-lg leading-none text-slate-400\">{{ isExpanded(operation.id) ? '\u2212' : '+' }}</span>\n </button>\n\n @if (isExpanded(operation.id)) {\n <div class=\"mt-4 space-y-4\">\n @for (change of getRelatedChanges(operation); track change.entityId + change.entityType) {\n <div class=\"rounded-xl bg-slate-50 p-3\">\n <p class=\"mb-2 text-xs font-semibold uppercase tracking-[0.16em] text-slate-500\">\n {{ getEntityLabel(change.entityType) }} \u00B7 {{ getActionLabel(change.action) }}\n </p>\n @for (field of (change.changedFields | keyvalue); track field.key) {\n <div class=\"flex flex-wrap items-center gap-2 text-sm\">\n <span class=\"font-medium text-slate-700\">{{ field.value.label }}</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.from).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0411\u0443\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.from); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-white px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.from.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.from.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-white\" (click)=\"openImageViewer(getImageUrls(field.value.from.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u0421\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.from.url) {\n <a class=\"text-sky-700 underline\" [href]=\"field.value.from.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.from.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-500\" [innerHTML]=\"field.value.from.display\"></div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.from.url) {\n <a class=\"text-sky-700 underline\" [routerLink]=\"field.value.from.url\">{{ field.value.from.display }}</a>\n } @else {\n <span class=\"text-slate-400\">{{ field.value.from.display }}</span>\n }\n }\n <span class=\"mx-1 shrink-0 text-lg font-semibold text-slate-500\">\u2192</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.to).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0421\u0442\u0430\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.to); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.to.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.to.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-white\" (click)=\"openImageViewer(getImageUrls(field.value.to.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u041D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.to.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.to.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-900\" [innerHTML]=\"field.value.to.display\"></div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.to.url\">{{ field.value.to.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.to.display }}</span>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </article>\n }\n </div>\n }\n</section>\n\n@if (isViewerOpen()) {\n <app-images-viewer [urls]=\"viewerUrls()\" (closed)=\"closeImageViewer()\" />\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ImagesViewerComponent, selector: "app-images-viewer", inputs: ["urls", "initialIndex"], outputs: ["closed"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }, { kind: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }] });
1875
1891
  }
1876
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: HistoryTabComponent, decorators: [{
1892
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: HistoryTabComponent, decorators: [{
1877
1893
  type: Component,
1878
1894
  args: [{ selector: 'app-history-tab', standalone: true, imports: [CommonModule, ImagesViewerComponent, RouterLink], template: "<section class=\"space-y-4\">\n @if (isLoading()) {\n <div class=\"rounded-2xl border border-slate-200 bg-white p-6 text-sm text-slate-500\">\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0456\u0441\u0442\u043E\u0440\u0456\u0457\u2026\n </div>\n } @else if (hasError()) {\n <div class=\"rounded-2xl border border-red-200 bg-red-50 p-6 text-sm text-red-700\">\n \u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0456\u0441\u0442\u043E\u0440\u0456\u044E \u0437\u043C\u0456\u043D.\n </div>\n } @else if (!operations().length) {\n <div class=\"rounded-2xl border border-slate-200 bg-white p-6 text-sm text-slate-500\">\n \u0406\u0441\u0442\u043E\u0440\u0456\u044F \u0437\u043C\u0456\u043D \u043F\u043E\u043A\u0438 \u043F\u043E\u0440\u043E\u0436\u043D\u044F.\n </div>\n } @else {\n <div class=\"space-y-3\">\n @for (operation of operations(); track operation.id) {\n <article class=\"rounded-2xl border border-slate-200 bg-white p-5 shadow-sm\">\n <div class=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h3 class=\"text-sm font-semibold text-slate-900\">{{ operation.description }}</h3>\n @if (operation.actorName) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ operation.actorName }}</p>\n }\n </div>\n <time class=\"text-xs text-slate-400\" [dateTime]=\"operation.createdAt\">\n {{ operation.createdAt | date: 'dd.MM.yyyy HH:mm' }}\n </time>\n </div>\n\n @if (getPrimaryChanges(operation).length) {\n <div class=\"mt-4 space-y-2 border-t border-slate-100 pt-4\">\n @for (change of getPrimaryChanges(operation); track change.entityId + change.entityType) {\n @for (field of (change.changedFields | keyvalue); track field.key) {\n <div class=\"flex flex-wrap items-center gap-2 text-sm\">\n <span class=\"font-medium text-slate-700\">{{ field.value.label }}</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.from).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0411\u0443\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.from); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.from.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.from.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-slate-100\" (click)=\"openImageViewer(getImageUrls(field.value.from.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u0421\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.from.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.from.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.from.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-500\" [innerHTML]=\"field.value.from.display\"></div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.from.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.from.url\">{{ field.value.from.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.from.display }}</span>\n }\n }\n <span class=\"mx-1 shrink-0 text-lg font-semibold text-slate-500\">\u2192</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.to).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0421\u0442\u0430\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.to); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.to.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.to.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-slate-100\" (click)=\"openImageViewer(getImageUrls(field.value.to.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u041D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.to.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.to.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-900\" [innerHTML]=\"field.value.to.display\"></div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.to.url\">{{ field.value.to.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.to.display }}</span>\n }\n }\n </div>\n }\n }\n </div>\n }\n\n @if (getRelatedChanges(operation).length) {\n <div class=\"mt-4 border-t border-slate-100 pt-4\">\n <button\n type=\"button\"\n class=\"flex w-full items-center justify-between gap-3 text-left text-sm text-slate-600\"\n [attr.aria-expanded]=\"isExpanded(operation.id)\"\n (click)=\"toggleOperation(operation.id)\"\n >\n <span>\n \u0414\u0435\u0442\u0430\u043B\u0456 \u0437\u043C\u0456\u043D:\n <span class=\"font-medium text-slate-900\">{{ getAffectedSummary(operation) }}</span>\n </span>\n <span class=\"text-lg leading-none text-slate-400\">{{ isExpanded(operation.id) ? '\u2212' : '+' }}</span>\n </button>\n\n @if (isExpanded(operation.id)) {\n <div class=\"mt-4 space-y-4\">\n @for (change of getRelatedChanges(operation); track change.entityId + change.entityType) {\n <div class=\"rounded-xl bg-slate-50 p-3\">\n <p class=\"mb-2 text-xs font-semibold uppercase tracking-[0.16em] text-slate-500\">\n {{ getEntityLabel(change.entityType) }} \u00B7 {{ getActionLabel(change.action) }}\n </p>\n @for (field of (change.changedFields | keyvalue); track field.key) {\n <div class=\"flex flex-wrap items-center gap-2 text-sm\">\n <span class=\"font-medium text-slate-700\">{{ field.value.label }}</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.from).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0411\u0443\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.from); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-white px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.from.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.from.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-white\" (click)=\"openImageViewer(getImageUrls(field.value.from.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u0441\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u0421\u0442\u0430\u0440\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.from.url) {\n <a class=\"text-sky-700 underline\" [href]=\"field.value.from.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.from.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-500\" [innerHTML]=\"field.value.from.display\"></div>\n } @else {\n <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.from.url) {\n <a class=\"text-sky-700 underline\" [routerLink]=\"field.value.from.url\">{{ field.value.from.display }}</a>\n } @else {\n <span class=\"text-slate-400\">{{ field.value.from.display }}</span>\n }\n }\n <span class=\"mx-1 shrink-0 text-lg font-semibold text-slate-500\">\u2192</span>\n @if (isStructuredField(field.value)) {\n @if (getStructuredItems(field.value.to).length) {\n <div class=\"min-w-[16rem] flex-1 space-y-1\">\n <div class=\"text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-400\">\u0421\u0442\u0430\u043B\u043E</div>\n @for (item of getStructuredItems(field.value.to); track item.key) {\n <div class=\"rounded-lg border border-slate-200 bg-slate-50 px-2 py-1 text-xs text-slate-600\">\n @for (itemField of item.fields; track itemField.key) {<span class=\"mr-2\"><span class=\"font-medium\">{{ itemField.label }}:</span> {{ itemField.display }}</span>}\n </div>\n }\n </div>\n } @else { <span class=\"text-slate-400\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span> }\n } @else if (isImageField(field.value)) {\n @if (getImageUrls(field.value.to.value).length) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (url of getImageUrls(field.value.to.value); track url; let imageIndex = $index) {\n <button type=\"button\" class=\"h-14 w-14 overflow-hidden rounded-lg border border-slate-200 bg-white\" (click)=\"openImageViewer(getImageUrls(field.value.to.value))\" [attr.aria-label]=\"'\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0438 \u043D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\">\n <img [src]=\"url\" [alt]=\"'\u041D\u043E\u0432\u0435 \u0444\u043E\u0442\u043E ' + (imageIndex + 1)\" class=\"h-full w-full object-cover\" />\n </button>\n }\n </div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isFileField(field.value)) {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [href]=\"field.value.to.url\" target=\"_blank\" rel=\"noopener noreferrer\">\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0444\u0430\u0439\u043B</a>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else if (isHtmlField(field.value)) {\n @if (field.value.to.display !== '\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E') {\n <div class=\"prose prose-sm max-w-none text-slate-900\" [innerHTML]=\"field.value.to.display\"></div>\n } @else {\n <span class=\"font-medium text-slate-900\">\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E</span>\n }\n } @else {\n @if (field.value.to.url) {\n <a class=\"font-medium text-sky-700 underline\" [routerLink]=\"field.value.to.url\">{{ field.value.to.display }}</a>\n } @else {\n <span class=\"font-medium text-slate-900\">{{ field.value.to.display }}</span>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </article>\n }\n </div>\n }\n</section>\n\n@if (isViewerOpen()) {\n <app-images-viewer [urls]=\"viewerUrls()\" (closed)=\"closeImageViewer()\" />\n}\n" }]
1879
1895
  }], ctorParameters: () => [], propDecorators: { entity: [{ type: i0.Input, args: [{ isSignal: true, alias: "entity", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });