@maro-tech/card 0.2.9 → 0.2.10
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.
|
@@ -6,12 +6,12 @@ import { input, inject, DestroyRef, signal, Component, computed, viewChild, view
|
|
|
6
6
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
7
7
|
import { EventBus, UiButtonComponent, UiToastService, UiModalComponent, UiConfirmService } from '@maro-tech/core';
|
|
8
8
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
9
|
+
import { RouterLink, ActivatedRoute, Router } from '@angular/router';
|
|
9
10
|
import Panzoom from '@panzoom/panzoom';
|
|
10
11
|
import { LucideDownload, LucideDynamicIcon, LucideEye, LucideFileText, LucidePlus, LucideSparkles, LucideTrash } from '@lucide/angular';
|
|
11
12
|
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
|
|
12
13
|
import { map, shareReplay, forkJoin, switchMap, timer, of } from 'rxjs';
|
|
13
14
|
import { UiTableComponent, UiPaginatorComponent } from '@maro-tech/table';
|
|
14
|
-
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
|
15
15
|
import { map as map$1, exhaustMap, catchError, takeWhile, takeUntil, finalize } from 'rxjs/operators';
|
|
16
16
|
import * as i1$1 from '@angular/forms';
|
|
17
17
|
import { FormsModule } from '@angular/forms';
|
|
@@ -486,6 +486,7 @@ class DetailsGridComponent {
|
|
|
486
486
|
...field,
|
|
487
487
|
displayValue: this.formatFieldValue(field),
|
|
488
488
|
imageSrc: this.getImageSrc(field),
|
|
489
|
+
linkUrl: this.getLinkUrl(field),
|
|
489
490
|
})), ...(ngDevMode ? [{ debugName: "displayFields" }] : /* istanbul ignore next */ []));
|
|
490
491
|
selectedImageSrc = signal(null, ...(ngDevMode ? [{ debugName: "selectedImageSrc" }] : /* istanbul ignore next */ []));
|
|
491
492
|
openViewer(imageSrc) {
|
|
@@ -560,6 +561,20 @@ class DetailsGridComponent {
|
|
|
560
561
|
}
|
|
561
562
|
return raw;
|
|
562
563
|
}
|
|
564
|
+
getLinkUrl(field) {
|
|
565
|
+
if (field.type !== 'link' || !field.link)
|
|
566
|
+
return null;
|
|
567
|
+
const data = this.data() || {};
|
|
568
|
+
const url = field.link.replace(/\{\{([a-zA-Z0-9_.-]+)\}\}/g, (_match, key) => {
|
|
569
|
+
const value = key.split('.').reduce((current, segment) => {
|
|
570
|
+
if (current == null || typeof current !== 'object')
|
|
571
|
+
return undefined;
|
|
572
|
+
return current[segment];
|
|
573
|
+
}, data);
|
|
574
|
+
return encodeURIComponent(String(value ?? ''));
|
|
575
|
+
}).trim();
|
|
576
|
+
return url && url !== '/' && !url.endsWith('/') ? url : null;
|
|
577
|
+
}
|
|
563
578
|
getImageSrc(field) {
|
|
564
579
|
if (field.type !== 'image')
|
|
565
580
|
return null;
|
|
@@ -591,11 +606,11 @@ class DetailsGridComponent {
|
|
|
591
606
|
: { day: '2-digit', month: '2-digit', year: 'numeric' }).format(date);
|
|
592
607
|
}
|
|
593
608
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DetailsGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
594
|
-
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"] }] });
|
|
609
|
+
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 if (field.type === 'link' && field.linkUrl) {\n <a class=\"mt-2 inline-block text-base font-semibold text-sky-800 underline\" [routerLink]=\"field.linkUrl\">{{ field.displayValue === '-' ? field.label : field.displayValue }}</a>\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"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
|
|
595
610
|
}
|
|
596
611
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: DetailsGridComponent, decorators: [{
|
|
597
612
|
type: Component,
|
|
598
|
-
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" }]
|
|
613
|
+
args: [{ selector: 'app-details-grid', standalone: true, imports: [CommonModule, ImagesViewerComponent, RouterLink], 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 if (field.type === 'link' && field.linkUrl) {\n <a class=\"mt-2 inline-block text-base font-semibold text-sky-800 underline\" [routerLink]=\"field.linkUrl\">{{ field.displayValue === '-' ? field.label : field.displayValue }}</a>\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" }]
|
|
599
614
|
}], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
|
|
600
615
|
|
|
601
616
|
class ImagesComponent {
|