@fovestta2/web-angular 1.0.24 → 1.0.25
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.
- package/esm2022/lib/fv-document-field/fv-document-field.component.mjs +38 -6
- package/esm2022/lib/fv-file-selector/fv-file-selector.component.mjs +34 -4
- package/esm2022/lib/fv-image-selector/fv-image-selector.component.mjs +22 -4
- package/fesm2022/fovestta2-web-angular.mjs +91 -11
- package/fesm2022/fovestta2-web-angular.mjs.map +1 -1
- package/lib/fv-document-field/fv-document-field.component.d.ts +2 -0
- package/lib/fv-file-selector/fv-file-selector.component.d.ts +1 -0
- package/lib/fv-image-selector/fv-image-selector.component.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1007,15 +1007,45 @@ class FvFileSelectorComponent {
|
|
|
1007
1007
|
}
|
|
1008
1008
|
// Subscribe to value changes
|
|
1009
1009
|
this.subscription = this.control.valueChanges.subscribe((value) => {
|
|
1010
|
+
this.handleValue(value);
|
|
1010
1011
|
this.validateValue(value);
|
|
1011
1012
|
this.valueChange.emit(value);
|
|
1012
1013
|
});
|
|
1013
1014
|
// Validate initial value
|
|
1014
|
-
|
|
1015
|
-
this.selectedFile = this.control.value;
|
|
1016
|
-
}
|
|
1015
|
+
this.handleValue(this.control.value);
|
|
1017
1016
|
this.validateValue(this.control.value);
|
|
1018
1017
|
}
|
|
1018
|
+
handleValue(value) {
|
|
1019
|
+
if (!value) {
|
|
1020
|
+
this.selectedFile = null;
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
if (typeof value === 'string') {
|
|
1024
|
+
// Handle API URL/String
|
|
1025
|
+
const name = value.split('/').pop() || 'Document';
|
|
1026
|
+
// Guess type from extension
|
|
1027
|
+
const ext = name.split('.').pop()?.toLowerCase() || '';
|
|
1028
|
+
let type = 'application/octet-stream';
|
|
1029
|
+
if (ext === 'pdf')
|
|
1030
|
+
type = 'application/pdf';
|
|
1031
|
+
if (['png', 'jpg', 'jpeg', 'gif'].includes(ext))
|
|
1032
|
+
type = `image/${ext}`;
|
|
1033
|
+
if (['xls', 'xlsx'].includes(ext))
|
|
1034
|
+
type = 'application/vnd.ms-excel';
|
|
1035
|
+
if (['doc', 'docx'].includes(ext))
|
|
1036
|
+
type = 'application/msword';
|
|
1037
|
+
this.selectedFile = {
|
|
1038
|
+
file: new File([''], name, { type }),
|
|
1039
|
+
name: name,
|
|
1040
|
+
size: 0,
|
|
1041
|
+
type: type
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
else {
|
|
1045
|
+
// Assume it's a FileInfo object
|
|
1046
|
+
this.selectedFile = value;
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1019
1049
|
ngOnDestroy() {
|
|
1020
1050
|
this.subscription?.unsubscribe();
|
|
1021
1051
|
}
|
|
@@ -1180,12 +1210,30 @@ class FvImageSelectorComponent {
|
|
|
1180
1210
|
if (!this.control)
|
|
1181
1211
|
return;
|
|
1182
1212
|
this.subscription = this.control.valueChanges.subscribe((value) => {
|
|
1213
|
+
this.handleValue(value);
|
|
1183
1214
|
this.validateValue(value);
|
|
1184
1215
|
this.valueChange.emit(value);
|
|
1185
1216
|
});
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1217
|
+
this.handleValue(this.control.value);
|
|
1218
|
+
this.validateValue(this.control.value);
|
|
1219
|
+
}
|
|
1220
|
+
handleValue(value) {
|
|
1221
|
+
if (!value) {
|
|
1222
|
+
this.selectedImage = null;
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
if (typeof value === 'string') {
|
|
1226
|
+
const name = value.split('/').pop() || 'Image';
|
|
1227
|
+
this.selectedImage = {
|
|
1228
|
+
file: new File([''], name, { type: 'image/jpeg' }),
|
|
1229
|
+
url: this.sanitizer.bypassSecurityTrustUrl(value),
|
|
1230
|
+
width: 0,
|
|
1231
|
+
height: 0,
|
|
1232
|
+
size: 0
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
else {
|
|
1236
|
+
this.selectedImage = value;
|
|
1189
1237
|
}
|
|
1190
1238
|
}
|
|
1191
1239
|
ngOnDestroy() {
|
|
@@ -2736,6 +2784,7 @@ class FvDocumentFieldComponent {
|
|
|
2736
2784
|
showPreview = false;
|
|
2737
2785
|
previewUrl = null;
|
|
2738
2786
|
subscription;
|
|
2787
|
+
fileInfo = null;
|
|
2739
2788
|
constructor(sanitizer) {
|
|
2740
2789
|
this.sanitizer = sanitizer;
|
|
2741
2790
|
}
|
|
@@ -2745,14 +2794,45 @@ class FvDocumentFieldComponent {
|
|
|
2745
2794
|
return;
|
|
2746
2795
|
}
|
|
2747
2796
|
this.subscription = this.control.valueChanges.subscribe((value) => {
|
|
2797
|
+
this.handleValue(value);
|
|
2748
2798
|
this.validateValue(value);
|
|
2749
2799
|
this.valueChange.emit(value);
|
|
2750
2800
|
});
|
|
2751
2801
|
// Initial validation
|
|
2802
|
+
this.handleValue(this.control.value);
|
|
2752
2803
|
if (this.control.value) {
|
|
2753
2804
|
this.validateValue(this.control.value);
|
|
2754
2805
|
}
|
|
2755
2806
|
}
|
|
2807
|
+
handleValue(value) {
|
|
2808
|
+
if (!value) {
|
|
2809
|
+
this.fileInfo = null;
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2812
|
+
if (typeof value === 'string') {
|
|
2813
|
+
const name = value.split('/').pop() || 'Document';
|
|
2814
|
+
// Guess type from extension
|
|
2815
|
+
const ext = name.split('.').pop()?.toLowerCase() || '';
|
|
2816
|
+
let type = 'application/octet-stream';
|
|
2817
|
+
if (ext === 'pdf')
|
|
2818
|
+
type = 'application/pdf';
|
|
2819
|
+
if (['png', 'jpg', 'jpeg', 'gif'].includes(ext))
|
|
2820
|
+
type = `image/${ext}`;
|
|
2821
|
+
if (['xls', 'xlsx'].includes(ext))
|
|
2822
|
+
type = 'application/vnd.ms-excel';
|
|
2823
|
+
if (['doc', 'docx'].includes(ext))
|
|
2824
|
+
type = 'application/msword';
|
|
2825
|
+
this.fileInfo = {
|
|
2826
|
+
file: value, // Store the URL string as file property if strict typing allows, or cast. Interface says file: File | Blob | string. Perfect.
|
|
2827
|
+
name: name,
|
|
2828
|
+
size: 0,
|
|
2829
|
+
type: type
|
|
2830
|
+
};
|
|
2831
|
+
}
|
|
2832
|
+
else {
|
|
2833
|
+
this.fileInfo = value;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2756
2836
|
ngOnDestroy() {
|
|
2757
2837
|
this.subscription?.unsubscribe();
|
|
2758
2838
|
}
|
|
@@ -2812,7 +2892,7 @@ class FvDocumentFieldComponent {
|
|
|
2812
2892
|
}
|
|
2813
2893
|
}
|
|
2814
2894
|
viewFile() {
|
|
2815
|
-
const fileInfo = this.
|
|
2895
|
+
const fileInfo = this.fileInfo;
|
|
2816
2896
|
if (!fileInfo)
|
|
2817
2897
|
return;
|
|
2818
2898
|
const type = fileInfo.type || '';
|
|
@@ -2844,7 +2924,7 @@ class FvDocumentFieldComponent {
|
|
|
2844
2924
|
this.previewUrl = null;
|
|
2845
2925
|
}
|
|
2846
2926
|
downloadFile() {
|
|
2847
|
-
const fileInfo = this.
|
|
2927
|
+
const fileInfo = this.fileInfo;
|
|
2848
2928
|
if (!fileInfo)
|
|
2849
2929
|
return;
|
|
2850
2930
|
let url;
|
|
@@ -2867,7 +2947,7 @@ class FvDocumentFieldComponent {
|
|
|
2867
2947
|
}
|
|
2868
2948
|
}
|
|
2869
2949
|
getFileIcon() {
|
|
2870
|
-
const fileInfo = this.
|
|
2950
|
+
const fileInfo = this.fileInfo;
|
|
2871
2951
|
if (!fileInfo)
|
|
2872
2952
|
return 'description';
|
|
2873
2953
|
const type = fileInfo.type || '';
|
|
@@ -2896,11 +2976,11 @@ class FvDocumentFieldComponent {
|
|
|
2896
2976
|
return errorMessages[this.errorMessage] || this.errorMessage;
|
|
2897
2977
|
}
|
|
2898
2978
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FvDocumentFieldComponent, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
|
|
2899
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: FvDocumentFieldComponent, isStandalone: true, selector: "fv-document-field", inputs: { label: "label", placeholder: "placeholder", schema: "schema", control: "control", disabled: "disabled", accept: "accept", maxSize: "maxSize" }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"fv-document-field-container\">\r\n <label *ngIf=\"label\" class=\"fv-document-field-label\">\r\n {{ label }}\r\n <span *ngIf=\"isRequired()\" class=\"required-asterisk\">*</span>\r\n </label>\r\n\r\n <input #fileInput type=\"file\" [accept]=\"accept\" (change)=\"onFileSelected($event)\" style=\"display: none\" />\r\n\r\n <div *ngIf=\"!
|
|
2979
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: FvDocumentFieldComponent, isStandalone: true, selector: "fv-document-field", inputs: { label: "label", placeholder: "placeholder", schema: "schema", control: "control", disabled: "disabled", accept: "accept", maxSize: "maxSize" }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"fv-document-field-container\">\r\n <label *ngIf=\"label\" class=\"fv-document-field-label\">\r\n {{ label }}\r\n <span *ngIf=\"isRequired()\" class=\"required-asterisk\">*</span>\r\n </label>\r\n\r\n <input #fileInput type=\"file\" [accept]=\"accept\" (change)=\"onFileSelected($event)\" style=\"display: none\" />\r\n\r\n <div *ngIf=\"!fileInfo; else fileUploaded\" class=\"fv-upload-btn-wrapper\">\r\n <button type=\"button\" class=\"fv-upload-button\" [disabled]=\"disabled\" (click)=\"openFileDialog()\">\r\n <span class=\"fv-upload-text\">{{ placeholder }}</span>\r\n <span class=\"fv-upload-icon-section\">\r\n <svg viewBox=\"0 0 24 24\" class=\"upload-icon\">\r\n <path d=\"M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z\" fill=\"currentColor\" />\r\n </svg>\r\n </span>\r\n </button>\r\n </div>\r\n\r\n <ng-template #fileUploaded>\r\n <div class=\"fv-preview-row\">\r\n <div class=\"fv-preview-wrapper\" (click)=\"viewFile()\" style=\"cursor: pointer;\">\r\n <div class=\"fv-file-icon-preview\" [ngClass]=\"getFileIcon()\">\r\n <span class=\"material-icons\">{{ getFileIcon() }}</span>\r\n </div>\r\n </div>\r\n <span class=\"fv-filename\" (click)=\"viewFile()\" style=\"cursor: pointer;\">{{ fileInfo?.name }}</span>\r\n <button type=\"button\" class=\"fv-trash-btn\" (click)=\"removeFile()\" [disabled]=\"disabled\">\r\n <svg viewBox=\"0 0 24 24\" class=\"trash-icon\">\r\n <path d=\"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </ng-template>\r\n\r\n <div *ngIf=\"errorMessage && control?.touched\" class=\"fv-document-error-message\">\r\n \u26A0 {{ getErrorMessage() }}\r\n </div>\r\n</div>\r\n\r\n<!-- Preview Overlay/Modal for Image -->\r\n<div *ngIf=\"showPreview\" class=\"fv-preview-overlay\" (click)=\"closePreview()\">\r\n <div class=\"fv-preview-content\" (click)=\"$event.stopPropagation()\">\r\n <img [src]=\"previewUrl\" alt=\"Preview\" />\r\n <div class=\"fv-preview-actions\">\r\n <button type=\"button\" class=\"fv-download-btn\" (click)=\"downloadFile()\">Download</button>\r\n <button type=\"button\" class=\"fv-close-btn\" (click)=\"closePreview()\">Close</button>\r\n </div>\r\n </div>\r\n</div>", styles: ["@import\"https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap\";.fv-document-field-container{display:flex;flex-direction:column;margin-bottom:16px;width:fit-content;max-width:100%;font-family:Poppins,sans-serif}.fv-document-field-label{font-size:14px;font-weight:600;color:#151d48;margin-bottom:6px;display:block}.required-asterisk{color:#e74c3c;font-weight:700}.fv-upload-button{display:flex;align-items:center;border:1px solid #dcdcdc;border-radius:8px;background:#fff;padding:0;cursor:pointer;overflow:hidden;width:100px;height:34px;transition:all .2s ease}.fv-upload-button:hover:not(:disabled){border-color:#bbb;box-shadow:0 2px 4px #0000000d}.fv-upload-button:disabled{cursor:not-allowed;background-color:#f9f9f9;opacity:.7}.fv-upload-text{flex:1;padding:0 16px;font-size:14px;color:#1f2b41;text-align:left;font-weight:500}.fv-upload-icon-section{background:#f4f5f7;padding:0 10px;border-left:1px solid #dcdcdc;display:flex;align-items:center;justify-content:center;color:#333;height:100%}.upload-icon{width:20px;height:20px}.fv-preview-row{display:flex;align-items:center;gap:8px;padding:8px 0;width:100px;box-sizing:border-box}.fv-preview-wrapper{position:relative;width:40px;height:40px}.fv-file-icon-preview{width:40px;height:40px;border-radius:8px;background:#f4f5f7;display:flex;align-items:center;justify-content:center;color:#3498db;border:1px solid #dcdcdc}.fv-file-icon-preview.picture_as_pdf{color:#e74c3c;background:#fdf2f2}.fv-file-icon-preview.image{color:#3498db;background:#f1f8fe}.fv-file-icon-preview.table_view{color:#27ae60;background:#f1f9f4}.material-icons{font-size:24px}.fv-filename{flex:1;font-size:14px;color:#666;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:300px}.fv-trash-btn{background:none;border:none;cursor:pointer;padding:6px;border-radius:50%;transition:background .2s;display:flex}.fv-trash-btn:hover:not(:disabled){background:#fee}.trash-icon{width:22px;height:22px;fill:red}.fv-document-error-message{margin-top:4px;font-size:12px;color:#e74c3c}.fv-preview-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000c;display:flex;justify-content:center;align-items:center;z-index:10000}.fv-preview-content{position:relative;background:#fff;padding:24px;border-radius:12px;max-width:90vw;max-height:90vh;display:flex;flex-direction:column;align-items:center}.fv-preview-content img{max-width:100%;max-height:70vh;object-fit:contain;border-radius:4px;margin-bottom:20px}.fv-preview-actions{display:flex;gap:16px}.fv-preview-actions button{padding:10px 24px;border-radius:6px;border:none;cursor:pointer;font-weight:500;transition:background .2s}.fv-download-btn{background:#3498db;color:#fff}.fv-download-btn:hover{background:#2980b9}.fv-close-btn{background:#f0f0f0;color:#333}.fv-close-btn:hover{background:#e0e0e0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
2900
2980
|
}
|
|
2901
2981
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FvDocumentFieldComponent, decorators: [{
|
|
2902
2982
|
type: Component,
|
|
2903
|
-
args: [{ standalone: true, imports: [CommonModule, ReactiveFormsModule], selector: 'fv-document-field', template: "<div class=\"fv-document-field-container\">\r\n <label *ngIf=\"label\" class=\"fv-document-field-label\">\r\n {{ label }}\r\n <span *ngIf=\"isRequired()\" class=\"required-asterisk\">*</span>\r\n </label>\r\n\r\n <input #fileInput type=\"file\" [accept]=\"accept\" (change)=\"onFileSelected($event)\" style=\"display: none\" />\r\n\r\n <div *ngIf=\"!
|
|
2983
|
+
args: [{ standalone: true, imports: [CommonModule, ReactiveFormsModule], selector: 'fv-document-field', template: "<div class=\"fv-document-field-container\">\r\n <label *ngIf=\"label\" class=\"fv-document-field-label\">\r\n {{ label }}\r\n <span *ngIf=\"isRequired()\" class=\"required-asterisk\">*</span>\r\n </label>\r\n\r\n <input #fileInput type=\"file\" [accept]=\"accept\" (change)=\"onFileSelected($event)\" style=\"display: none\" />\r\n\r\n <div *ngIf=\"!fileInfo; else fileUploaded\" class=\"fv-upload-btn-wrapper\">\r\n <button type=\"button\" class=\"fv-upload-button\" [disabled]=\"disabled\" (click)=\"openFileDialog()\">\r\n <span class=\"fv-upload-text\">{{ placeholder }}</span>\r\n <span class=\"fv-upload-icon-section\">\r\n <svg viewBox=\"0 0 24 24\" class=\"upload-icon\">\r\n <path d=\"M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z\" fill=\"currentColor\" />\r\n </svg>\r\n </span>\r\n </button>\r\n </div>\r\n\r\n <ng-template #fileUploaded>\r\n <div class=\"fv-preview-row\">\r\n <div class=\"fv-preview-wrapper\" (click)=\"viewFile()\" style=\"cursor: pointer;\">\r\n <div class=\"fv-file-icon-preview\" [ngClass]=\"getFileIcon()\">\r\n <span class=\"material-icons\">{{ getFileIcon() }}</span>\r\n </div>\r\n </div>\r\n <span class=\"fv-filename\" (click)=\"viewFile()\" style=\"cursor: pointer;\">{{ fileInfo?.name }}</span>\r\n <button type=\"button\" class=\"fv-trash-btn\" (click)=\"removeFile()\" [disabled]=\"disabled\">\r\n <svg viewBox=\"0 0 24 24\" class=\"trash-icon\">\r\n <path d=\"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </ng-template>\r\n\r\n <div *ngIf=\"errorMessage && control?.touched\" class=\"fv-document-error-message\">\r\n \u26A0 {{ getErrorMessage() }}\r\n </div>\r\n</div>\r\n\r\n<!-- Preview Overlay/Modal for Image -->\r\n<div *ngIf=\"showPreview\" class=\"fv-preview-overlay\" (click)=\"closePreview()\">\r\n <div class=\"fv-preview-content\" (click)=\"$event.stopPropagation()\">\r\n <img [src]=\"previewUrl\" alt=\"Preview\" />\r\n <div class=\"fv-preview-actions\">\r\n <button type=\"button\" class=\"fv-download-btn\" (click)=\"downloadFile()\">Download</button>\r\n <button type=\"button\" class=\"fv-close-btn\" (click)=\"closePreview()\">Close</button>\r\n </div>\r\n </div>\r\n</div>", styles: ["@import\"https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap\";.fv-document-field-container{display:flex;flex-direction:column;margin-bottom:16px;width:fit-content;max-width:100%;font-family:Poppins,sans-serif}.fv-document-field-label{font-size:14px;font-weight:600;color:#151d48;margin-bottom:6px;display:block}.required-asterisk{color:#e74c3c;font-weight:700}.fv-upload-button{display:flex;align-items:center;border:1px solid #dcdcdc;border-radius:8px;background:#fff;padding:0;cursor:pointer;overflow:hidden;width:100px;height:34px;transition:all .2s ease}.fv-upload-button:hover:not(:disabled){border-color:#bbb;box-shadow:0 2px 4px #0000000d}.fv-upload-button:disabled{cursor:not-allowed;background-color:#f9f9f9;opacity:.7}.fv-upload-text{flex:1;padding:0 16px;font-size:14px;color:#1f2b41;text-align:left;font-weight:500}.fv-upload-icon-section{background:#f4f5f7;padding:0 10px;border-left:1px solid #dcdcdc;display:flex;align-items:center;justify-content:center;color:#333;height:100%}.upload-icon{width:20px;height:20px}.fv-preview-row{display:flex;align-items:center;gap:8px;padding:8px 0;width:100px;box-sizing:border-box}.fv-preview-wrapper{position:relative;width:40px;height:40px}.fv-file-icon-preview{width:40px;height:40px;border-radius:8px;background:#f4f5f7;display:flex;align-items:center;justify-content:center;color:#3498db;border:1px solid #dcdcdc}.fv-file-icon-preview.picture_as_pdf{color:#e74c3c;background:#fdf2f2}.fv-file-icon-preview.image{color:#3498db;background:#f1f8fe}.fv-file-icon-preview.table_view{color:#27ae60;background:#f1f9f4}.material-icons{font-size:24px}.fv-filename{flex:1;font-size:14px;color:#666;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:300px}.fv-trash-btn{background:none;border:none;cursor:pointer;padding:6px;border-radius:50%;transition:background .2s;display:flex}.fv-trash-btn:hover:not(:disabled){background:#fee}.trash-icon{width:22px;height:22px;fill:red}.fv-document-error-message{margin-top:4px;font-size:12px;color:#e74c3c}.fv-preview-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#000c;display:flex;justify-content:center;align-items:center;z-index:10000}.fv-preview-content{position:relative;background:#fff;padding:24px;border-radius:12px;max-width:90vw;max-height:90vh;display:flex;flex-direction:column;align-items:center}.fv-preview-content img{max-width:100%;max-height:70vh;object-fit:contain;border-radius:4px;margin-bottom:20px}.fv-preview-actions{display:flex;gap:16px}.fv-preview-actions button{padding:10px 24px;border-radius:6px;border:none;cursor:pointer;font-weight:500;transition:background .2s}.fv-download-btn{background:#3498db;color:#fff}.fv-download-btn:hover{background:#2980b9}.fv-close-btn{background:#f0f0f0;color:#333}.fv-close-btn:hover{background:#e0e0e0}\n"] }]
|
|
2904
2984
|
}], ctorParameters: () => [{ type: i1$1.DomSanitizer }], propDecorators: { label: [{
|
|
2905
2985
|
type: Input
|
|
2906
2986
|
}], placeholder: [{
|