osl-base-extended 2.0.37 → 3.0.1
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.
|
@@ -403,12 +403,13 @@ class Httpbase {
|
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
405
|
/** Multipart file upload — do NOT pass Content-Type; browser sets the boundary */
|
|
406
|
-
async upload(methodName, formData) {
|
|
406
|
+
async upload(methodName, formData, params) {
|
|
407
407
|
try {
|
|
408
408
|
const res = await firstValueFrom(this.http
|
|
409
409
|
.post(this.getEndPoint(methodName), formData, {
|
|
410
410
|
observe: 'response',
|
|
411
411
|
headers: this.getUploadHeaders(),
|
|
412
|
+
params: this.buildParams(params || [])
|
|
412
413
|
})
|
|
413
414
|
.pipe(timeout(60000)));
|
|
414
415
|
return this.handleSuccess(res.status, res.body, res.headers);
|
|
@@ -5371,6 +5372,217 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
5371
5372
|
args: ['click', ['$event']]
|
|
5372
5373
|
}] } });
|
|
5373
5374
|
|
|
5375
|
+
class OslDocumentUploader {
|
|
5376
|
+
label = '';
|
|
5377
|
+
required = false;
|
|
5378
|
+
disabled = false;
|
|
5379
|
+
multiple = false;
|
|
5380
|
+
accept = '';
|
|
5381
|
+
maxSize = 0;
|
|
5382
|
+
minFiles = 0;
|
|
5383
|
+
maxFiles = 0;
|
|
5384
|
+
showUploadButton = false;
|
|
5385
|
+
uploadButtonLabel = 'Upload Files';
|
|
5386
|
+
savedDocuments = [];
|
|
5387
|
+
skeletonLoading = false;
|
|
5388
|
+
skeletonTheme = 'light';
|
|
5389
|
+
uploadCallback = new EventEmitter();
|
|
5390
|
+
viewCallback = new EventEmitter();
|
|
5391
|
+
deleteCallback = new EventEmitter();
|
|
5392
|
+
downloadCallback = new EventEmitter();
|
|
5393
|
+
filesChanged = new EventEmitter();
|
|
5394
|
+
pendingFiles = [];
|
|
5395
|
+
isDragOver = false;
|
|
5396
|
+
sizeErrors = [];
|
|
5397
|
+
touched = false;
|
|
5398
|
+
get maxFilesReached() {
|
|
5399
|
+
return this.multiple && this.maxFiles > 0 && this.pendingFiles.length >= this.maxFiles;
|
|
5400
|
+
}
|
|
5401
|
+
get isBelowMin() {
|
|
5402
|
+
return this.minFiles > 0 && this.pendingFiles.length > 0 && this.pendingFiles.length < this.minFiles;
|
|
5403
|
+
}
|
|
5404
|
+
get isInvalid() {
|
|
5405
|
+
if (!this.touched)
|
|
5406
|
+
return false;
|
|
5407
|
+
if (this.required && this.pendingFiles.length === 0)
|
|
5408
|
+
return true;
|
|
5409
|
+
return this.isBelowMin;
|
|
5410
|
+
}
|
|
5411
|
+
get requiredError() {
|
|
5412
|
+
return this.touched && this.required && this.pendingFiles.length === 0;
|
|
5413
|
+
}
|
|
5414
|
+
get minFilesError() {
|
|
5415
|
+
return this.touched && this.isBelowMin;
|
|
5416
|
+
}
|
|
5417
|
+
get maxSizeLabel() {
|
|
5418
|
+
if (!this.maxSize)
|
|
5419
|
+
return '';
|
|
5420
|
+
if (this.maxSize >= 1024 * 1024)
|
|
5421
|
+
return `Max ${(this.maxSize / 1024 / 1024).toFixed(1)} MB`;
|
|
5422
|
+
if (this.maxSize >= 1024)
|
|
5423
|
+
return `Max ${(this.maxSize / 1024).toFixed(0)} KB`;
|
|
5424
|
+
return `Max ${this.maxSize} B`;
|
|
5425
|
+
}
|
|
5426
|
+
getFileSize(bytes) {
|
|
5427
|
+
if (bytes >= 1024 * 1024)
|
|
5428
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
5429
|
+
if (bytes >= 1024)
|
|
5430
|
+
return `${(bytes / 1024).toFixed(0)} KB`;
|
|
5431
|
+
return `${bytes} B`;
|
|
5432
|
+
}
|
|
5433
|
+
getFileType(name) {
|
|
5434
|
+
const ext = name.split('.').pop()?.toLowerCase() || '';
|
|
5435
|
+
if (['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'bmp', 'ico'].includes(ext))
|
|
5436
|
+
return 'image';
|
|
5437
|
+
if (ext === 'pdf')
|
|
5438
|
+
return 'pdf';
|
|
5439
|
+
if (['doc', 'docx'].includes(ext))
|
|
5440
|
+
return 'word';
|
|
5441
|
+
if (['xls', 'xlsx', 'csv'].includes(ext))
|
|
5442
|
+
return 'excel';
|
|
5443
|
+
if (['zip', 'rar', '7z', 'tar', 'gz'].includes(ext))
|
|
5444
|
+
return 'archive';
|
|
5445
|
+
return 'generic';
|
|
5446
|
+
}
|
|
5447
|
+
formatDate(value) {
|
|
5448
|
+
if (!value)
|
|
5449
|
+
return '';
|
|
5450
|
+
const d = new Date(value);
|
|
5451
|
+
if (isNaN(d.getTime()))
|
|
5452
|
+
return String(value);
|
|
5453
|
+
return d.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });
|
|
5454
|
+
}
|
|
5455
|
+
onFileChange(event) {
|
|
5456
|
+
this.touched = true;
|
|
5457
|
+
const input = event.target;
|
|
5458
|
+
this.processFiles(input.files);
|
|
5459
|
+
input.value = '';
|
|
5460
|
+
}
|
|
5461
|
+
onDragOver(event) {
|
|
5462
|
+
event.preventDefault();
|
|
5463
|
+
if (!this.disabled && !this.maxFilesReached)
|
|
5464
|
+
this.isDragOver = true;
|
|
5465
|
+
}
|
|
5466
|
+
onDragLeave(event) {
|
|
5467
|
+
const target = event.currentTarget;
|
|
5468
|
+
const related = event.relatedTarget;
|
|
5469
|
+
if (!related || !target.contains(related))
|
|
5470
|
+
this.isDragOver = false;
|
|
5471
|
+
}
|
|
5472
|
+
onDrop(event) {
|
|
5473
|
+
event.preventDefault();
|
|
5474
|
+
this.isDragOver = false;
|
|
5475
|
+
if (this.disabled || this.maxFilesReached)
|
|
5476
|
+
return;
|
|
5477
|
+
this.touched = true;
|
|
5478
|
+
this.processFiles(event.dataTransfer?.files ?? null);
|
|
5479
|
+
}
|
|
5480
|
+
processFiles(files) {
|
|
5481
|
+
if (!files || files.length === 0)
|
|
5482
|
+
return;
|
|
5483
|
+
this.sizeErrors = [];
|
|
5484
|
+
const newFiles = [];
|
|
5485
|
+
for (let i = 0; i < files.length; i++) {
|
|
5486
|
+
const file = files[i];
|
|
5487
|
+
if (this.maxSize > 0 && file.size > this.maxSize) {
|
|
5488
|
+
this.sizeErrors.push(`"${file.name}" exceeds the ${this.maxSizeLabel} limit.`);
|
|
5489
|
+
continue;
|
|
5490
|
+
}
|
|
5491
|
+
newFiles.push(file);
|
|
5492
|
+
}
|
|
5493
|
+
if (this.multiple) {
|
|
5494
|
+
const remaining = this.maxFiles > 0 ? this.maxFiles - this.pendingFiles.length : newFiles.length;
|
|
5495
|
+
const toAdd = newFiles.slice(0, remaining);
|
|
5496
|
+
if (newFiles.length > remaining) {
|
|
5497
|
+
this.sizeErrors.push(`Only ${remaining} more file(s) can be added. ${newFiles.length - remaining} skipped.`);
|
|
5498
|
+
}
|
|
5499
|
+
this.pendingFiles = [...this.pendingFiles, ...toAdd];
|
|
5500
|
+
}
|
|
5501
|
+
else {
|
|
5502
|
+
this.pendingFiles = newFiles.slice(0, 1);
|
|
5503
|
+
}
|
|
5504
|
+
this.filesChanged.emit(this.pendingFiles);
|
|
5505
|
+
}
|
|
5506
|
+
removeFile(index) {
|
|
5507
|
+
this.pendingFiles = this.pendingFiles.filter((_, i) => i !== index);
|
|
5508
|
+
this.filesChanged.emit(this.pendingFiles);
|
|
5509
|
+
}
|
|
5510
|
+
triggerInput(fileInput) {
|
|
5511
|
+
if (!this.disabled && !this.maxFilesReached)
|
|
5512
|
+
fileInput.click();
|
|
5513
|
+
}
|
|
5514
|
+
upload() {
|
|
5515
|
+
if (this.pendingFiles.length === 0)
|
|
5516
|
+
return;
|
|
5517
|
+
const formData = new FormData();
|
|
5518
|
+
if (this.multiple) {
|
|
5519
|
+
this.pendingFiles.forEach(file => formData.append('files', file, file.name));
|
|
5520
|
+
}
|
|
5521
|
+
else {
|
|
5522
|
+
formData.append('file', this.pendingFiles[0], this.pendingFiles[0].name);
|
|
5523
|
+
}
|
|
5524
|
+
this.uploadCallback.emit(formData);
|
|
5525
|
+
}
|
|
5526
|
+
onView(doc) { this.viewCallback.emit(doc); }
|
|
5527
|
+
onDelete(doc) { this.deleteCallback.emit(doc); }
|
|
5528
|
+
onDownload(doc) { this.downloadCallback.emit(doc); }
|
|
5529
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslDocumentUploader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5530
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslDocumentUploader, isStandalone: false, selector: "osl-document-uploader", inputs: { label: "label", required: "required", disabled: "disabled", multiple: "multiple", accept: "accept", maxSize: "maxSize", minFiles: "minFiles", maxFiles: "maxFiles", showUploadButton: "showUploadButton", uploadButtonLabel: "uploadButtonLabel", savedDocuments: "savedDocuments", skeletonLoading: "skeletonLoading", skeletonTheme: "skeletonTheme" }, outputs: { uploadCallback: "uploadCallback", viewCallback: "viewCallback", deleteCallback: "deleteCallback", downloadCallback: "downloadCallback", filesChanged: "filesChanged" }, ngImport: i0, template: "<div class=\"du-container\" [class.du--disabled]=\"disabled\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\n\n @if (label) {\n <label class=\"du-label\" [class.du-label--error]=\"isInvalid\">\n <span class=\"du-label__text\" [title]=\"label\">{{ label }}</span>\n @if (required) { <span class=\"du-label__req\">*</span> }\n </label>\n }\n\n <input type=\"file\" [accept]=\"accept\" [multiple]=\"multiple\" [disabled]=\"disabled || maxFilesReached\"\n (change)=\"onFileChange($event)\" #fileInput class=\"du-file-input\">\n\n <!-- \u2500\u2500 Drop Zone \u2500\u2500 -->\n <div class=\"du-dropzone\"\n [class.du-dropzone--over]=\"isDragOver\"\n [class.du-dropzone--error]=\"isInvalid\"\n [class.du-dropzone--disabled]=\"disabled\"\n [class.du-dropzone--maxed]=\"maxFilesReached\"\n (click)=\"triggerInput(fileInput)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n\n <div class=\"du-particles\">\n <span class=\"du-p du-p--1\"></span>\n <span class=\"du-p du-p--2\"></span>\n <span class=\"du-p du-p--3\"></span>\n <span class=\"du-p du-p--4\"></span>\n <span class=\"du-p du-p--5\"></span>\n <span class=\"du-p du-p--6\"></span>\n </div>\n\n <div class=\"du-dropzone__inner\">\n\n @if (maxFilesReached) {\n <!-- Max files reached state -->\n <div class=\"du-maxed-icon\">\n <svg viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"32\" cy=\"32\" r=\"28\" fill=\"#f0fdf4\" stroke=\"#86efac\" stroke-width=\"2\"/>\n <path d=\"M20 32l8 8 16-16\" stroke=\"#22c55e\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n <p class=\"du-dropzone__headline\">\n <span class=\"du-gradient-text du-gradient-text--green\">Limit reached</span>\n </p>\n <p class=\"du-maxed-sub\">{{ maxFiles }} / {{ maxFiles }} files added</p>\n } @else {\n\n <!-- Cloud SVG -->\n <div class=\"du-cloud-wrap\" [class.du-cloud-wrap--over]=\"isDragOver\">\n <svg class=\"du-cloud-svg\" viewBox=\"0 0 90 72\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path class=\"du-cloud-body\"\n d=\"M63 42H27C19.8 42 14 36.2 14 29C14 22.2 19.2 16.7 25.8 16.1C25.9 9.4 31.3 4 38 4C42.8 4 47 6.7 49.2 10.7C50.8 9.6 52.8 9 55 9C61 9 65.9 13.9 65.9 19.9V20.1C72.1 20.9 77 26.3 77 33C77 38.1 70.7 42 63 42Z\"\n stroke=\"#667eea\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <line class=\"du-arrow\" x1=\"45\" y1=\"64\" x2=\"45\" y2=\"46\" stroke=\"#764ba2\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <polyline class=\"du-arrow\" points=\"37,55 45,46 53,55\"\n stroke=\"#764ba2\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/>\n <circle class=\"du-cloud-glint\" cx=\"30\" cy=\"26\" r=\"3\" fill=\"#a5b4fc\" opacity=\"0.5\"/>\n </svg>\n </div>\n\n @if (!isDragOver) {\n <p class=\"du-dropzone__headline\">\n <span class=\"du-gradient-text\">Click to browse</span><span class=\"du-or\"> or drag & drop</span>\n </p>\n <div class=\"du-dropzone__meta\">\n @if (multiple) {\n @if (maxFiles > 0 && minFiles > 0) {\n <span class=\"du-chip du-chip--info\">{{ minFiles }}\u2013{{ maxFiles }} files</span>\n } @else if (maxFiles > 0) {\n <span class=\"du-chip du-chip--info\">Max {{ maxFiles }} files</span>\n } @else if (minFiles > 0) {\n <span class=\"du-chip du-chip--info\">Min {{ minFiles }} files</span>\n } @else {\n <span class=\"du-chip du-chip--info\">Multiple files</span>\n }\n } @else {\n <span class=\"du-chip du-chip--info\">Single file</span>\n }\n @if (accept) { <span class=\"du-chip\">{{ accept }}</span> }\n @if (maxSize) { <span class=\"du-chip\">{{ maxSizeLabel }}</span> }\n </div>\n } @else {\n <p class=\"du-dropzone__headline du-dropzone__headline--drop\">\n <span class=\"du-gradient-text\">Release to drop!</span>\n </p>\n }\n\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Errors \u2500\u2500 -->\n @for (err of sizeErrors; track err) {\n <div class=\"du-msg du-msg--error\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"17\" r=\"1.2\" fill=\"currentColor\"/>\n </svg>\n {{ err }}\n </div>\n }\n @if (requiredError) {\n <div class=\"du-msg du-msg--error\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"17\" r=\"1.2\" fill=\"currentColor\"/>\n </svg>\n {{ label || 'File' }} is required!\n </div>\n }\n @if (minFilesError) {\n <div class=\"du-msg du-msg--error\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"17\" r=\"1.2\" fill=\"currentColor\"/>\n </svg>\n At least {{ minFiles }} files are required ({{ pendingFiles.length }} added).\n </div>\n }\n\n <!-- \u2500\u2500 Pending Files \u2500\u2500 -->\n @if (pendingFiles.length > 0) {\n <div class=\"du-section\">\n <div class=\"du-section__hdr\">\n <span class=\"du-section__title\">Queued Files</span>\n @if (multiple && maxFiles > 0) {\n <span class=\"du-count-label\" [class.du-count-label--full]=\"maxFilesReached\">\n {{ pendingFiles.length }} / {{ maxFiles }}\n </span>\n } @else {\n <span class=\"du-count du-count--purple\">{{ pendingFiles.length }}</span>\n }\n </div>\n <div class=\"du-file-list\">\n @for (file of pendingFiles; track file.name; let i = $index) {\n <div class=\"du-file-card\" [attr.data-ftype]=\"getFileType(file.name)\" [style.animation-delay]=\"i * 40 + 'ms'\">\n\n <div class=\"du-file-icon\">\n @switch (getFileType(file.name)) {\n @case ('pdf') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#FEE2E2\"/>\n <path d=\"M26 4v10h10\" fill=\"#FECACA\"/>\n <rect x=\"4\" y=\"28\" width=\"32\" height=\"12\" rx=\"2\" fill=\"#EF4444\"/>\n <text x=\"20\" y=\"38\" text-anchor=\"middle\" fill=\"white\" font-size=\"7\" font-weight=\"800\" font-family=\"sans-serif\">PDF</text>\n </svg>\n }\n @case ('word') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#DBEAFE\"/>\n <path d=\"M26 4v10h10\" fill=\"#BFDBFE\"/>\n <rect x=\"4\" y=\"28\" width=\"32\" height=\"12\" rx=\"2\" fill=\"#3B82F6\"/>\n <text x=\"20\" y=\"38\" text-anchor=\"middle\" fill=\"white\" font-size=\"7\" font-weight=\"800\" font-family=\"sans-serif\">DOC</text>\n </svg>\n }\n @case ('excel') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#DCFCE7\"/>\n <path d=\"M26 4v10h10\" fill=\"#BBF7D0\"/>\n <rect x=\"4\" y=\"28\" width=\"32\" height=\"12\" rx=\"2\" fill=\"#22C55E\"/>\n <text x=\"20\" y=\"38\" text-anchor=\"middle\" fill=\"white\" font-size=\"7\" font-weight=\"800\" font-family=\"sans-serif\">XLS</text>\n </svg>\n }\n @case ('image') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#FEF9C3\"/>\n <path d=\"M26 4v10h10\" fill=\"#FEF08A\"/>\n <rect x=\"6\" y=\"18\" width=\"28\" height=\"18\" rx=\"2\" fill=\"#FDE047\"/>\n <circle cx=\"13\" cy=\"24\" r=\"3\" fill=\"#CA8A04\"/>\n <path d=\"M6 36l9-9 5 5 4-4 10 8H6Z\" fill=\"#EAB308\" opacity=\"0.8\"/>\n </svg>\n }\n @case ('archive') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#EDE9FE\"/>\n <path d=\"M26 4v10h10\" fill=\"#DDD6FE\"/>\n <rect x=\"14\" y=\"12\" width=\"12\" height=\"4\" rx=\"1\" fill=\"#A78BFA\"/>\n <rect x=\"14\" y=\"18\" width=\"12\" height=\"4\" rx=\"1\" fill=\"#C4B5FD\"/>\n <rect x=\"14\" y=\"24\" width=\"12\" height=\"4\" rx=\"1\" fill=\"#A78BFA\"/>\n <rect x=\"14\" y=\"30\" width=\"12\" height=\"4\" rx=\"1\" fill=\"#C4B5FD\"/>\n <rect x=\"16\" y=\"26\" width=\"8\" height=\"6\" rx=\"1\" fill=\"#7C3AED\"/>\n </svg>\n }\n @default {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#F1F5F9\"/>\n <path d=\"M26 4v10h10\" fill=\"#E2E8F0\"/>\n <line x1=\"10\" y1=\"24\" x2=\"30\" y2=\"24\" stroke=\"#94A3B8\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <line x1=\"10\" y1=\"30\" x2=\"26\" y2=\"30\" stroke=\"#94A3B8\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <line x1=\"10\" y1=\"36\" x2=\"22\" y2=\"36\" stroke=\"#94A3B8\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n }\n }\n </div>\n\n <div class=\"du-file-info\">\n <span class=\"du-file-name\" [title]=\"file.name\">{{ file.name }}</span>\n <span class=\"du-file-size\">{{ getFileSize(file.size) }}</span>\n </div>\n\n <button type=\"button\" class=\"du-remove-btn\" (click)=\"removeFile(i)\" title=\"Remove\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <path d=\"M15 9L9 15M9 9l6 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- \u2500\u2500 Upload Button \u2500\u2500 -->\n @if (showUploadButton && pendingFiles.length > 0) {\n <button type=\"button\" class=\"du-upload-btn\" (click)=\"upload()\" [disabled]=\"disabled\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"17\" height=\"17\">\n <path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\"/>\n <polyline points=\"17,8 12,3 7,8\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/>\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\"/>\n </svg>\n {{ uploadButtonLabel }}\n <span class=\"du-upload-btn__badge\">{{ pendingFiles.length }}</span>\n </button>\n }\n\n <!-- \u2500\u2500 Saved Documents \u2500\u2500 -->\n @if (savedDocuments.length > 0) {\n <div class=\"du-section\">\n <div class=\"du-section__hdr\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"du-section__icon\">\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" stroke=\"#10b981\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <polyline points=\"14,2 14,8 20,8\" stroke=\"#10b981\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n <span class=\"du-section__title\">Saved Documents</span>\n <span class=\"du-count du-count--green\">{{ savedDocuments.length }}</span>\n </div>\n <div class=\"du-saved-list\">\n @for (doc of savedDocuments; track doc.id; let i = $index) {\n <div class=\"du-saved-card\" [style.animation-delay]=\"i * 50 + 'ms'\">\n\n <div class=\"du-saved-icon\">\n @switch (getFileType(doc.name)) {\n @case ('pdf') {\n <svg viewBox=\"0 0 32 38\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 3h16l8 8v24a1.5 1.5 0 01-1.5 1.5H4A1.5 1.5 0 012.5 35V4.5A1.5 1.5 0 014 3z\" fill=\"#FEE2E2\"/>\n <path d=\"M20 3v8h8\" fill=\"#FECACA\"/>\n <rect x=\"2\" y=\"22\" width=\"28\" height=\"10\" rx=\"2\" fill=\"#EF4444\"/>\n <text x=\"16\" y=\"30\" text-anchor=\"middle\" fill=\"white\" font-size=\"6\" font-weight=\"800\" font-family=\"sans-serif\">PDF</text>\n </svg>\n }\n @case ('word') {\n <svg viewBox=\"0 0 32 38\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 3h16l8 8v24a1.5 1.5 0 01-1.5 1.5H4A1.5 1.5 0 012.5 35V4.5A1.5 1.5 0 014 3z\" fill=\"#DBEAFE\"/>\n <path d=\"M20 3v8h8\" fill=\"#BFDBFE\"/>\n <rect x=\"2\" y=\"22\" width=\"28\" height=\"10\" rx=\"2\" fill=\"#3B82F6\"/>\n <text x=\"16\" y=\"30\" text-anchor=\"middle\" fill=\"white\" font-size=\"6\" font-weight=\"800\" font-family=\"sans-serif\">DOC</text>\n </svg>\n }\n @case ('excel') {\n <svg viewBox=\"0 0 32 38\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 3h16l8 8v24a1.5 1.5 0 01-1.5 1.5H4A1.5 1.5 0 012.5 35V4.5A1.5 1.5 0 014 3z\" fill=\"#DCFCE7\"/>\n <path d=\"M20 3v8h8\" fill=\"#BBF7D0\"/>\n <rect x=\"2\" y=\"22\" width=\"28\" height=\"10\" rx=\"2\" fill=\"#22C55E\"/>\n <text x=\"16\" y=\"30\" text-anchor=\"middle\" fill=\"white\" font-size=\"6\" font-weight=\"800\" font-family=\"sans-serif\">XLS</text>\n </svg>\n }\n @case ('image') {\n <svg viewBox=\"0 0 32 32\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"32\" height=\"32\" rx=\"6\" fill=\"#FEF9C3\"/>\n <rect x=\"4\" y=\"7\" width=\"24\" height=\"18\" rx=\"2\" fill=\"#FDE047\"/>\n <circle cx=\"10\" cy=\"13\" r=\"2.5\" fill=\"#CA8A04\"/>\n <path d=\"M4 25l8-8 5 5 4-4 11 7H4Z\" fill=\"#EAB308\" opacity=\"0.7\"/>\n </svg>\n }\n @case ('archive') {\n <svg viewBox=\"0 0 32 32\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"32\" height=\"32\" rx=\"6\" fill=\"#EDE9FE\"/>\n <rect x=\"4\" y=\"8\" width=\"24\" height=\"5\" rx=\"1.5\" fill=\"#A78BFA\"/>\n <rect x=\"4\" y=\"14\" width=\"24\" height=\"14\" rx=\"2\" fill=\"#C4B5FD\"/>\n <rect x=\"11\" y=\"18\" width=\"10\" height=\"6\" rx=\"1.5\" fill=\"#7C3AED\"/>\n <line x1=\"16\" y1=\"18\" x2=\"16\" y2=\"24\" stroke=\"white\" stroke-width=\"1.5\"/>\n </svg>\n }\n @default {\n <svg viewBox=\"0 0 32 38\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 3h16l8 8v24a1.5 1.5 0 01-1.5 1.5H4A1.5 1.5 0 012.5 35V4.5A1.5 1.5 0 014 3z\" fill=\"#F1F5F9\"/>\n <path d=\"M20 3v8h8\" fill=\"#E2E8F0\"/>\n <line x1=\"7\" y1=\"20\" x2=\"25\" y2=\"20\" stroke=\"#94A3B8\" stroke-width=\"1.8\" stroke-linecap=\"round\"/>\n <line x1=\"7\" y1=\"25\" x2=\"21\" y2=\"25\" stroke=\"#94A3B8\" stroke-width=\"1.8\" stroke-linecap=\"round\"/>\n <line x1=\"7\" y1=\"30\" x2=\"17\" y2=\"30\" stroke=\"#94A3B8\" stroke-width=\"1.8\" stroke-linecap=\"round\"/>\n </svg>\n }\n }\n </div>\n\n <div class=\"du-saved-info\">\n <span class=\"du-saved-name\" [title]=\"doc.name\">{{ doc.name }}</span>\n @if (doc.addBy || doc.addOn) {\n <span class=\"du-saved-meta\">\n @if (doc.addBy) { <span class=\"du-saved-by\">{{ doc.addBy }}</span> }\n @if (doc.addBy && doc.addOn) { <span class=\"du-saved-sep\">\u00B7</span> }\n @if (doc.addOn) { <span class=\"du-saved-on\">{{ formatDate(doc.addOn) }}</span> }\n </span>\n }\n </div>\n\n <div class=\"du-saved-actions\">\n <button type=\"button\" class=\"du-act du-act--view\" (click)=\"onView(doc)\" title=\"View\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"12\" r=\"3\" stroke=\"currentColor\" stroke-width=\"2\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"du-act du-act--download\" (click)=\"onDownload(doc)\" title=\"Download\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <polyline points=\"7,10 12,15 17,10\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/>\n <line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"du-act du-act--delete\" (click)=\"onDelete(doc)\" title=\"Delete\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <polyline points=\"3,6 5,6 21,6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path d=\"M10 11v6M14 11v6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </button>\n </div>\n\n </div>\n }\n </div>\n </div>\n }\n\n</div>\n", styles: ["@keyframes du-float{0%,to{transform:translateY(0)}50%{transform:translateY(-9px)}}@keyframes du-arrow-bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}@keyframes du-particle{0%,to{transform:translate(0) scale(1);opacity:.25}33%{transform:translate(4px,-14px) scale(1.15);opacity:.5}66%{transform:translate(-4px,-7px) scale(.88);opacity:.2}}@keyframes du-slide-in{0%{opacity:0;transform:translate(18px)}to{opacity:1;transform:translate(0)}}@keyframes du-fade-up{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes du-pop-in{0%{opacity:0;transform:scale(.8)}70%{transform:scale(1.06)}to{opacity:1;transform:scale(1)}}@keyframes du-glow-pulse{0%,to{box-shadow:0 0 #667eea59}50%{box-shadow:0 0 0 8px #667eea00}}@keyframes du-btn-pulse{0%,to{box-shadow:0 4px 20px #667eea66}50%{box-shadow:0 6px 30px #764ba299}}@keyframes du-gradient-shift{0%{background-position:0% 50%}50%{background-position:100% 50%}to{background-position:0% 50%}}@keyframes du-ripple{0%{transform:scale(.6);opacity:.7}to{transform:scale(2.2);opacity:0}}@keyframes du-glint{0%,80%,to{opacity:0;transform:scale(.5)}40%{opacity:.7;transform:scale(1.4)}}.du-container{display:flex;flex-direction:column;gap:10px;width:100%}.du-container.du--disabled{opacity:.55;pointer-events:none}.du-label{display:flex;align-items:center;gap:2px;font-size:var(--osl-label-font-size, 13px);font-weight:500;color:#374151;overflow:hidden}.du-label--error{color:var(--osl-error-color, #ef4444)}.du-label__text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.du-label__req{color:var(--osl-error-color, #ef4444);flex-shrink:0;font-weight:700}.du-file-input{display:none}.du-dropzone{position:relative;width:100%;min-height:158px;border-radius:18px;border:2px dashed rgba(102,126,234,.35);background:linear-gradient(145deg,#fafbff,#f5f3ff);cursor:pointer;overflow:hidden;transition:border-color .3s ease,background .3s ease,box-shadow .3s ease,transform .25s ease}.du-dropzone:hover:not(.du-dropzone--disabled){border-color:#667eeab3;background:linear-gradient(145deg,#f5f3ff,#ede9fe);transform:translateY(-2px);box-shadow:0 10px 30px #667eea1f}.du-dropzone--over{border:2px solid #667eea!important;background:linear-gradient(145deg,#ede9fe,#ddd6fe)!important;transform:scale(1.012) translateY(-3px)!important;box-shadow:0 18px 40px #667eea38,inset 0 0 0 1px #667eea4d!important}.du-dropzone--over .du-cloud-body{stroke:#764ba2}.du-dropzone--over .du-cloud-glint{animation:du-glint .6s ease infinite}.du-dropzone--error{border-color:#ef444480;background:linear-gradient(145deg,#fff5f5,#fee2e2);animation:du-glow-pulse 1.8s ease infinite}.du-dropzone--disabled{cursor:not-allowed;background:#f9fafb!important;border-color:#e5e7eb!important;box-shadow:none!important;transform:none!important}.du-particles{position:absolute;inset:0;pointer-events:none;overflow:hidden}.du-p{position:absolute;border-radius:50%;background:radial-gradient(circle,#667eea38,#764ba21f);animation:du-particle var(--dur, 4s) ease-in-out infinite}.du-p--1{width:22px;height:22px;top:12%;left:6%;--dur: 4.2s;animation-delay:0s}.du-p--2{width:14px;height:14px;top:65%;left:88%;--dur: 5.1s;animation-delay:.9s}.du-p--3{width:18px;height:18px;top:18%;left:82%;--dur: 3.8s;animation-delay:1.6s}.du-p--4{width:10px;height:10px;top:75%;left:12%;--dur: 6.3s;animation-delay:.4s}.du-p--5{width:16px;height:16px;top:50%;left:48%;--dur: 4.7s;animation-delay:2.1s}.du-p--6{width:8px;height:8px;top:30%;left:38%;--dur: 5.5s;animation-delay:1.1s}.du-dropzone__inner{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:26px 20px;min-height:158px}.du-cloud-wrap{width:80px;height:64px;animation:du-float 3.2s ease-in-out infinite;filter:drop-shadow(0 4px 10px rgba(102,126,234,.2));transition:filter .3s ease;flex-shrink:0}.du-cloud-wrap--over{animation-duration:1.2s;filter:drop-shadow(0 6px 18px rgba(102,126,234,.45))}.du-cloud-svg{width:100%;height:100%}.du-cloud-body{transition:stroke .3s ease}.du-cloud-glint{transform-origin:center}.du-arrow{animation:du-arrow-bounce 1.6s ease-in-out infinite}.du-dropzone__headline{margin:0;font-size:14px;color:#6b7280;line-height:1.5;text-align:center}.du-dropzone__headline--drop .du-gradient-text{animation:du-glow-pulse .7s ease infinite}.du-gradient-text{background:linear-gradient(135deg,#667eea,#764ba2);background-size:200% 200%;-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-weight:700;animation:du-gradient-shift 3s ease infinite}.du-or{color:#9ca3af;font-size:13px}.du-dropzone__meta{display:flex;flex-wrap:wrap;justify-content:center;gap:6px}.du-chip{border-radius:20px;padding:2px 10px;font-size:11px;font-weight:500;background:#667eea14;color:#7c6fcd;border:1px solid rgba(102,126,234,.18);transition:background .2s}.du-chip--info{background:#10b98114;color:#059669;border-color:#10b98133}.du-msg{display:flex;align-items:center;gap:6px;font-size:var(--osl-hint-font-size, 11px);animation:du-fade-up .2s ease}.du-msg svg{flex-shrink:0}.du-msg--error{color:var(--osl-error-color, #ef4444)}.du-section{display:flex;flex-direction:column;gap:8px;animation:du-fade-up .3s ease}.du-section__hdr{display:flex;align-items:center;gap:7px}.du-section__icon{flex-shrink:0}.du-section__title{font-size:11px;font-weight:700;color:#9ca3af;text-transform:uppercase;letter-spacing:.07em}.du-count{width:19px;height:19px;border-radius:50%;font-size:10px;font-weight:800;color:#fff;display:flex;align-items:center;justify-content:center;flex-shrink:0;animation:du-pop-in .3s ease}.du-count--purple{background:linear-gradient(135deg,#667eea,#764ba2)}.du-count--green{background:linear-gradient(135deg,#10b981,#059669)}.du-file-list{display:flex;flex-direction:column;gap:7px}.du-file-card{display:flex;align-items:center;gap:11px;padding:10px 14px 10px 16px;background:#fff;border-radius:13px;border:1px solid #e9ecf1;animation:du-slide-in .28s ease both;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease;position:relative}.du-file-card:before{content:\"\";position:absolute;left:0;top:50%;transform:translateY(-50%);width:4px;height:60%;border-radius:0 4px 4px 0;transition:height .2s ease}.du-file-card[data-ftype=pdf]:before{background:#ef4444}.du-file-card[data-ftype=word]:before{background:#3b82f6}.du-file-card[data-ftype=excel]:before{background:#22c55e}.du-file-card[data-ftype=image]:before{background:#f59e0b}.du-file-card[data-ftype=archive]:before{background:#8b5cf6}.du-file-card[data-ftype=generic]:before{background:#94a3b8}.du-file-card:hover{border-color:#c4b5fd;box-shadow:0 3px 14px #667eea1a;transform:translate(3px)}.du-file-card:hover:before{height:75%}.du-file-icon{width:38px;height:46px;flex-shrink:0}.du-file-icon svg{width:100%;height:100%}.du-file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}.du-file-name{font-size:13px;font-weight:600;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.du-file-size{font-size:11px;color:#94a3b8;font-weight:500}.du-remove-btn{width:30px;height:30px;flex-shrink:0;border-radius:50%;border:1.5px solid #fecaca;background:#fef2f2;color:#fca5a5;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:6px;transition:all .22s ease}.du-remove-btn svg{width:100%;height:100%}.du-remove-btn:hover{background:#fee2e2;border-color:#ef4444;color:#ef4444;transform:rotate(90deg) scale(1.1);box-shadow:0 3px 10px #ef444440}.du-upload-btn{display:flex;align-items:center;justify-content:center;gap:8px;padding:12px 24px;width:100%;border:none;border-radius:13px;background:linear-gradient(135deg,#667eea,#764ba2);background-size:200% 200%;color:#fff;font-size:14px;font-weight:700;letter-spacing:.03em;cursor:pointer;transition:transform .25s ease,box-shadow .25s ease;animation:du-btn-pulse 2.5s ease-in-out infinite,du-gradient-shift 4s ease infinite}.du-upload-btn svg{flex-shrink:0;transition:transform .25s ease}.du-upload-btn:hover:not([disabled]){transform:translateY(-3px);box-shadow:0 10px 28px #667eea80;animation:du-gradient-shift 1.5s ease infinite}.du-upload-btn:hover:not([disabled]) svg{transform:translateY(-3px)}.du-upload-btn:active:not([disabled]){transform:translateY(-1px)}.du-upload-btn[disabled]{opacity:.45;cursor:not-allowed;animation:none}.du-upload-btn__badge{min-width:22px;height:22px;padding:0 6px;border-radius:11px;background:#ffffff38;font-size:11px;font-weight:800;display:flex;align-items:center;justify-content:center;animation:du-pop-in .3s ease}.du-saved-list{display:flex;flex-direction:column;gap:7px}.du-saved-card{display:flex;align-items:center;gap:11px;padding:10px 12px;background:linear-gradient(135deg,#fff,#f8faff);border-radius:13px;border:1px solid #e9ecf1;opacity:0;animation:du-fade-up .32s ease forwards;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease}.du-saved-card:hover{border-color:#a5b4fc;box-shadow:0 4px 18px #667eea1a;transform:translateY(-1px)}.du-saved-icon{width:32px;height:38px;flex-shrink:0}.du-saved-icon svg{width:100%;height:100%}.du-saved-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}.du-saved-name{font-size:13px;font-weight:600;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.du-saved-size{font-size:11px;color:#94a3b8;font-weight:500}.du-saved-actions{display:flex;align-items:center;gap:5px;flex-shrink:0}.du-act{width:32px;height:32px;border-radius:9px;border:1.5px solid transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:7px;transition:all .22s ease;position:relative;overflow:hidden}.du-act svg{width:100%;height:100%;transition:transform .22s ease}.du-act:after{content:\"\";position:absolute;inset:50%;border-radius:50%;transition:all 0s;pointer-events:none}.du-act:active:after{inset:0;border-radius:9px;background:#ffffff59;animation:du-ripple .4s ease}.du-act--view{background:#eff6ff;color:#3b82f6;border-color:#bfdbfe}.du-act--view:hover{background:#dbeafe;border-color:#93c5fd;box-shadow:0 3px 12px #3b82f64d}.du-act--view:hover svg{transform:scale(1.12)}.du-act--download{background:#f0fdf4;color:#22c55e;border-color:#bbf7d0}.du-act--download:hover{background:#dcfce7;border-color:#86efac;box-shadow:0 3px 12px #22c55e4d}.du-act--download:hover svg{transform:translateY(2px) scale(1.08)}.du-act--delete{background:#fef2f2;color:#ef4444;border-color:#fecaca}.du-act--delete:hover{background:#fee2e2;border-color:#fca5a5;box-shadow:0 3px 12px #ef44444d}.du-act--delete:hover svg{transform:scale(1.1) rotate(-5deg)}.du-dropzone--maxed{cursor:default;border-color:#22c55e66!important;background:linear-gradient(145deg,#f0fdf4,#dcfce7)!important;pointer-events:none}.du-dropzone--maxed .du-particles .du-p{background:radial-gradient(circle,#22c55e2e,#10b9811a)}.du-maxed-icon{width:56px;height:56px;animation:du-pop-in .4s cubic-bezier(.34,1.56,.64,1)}.du-maxed-icon svg{width:100%;height:100%}.du-gradient-text--green{background:linear-gradient(135deg,#22c55e,#059669)!important;background-size:200% 200%!important;-webkit-background-clip:text!important;-webkit-text-fill-color:transparent!important;background-clip:text!important}.du-maxed-sub{margin:0;font-size:12px;color:#6b7280;font-weight:500}.du-count-label{font-size:11px;font-weight:700;padding:2px 9px;border-radius:20px;background:#667eea1a;color:#667eea;border:1px solid rgba(102,126,234,.2);transition:all .25s ease;animation:du-pop-in .3s ease}.du-count-label--full{background:#22c55e1a;color:#16a34a;border-color:#22c55e40}.du-saved-meta{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.du-saved-by{font-size:11px;font-weight:600;color:#667eea}.du-saved-sep{font-size:11px;color:#d1d5db}.du-saved-on{font-size:11px;color:#94a3b8}\n"], dependencies: [{ kind: "directive", type: OslSkeletonDirective, selector: "[oslSkeleton]", inputs: ["oslSkeleton", "oslSkeletonType", "oslSkeletonAnimation", "oslSkeletonTheme", "oslSkeletonColor", "oslSkeletonHighlight", "oslSkeletonRadius", "oslSkeletonRows", "oslSkeletonRowGap", "oslSkeletonZIndex", "oslSkeletonDelay", "oslSkeletonDuration", "oslSkeletonMinHeight", "oslSkeletonForceReread", "oslSkeletonCircleSize", "oslSkeletonListItems", "oslSkeletonTableRows", "oslSkeletonTableCols", "oslSkeletonCardLines", "oslSkeletonBgColor"] }] });
|
|
5531
|
+
}
|
|
5532
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslDocumentUploader, decorators: [{
|
|
5533
|
+
type: Component,
|
|
5534
|
+
args: [{ selector: 'osl-document-uploader', standalone: false, template: "<div class=\"du-container\" [class.du--disabled]=\"disabled\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\n\n @if (label) {\n <label class=\"du-label\" [class.du-label--error]=\"isInvalid\">\n <span class=\"du-label__text\" [title]=\"label\">{{ label }}</span>\n @if (required) { <span class=\"du-label__req\">*</span> }\n </label>\n }\n\n <input type=\"file\" [accept]=\"accept\" [multiple]=\"multiple\" [disabled]=\"disabled || maxFilesReached\"\n (change)=\"onFileChange($event)\" #fileInput class=\"du-file-input\">\n\n <!-- \u2500\u2500 Drop Zone \u2500\u2500 -->\n <div class=\"du-dropzone\"\n [class.du-dropzone--over]=\"isDragOver\"\n [class.du-dropzone--error]=\"isInvalid\"\n [class.du-dropzone--disabled]=\"disabled\"\n [class.du-dropzone--maxed]=\"maxFilesReached\"\n (click)=\"triggerInput(fileInput)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n\n <div class=\"du-particles\">\n <span class=\"du-p du-p--1\"></span>\n <span class=\"du-p du-p--2\"></span>\n <span class=\"du-p du-p--3\"></span>\n <span class=\"du-p du-p--4\"></span>\n <span class=\"du-p du-p--5\"></span>\n <span class=\"du-p du-p--6\"></span>\n </div>\n\n <div class=\"du-dropzone__inner\">\n\n @if (maxFilesReached) {\n <!-- Max files reached state -->\n <div class=\"du-maxed-icon\">\n <svg viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"32\" cy=\"32\" r=\"28\" fill=\"#f0fdf4\" stroke=\"#86efac\" stroke-width=\"2\"/>\n <path d=\"M20 32l8 8 16-16\" stroke=\"#22c55e\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n <p class=\"du-dropzone__headline\">\n <span class=\"du-gradient-text du-gradient-text--green\">Limit reached</span>\n </p>\n <p class=\"du-maxed-sub\">{{ maxFiles }} / {{ maxFiles }} files added</p>\n } @else {\n\n <!-- Cloud SVG -->\n <div class=\"du-cloud-wrap\" [class.du-cloud-wrap--over]=\"isDragOver\">\n <svg class=\"du-cloud-svg\" viewBox=\"0 0 90 72\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path class=\"du-cloud-body\"\n d=\"M63 42H27C19.8 42 14 36.2 14 29C14 22.2 19.2 16.7 25.8 16.1C25.9 9.4 31.3 4 38 4C42.8 4 47 6.7 49.2 10.7C50.8 9.6 52.8 9 55 9C61 9 65.9 13.9 65.9 19.9V20.1C72.1 20.9 77 26.3 77 33C77 38.1 70.7 42 63 42Z\"\n stroke=\"#667eea\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <line class=\"du-arrow\" x1=\"45\" y1=\"64\" x2=\"45\" y2=\"46\" stroke=\"#764ba2\" stroke-width=\"2.5\" stroke-linecap=\"round\"/>\n <polyline class=\"du-arrow\" points=\"37,55 45,46 53,55\"\n stroke=\"#764ba2\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/>\n <circle class=\"du-cloud-glint\" cx=\"30\" cy=\"26\" r=\"3\" fill=\"#a5b4fc\" opacity=\"0.5\"/>\n </svg>\n </div>\n\n @if (!isDragOver) {\n <p class=\"du-dropzone__headline\">\n <span class=\"du-gradient-text\">Click to browse</span><span class=\"du-or\"> or drag & drop</span>\n </p>\n <div class=\"du-dropzone__meta\">\n @if (multiple) {\n @if (maxFiles > 0 && minFiles > 0) {\n <span class=\"du-chip du-chip--info\">{{ minFiles }}\u2013{{ maxFiles }} files</span>\n } @else if (maxFiles > 0) {\n <span class=\"du-chip du-chip--info\">Max {{ maxFiles }} files</span>\n } @else if (minFiles > 0) {\n <span class=\"du-chip du-chip--info\">Min {{ minFiles }} files</span>\n } @else {\n <span class=\"du-chip du-chip--info\">Multiple files</span>\n }\n } @else {\n <span class=\"du-chip du-chip--info\">Single file</span>\n }\n @if (accept) { <span class=\"du-chip\">{{ accept }}</span> }\n @if (maxSize) { <span class=\"du-chip\">{{ maxSizeLabel }}</span> }\n </div>\n } @else {\n <p class=\"du-dropzone__headline du-dropzone__headline--drop\">\n <span class=\"du-gradient-text\">Release to drop!</span>\n </p>\n }\n\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Errors \u2500\u2500 -->\n @for (err of sizeErrors; track err) {\n <div class=\"du-msg du-msg--error\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"17\" r=\"1.2\" fill=\"currentColor\"/>\n </svg>\n {{ err }}\n </div>\n }\n @if (requiredError) {\n <div class=\"du-msg du-msg--error\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"17\" r=\"1.2\" fill=\"currentColor\"/>\n </svg>\n {{ label || 'File' }} is required!\n </div>\n }\n @if (minFilesError) {\n <div class=\"du-msg du-msg--error\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"17\" r=\"1.2\" fill=\"currentColor\"/>\n </svg>\n At least {{ minFiles }} files are required ({{ pendingFiles.length }} added).\n </div>\n }\n\n <!-- \u2500\u2500 Pending Files \u2500\u2500 -->\n @if (pendingFiles.length > 0) {\n <div class=\"du-section\">\n <div class=\"du-section__hdr\">\n <span class=\"du-section__title\">Queued Files</span>\n @if (multiple && maxFiles > 0) {\n <span class=\"du-count-label\" [class.du-count-label--full]=\"maxFilesReached\">\n {{ pendingFiles.length }} / {{ maxFiles }}\n </span>\n } @else {\n <span class=\"du-count du-count--purple\">{{ pendingFiles.length }}</span>\n }\n </div>\n <div class=\"du-file-list\">\n @for (file of pendingFiles; track file.name; let i = $index) {\n <div class=\"du-file-card\" [attr.data-ftype]=\"getFileType(file.name)\" [style.animation-delay]=\"i * 40 + 'ms'\">\n\n <div class=\"du-file-icon\">\n @switch (getFileType(file.name)) {\n @case ('pdf') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#FEE2E2\"/>\n <path d=\"M26 4v10h10\" fill=\"#FECACA\"/>\n <rect x=\"4\" y=\"28\" width=\"32\" height=\"12\" rx=\"2\" fill=\"#EF4444\"/>\n <text x=\"20\" y=\"38\" text-anchor=\"middle\" fill=\"white\" font-size=\"7\" font-weight=\"800\" font-family=\"sans-serif\">PDF</text>\n </svg>\n }\n @case ('word') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#DBEAFE\"/>\n <path d=\"M26 4v10h10\" fill=\"#BFDBFE\"/>\n <rect x=\"4\" y=\"28\" width=\"32\" height=\"12\" rx=\"2\" fill=\"#3B82F6\"/>\n <text x=\"20\" y=\"38\" text-anchor=\"middle\" fill=\"white\" font-size=\"7\" font-weight=\"800\" font-family=\"sans-serif\">DOC</text>\n </svg>\n }\n @case ('excel') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#DCFCE7\"/>\n <path d=\"M26 4v10h10\" fill=\"#BBF7D0\"/>\n <rect x=\"4\" y=\"28\" width=\"32\" height=\"12\" rx=\"2\" fill=\"#22C55E\"/>\n <text x=\"20\" y=\"38\" text-anchor=\"middle\" fill=\"white\" font-size=\"7\" font-weight=\"800\" font-family=\"sans-serif\">XLS</text>\n </svg>\n }\n @case ('image') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#FEF9C3\"/>\n <path d=\"M26 4v10h10\" fill=\"#FEF08A\"/>\n <rect x=\"6\" y=\"18\" width=\"28\" height=\"18\" rx=\"2\" fill=\"#FDE047\"/>\n <circle cx=\"13\" cy=\"24\" r=\"3\" fill=\"#CA8A04\"/>\n <path d=\"M6 36l9-9 5 5 4-4 10 8H6Z\" fill=\"#EAB308\" opacity=\"0.8\"/>\n </svg>\n }\n @case ('archive') {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#EDE9FE\"/>\n <path d=\"M26 4v10h10\" fill=\"#DDD6FE\"/>\n <rect x=\"14\" y=\"12\" width=\"12\" height=\"4\" rx=\"1\" fill=\"#A78BFA\"/>\n <rect x=\"14\" y=\"18\" width=\"12\" height=\"4\" rx=\"1\" fill=\"#C4B5FD\"/>\n <rect x=\"14\" y=\"24\" width=\"12\" height=\"4\" rx=\"1\" fill=\"#A78BFA\"/>\n <rect x=\"14\" y=\"30\" width=\"12\" height=\"4\" rx=\"1\" fill=\"#C4B5FD\"/>\n <rect x=\"16\" y=\"26\" width=\"8\" height=\"6\" rx=\"1\" fill=\"#7C3AED\"/>\n </svg>\n }\n @default {\n <svg viewBox=\"0 0 40 48\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 4h20l10 10v30a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2z\" fill=\"#F1F5F9\"/>\n <path d=\"M26 4v10h10\" fill=\"#E2E8F0\"/>\n <line x1=\"10\" y1=\"24\" x2=\"30\" y2=\"24\" stroke=\"#94A3B8\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <line x1=\"10\" y1=\"30\" x2=\"26\" y2=\"30\" stroke=\"#94A3B8\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <line x1=\"10\" y1=\"36\" x2=\"22\" y2=\"36\" stroke=\"#94A3B8\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n }\n }\n </div>\n\n <div class=\"du-file-info\">\n <span class=\"du-file-name\" [title]=\"file.name\">{{ file.name }}</span>\n <span class=\"du-file-size\">{{ getFileSize(file.size) }}</span>\n </div>\n\n <button type=\"button\" class=\"du-remove-btn\" (click)=\"removeFile(i)\" title=\"Remove\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <path d=\"M15 9L9 15M9 9l6 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- \u2500\u2500 Upload Button \u2500\u2500 -->\n @if (showUploadButton && pendingFiles.length > 0) {\n <button type=\"button\" class=\"du-upload-btn\" (click)=\"upload()\" [disabled]=\"disabled\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"17\" height=\"17\">\n <path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\"/>\n <polyline points=\"17,8 12,3 7,8\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/>\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\"/>\n </svg>\n {{ uploadButtonLabel }}\n <span class=\"du-upload-btn__badge\">{{ pendingFiles.length }}</span>\n </button>\n }\n\n <!-- \u2500\u2500 Saved Documents \u2500\u2500 -->\n @if (savedDocuments.length > 0) {\n <div class=\"du-section\">\n <div class=\"du-section__hdr\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"du-section__icon\">\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" stroke=\"#10b981\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <polyline points=\"14,2 14,8 20,8\" stroke=\"#10b981\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n <span class=\"du-section__title\">Saved Documents</span>\n <span class=\"du-count du-count--green\">{{ savedDocuments.length }}</span>\n </div>\n <div class=\"du-saved-list\">\n @for (doc of savedDocuments; track doc.id; let i = $index) {\n <div class=\"du-saved-card\" [style.animation-delay]=\"i * 50 + 'ms'\">\n\n <div class=\"du-saved-icon\">\n @switch (getFileType(doc.name)) {\n @case ('pdf') {\n <svg viewBox=\"0 0 32 38\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 3h16l8 8v24a1.5 1.5 0 01-1.5 1.5H4A1.5 1.5 0 012.5 35V4.5A1.5 1.5 0 014 3z\" fill=\"#FEE2E2\"/>\n <path d=\"M20 3v8h8\" fill=\"#FECACA\"/>\n <rect x=\"2\" y=\"22\" width=\"28\" height=\"10\" rx=\"2\" fill=\"#EF4444\"/>\n <text x=\"16\" y=\"30\" text-anchor=\"middle\" fill=\"white\" font-size=\"6\" font-weight=\"800\" font-family=\"sans-serif\">PDF</text>\n </svg>\n }\n @case ('word') {\n <svg viewBox=\"0 0 32 38\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 3h16l8 8v24a1.5 1.5 0 01-1.5 1.5H4A1.5 1.5 0 012.5 35V4.5A1.5 1.5 0 014 3z\" fill=\"#DBEAFE\"/>\n <path d=\"M20 3v8h8\" fill=\"#BFDBFE\"/>\n <rect x=\"2\" y=\"22\" width=\"28\" height=\"10\" rx=\"2\" fill=\"#3B82F6\"/>\n <text x=\"16\" y=\"30\" text-anchor=\"middle\" fill=\"white\" font-size=\"6\" font-weight=\"800\" font-family=\"sans-serif\">DOC</text>\n </svg>\n }\n @case ('excel') {\n <svg viewBox=\"0 0 32 38\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 3h16l8 8v24a1.5 1.5 0 01-1.5 1.5H4A1.5 1.5 0 012.5 35V4.5A1.5 1.5 0 014 3z\" fill=\"#DCFCE7\"/>\n <path d=\"M20 3v8h8\" fill=\"#BBF7D0\"/>\n <rect x=\"2\" y=\"22\" width=\"28\" height=\"10\" rx=\"2\" fill=\"#22C55E\"/>\n <text x=\"16\" y=\"30\" text-anchor=\"middle\" fill=\"white\" font-size=\"6\" font-weight=\"800\" font-family=\"sans-serif\">XLS</text>\n </svg>\n }\n @case ('image') {\n <svg viewBox=\"0 0 32 32\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"32\" height=\"32\" rx=\"6\" fill=\"#FEF9C3\"/>\n <rect x=\"4\" y=\"7\" width=\"24\" height=\"18\" rx=\"2\" fill=\"#FDE047\"/>\n <circle cx=\"10\" cy=\"13\" r=\"2.5\" fill=\"#CA8A04\"/>\n <path d=\"M4 25l8-8 5 5 4-4 11 7H4Z\" fill=\"#EAB308\" opacity=\"0.7\"/>\n </svg>\n }\n @case ('archive') {\n <svg viewBox=\"0 0 32 32\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"32\" height=\"32\" rx=\"6\" fill=\"#EDE9FE\"/>\n <rect x=\"4\" y=\"8\" width=\"24\" height=\"5\" rx=\"1.5\" fill=\"#A78BFA\"/>\n <rect x=\"4\" y=\"14\" width=\"24\" height=\"14\" rx=\"2\" fill=\"#C4B5FD\"/>\n <rect x=\"11\" y=\"18\" width=\"10\" height=\"6\" rx=\"1.5\" fill=\"#7C3AED\"/>\n <line x1=\"16\" y1=\"18\" x2=\"16\" y2=\"24\" stroke=\"white\" stroke-width=\"1.5\"/>\n </svg>\n }\n @default {\n <svg viewBox=\"0 0 32 38\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 3h16l8 8v24a1.5 1.5 0 01-1.5 1.5H4A1.5 1.5 0 012.5 35V4.5A1.5 1.5 0 014 3z\" fill=\"#F1F5F9\"/>\n <path d=\"M20 3v8h8\" fill=\"#E2E8F0\"/>\n <line x1=\"7\" y1=\"20\" x2=\"25\" y2=\"20\" stroke=\"#94A3B8\" stroke-width=\"1.8\" stroke-linecap=\"round\"/>\n <line x1=\"7\" y1=\"25\" x2=\"21\" y2=\"25\" stroke=\"#94A3B8\" stroke-width=\"1.8\" stroke-linecap=\"round\"/>\n <line x1=\"7\" y1=\"30\" x2=\"17\" y2=\"30\" stroke=\"#94A3B8\" stroke-width=\"1.8\" stroke-linecap=\"round\"/>\n </svg>\n }\n }\n </div>\n\n <div class=\"du-saved-info\">\n <span class=\"du-saved-name\" [title]=\"doc.name\">{{ doc.name }}</span>\n @if (doc.addBy || doc.addOn) {\n <span class=\"du-saved-meta\">\n @if (doc.addBy) { <span class=\"du-saved-by\">{{ doc.addBy }}</span> }\n @if (doc.addBy && doc.addOn) { <span class=\"du-saved-sep\">\u00B7</span> }\n @if (doc.addOn) { <span class=\"du-saved-on\">{{ formatDate(doc.addOn) }}</span> }\n </span>\n }\n </div>\n\n <div class=\"du-saved-actions\">\n <button type=\"button\" class=\"du-act du-act--view\" (click)=\"onView(doc)\" title=\"View\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <circle cx=\"12\" cy=\"12\" r=\"3\" stroke=\"currentColor\" stroke-width=\"2\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"du-act du-act--download\" (click)=\"onDownload(doc)\" title=\"Download\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <polyline points=\"7,10 12,15 17,10\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/>\n <line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"du-act du-act--delete\" (click)=\"onDelete(doc)\" title=\"Delete\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <polyline points=\"3,6 5,6 21,6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path d=\"M10 11v6M14 11v6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </button>\n </div>\n\n </div>\n }\n </div>\n </div>\n }\n\n</div>\n", styles: ["@keyframes du-float{0%,to{transform:translateY(0)}50%{transform:translateY(-9px)}}@keyframes du-arrow-bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}@keyframes du-particle{0%,to{transform:translate(0) scale(1);opacity:.25}33%{transform:translate(4px,-14px) scale(1.15);opacity:.5}66%{transform:translate(-4px,-7px) scale(.88);opacity:.2}}@keyframes du-slide-in{0%{opacity:0;transform:translate(18px)}to{opacity:1;transform:translate(0)}}@keyframes du-fade-up{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes du-pop-in{0%{opacity:0;transform:scale(.8)}70%{transform:scale(1.06)}to{opacity:1;transform:scale(1)}}@keyframes du-glow-pulse{0%,to{box-shadow:0 0 #667eea59}50%{box-shadow:0 0 0 8px #667eea00}}@keyframes du-btn-pulse{0%,to{box-shadow:0 4px 20px #667eea66}50%{box-shadow:0 6px 30px #764ba299}}@keyframes du-gradient-shift{0%{background-position:0% 50%}50%{background-position:100% 50%}to{background-position:0% 50%}}@keyframes du-ripple{0%{transform:scale(.6);opacity:.7}to{transform:scale(2.2);opacity:0}}@keyframes du-glint{0%,80%,to{opacity:0;transform:scale(.5)}40%{opacity:.7;transform:scale(1.4)}}.du-container{display:flex;flex-direction:column;gap:10px;width:100%}.du-container.du--disabled{opacity:.55;pointer-events:none}.du-label{display:flex;align-items:center;gap:2px;font-size:var(--osl-label-font-size, 13px);font-weight:500;color:#374151;overflow:hidden}.du-label--error{color:var(--osl-error-color, #ef4444)}.du-label__text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.du-label__req{color:var(--osl-error-color, #ef4444);flex-shrink:0;font-weight:700}.du-file-input{display:none}.du-dropzone{position:relative;width:100%;min-height:158px;border-radius:18px;border:2px dashed rgba(102,126,234,.35);background:linear-gradient(145deg,#fafbff,#f5f3ff);cursor:pointer;overflow:hidden;transition:border-color .3s ease,background .3s ease,box-shadow .3s ease,transform .25s ease}.du-dropzone:hover:not(.du-dropzone--disabled){border-color:#667eeab3;background:linear-gradient(145deg,#f5f3ff,#ede9fe);transform:translateY(-2px);box-shadow:0 10px 30px #667eea1f}.du-dropzone--over{border:2px solid #667eea!important;background:linear-gradient(145deg,#ede9fe,#ddd6fe)!important;transform:scale(1.012) translateY(-3px)!important;box-shadow:0 18px 40px #667eea38,inset 0 0 0 1px #667eea4d!important}.du-dropzone--over .du-cloud-body{stroke:#764ba2}.du-dropzone--over .du-cloud-glint{animation:du-glint .6s ease infinite}.du-dropzone--error{border-color:#ef444480;background:linear-gradient(145deg,#fff5f5,#fee2e2);animation:du-glow-pulse 1.8s ease infinite}.du-dropzone--disabled{cursor:not-allowed;background:#f9fafb!important;border-color:#e5e7eb!important;box-shadow:none!important;transform:none!important}.du-particles{position:absolute;inset:0;pointer-events:none;overflow:hidden}.du-p{position:absolute;border-radius:50%;background:radial-gradient(circle,#667eea38,#764ba21f);animation:du-particle var(--dur, 4s) ease-in-out infinite}.du-p--1{width:22px;height:22px;top:12%;left:6%;--dur: 4.2s;animation-delay:0s}.du-p--2{width:14px;height:14px;top:65%;left:88%;--dur: 5.1s;animation-delay:.9s}.du-p--3{width:18px;height:18px;top:18%;left:82%;--dur: 3.8s;animation-delay:1.6s}.du-p--4{width:10px;height:10px;top:75%;left:12%;--dur: 6.3s;animation-delay:.4s}.du-p--5{width:16px;height:16px;top:50%;left:48%;--dur: 4.7s;animation-delay:2.1s}.du-p--6{width:8px;height:8px;top:30%;left:38%;--dur: 5.5s;animation-delay:1.1s}.du-dropzone__inner{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:26px 20px;min-height:158px}.du-cloud-wrap{width:80px;height:64px;animation:du-float 3.2s ease-in-out infinite;filter:drop-shadow(0 4px 10px rgba(102,126,234,.2));transition:filter .3s ease;flex-shrink:0}.du-cloud-wrap--over{animation-duration:1.2s;filter:drop-shadow(0 6px 18px rgba(102,126,234,.45))}.du-cloud-svg{width:100%;height:100%}.du-cloud-body{transition:stroke .3s ease}.du-cloud-glint{transform-origin:center}.du-arrow{animation:du-arrow-bounce 1.6s ease-in-out infinite}.du-dropzone__headline{margin:0;font-size:14px;color:#6b7280;line-height:1.5;text-align:center}.du-dropzone__headline--drop .du-gradient-text{animation:du-glow-pulse .7s ease infinite}.du-gradient-text{background:linear-gradient(135deg,#667eea,#764ba2);background-size:200% 200%;-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-weight:700;animation:du-gradient-shift 3s ease infinite}.du-or{color:#9ca3af;font-size:13px}.du-dropzone__meta{display:flex;flex-wrap:wrap;justify-content:center;gap:6px}.du-chip{border-radius:20px;padding:2px 10px;font-size:11px;font-weight:500;background:#667eea14;color:#7c6fcd;border:1px solid rgba(102,126,234,.18);transition:background .2s}.du-chip--info{background:#10b98114;color:#059669;border-color:#10b98133}.du-msg{display:flex;align-items:center;gap:6px;font-size:var(--osl-hint-font-size, 11px);animation:du-fade-up .2s ease}.du-msg svg{flex-shrink:0}.du-msg--error{color:var(--osl-error-color, #ef4444)}.du-section{display:flex;flex-direction:column;gap:8px;animation:du-fade-up .3s ease}.du-section__hdr{display:flex;align-items:center;gap:7px}.du-section__icon{flex-shrink:0}.du-section__title{font-size:11px;font-weight:700;color:#9ca3af;text-transform:uppercase;letter-spacing:.07em}.du-count{width:19px;height:19px;border-radius:50%;font-size:10px;font-weight:800;color:#fff;display:flex;align-items:center;justify-content:center;flex-shrink:0;animation:du-pop-in .3s ease}.du-count--purple{background:linear-gradient(135deg,#667eea,#764ba2)}.du-count--green{background:linear-gradient(135deg,#10b981,#059669)}.du-file-list{display:flex;flex-direction:column;gap:7px}.du-file-card{display:flex;align-items:center;gap:11px;padding:10px 14px 10px 16px;background:#fff;border-radius:13px;border:1px solid #e9ecf1;animation:du-slide-in .28s ease both;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease;position:relative}.du-file-card:before{content:\"\";position:absolute;left:0;top:50%;transform:translateY(-50%);width:4px;height:60%;border-radius:0 4px 4px 0;transition:height .2s ease}.du-file-card[data-ftype=pdf]:before{background:#ef4444}.du-file-card[data-ftype=word]:before{background:#3b82f6}.du-file-card[data-ftype=excel]:before{background:#22c55e}.du-file-card[data-ftype=image]:before{background:#f59e0b}.du-file-card[data-ftype=archive]:before{background:#8b5cf6}.du-file-card[data-ftype=generic]:before{background:#94a3b8}.du-file-card:hover{border-color:#c4b5fd;box-shadow:0 3px 14px #667eea1a;transform:translate(3px)}.du-file-card:hover:before{height:75%}.du-file-icon{width:38px;height:46px;flex-shrink:0}.du-file-icon svg{width:100%;height:100%}.du-file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}.du-file-name{font-size:13px;font-weight:600;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.du-file-size{font-size:11px;color:#94a3b8;font-weight:500}.du-remove-btn{width:30px;height:30px;flex-shrink:0;border-radius:50%;border:1.5px solid #fecaca;background:#fef2f2;color:#fca5a5;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:6px;transition:all .22s ease}.du-remove-btn svg{width:100%;height:100%}.du-remove-btn:hover{background:#fee2e2;border-color:#ef4444;color:#ef4444;transform:rotate(90deg) scale(1.1);box-shadow:0 3px 10px #ef444440}.du-upload-btn{display:flex;align-items:center;justify-content:center;gap:8px;padding:12px 24px;width:100%;border:none;border-radius:13px;background:linear-gradient(135deg,#667eea,#764ba2);background-size:200% 200%;color:#fff;font-size:14px;font-weight:700;letter-spacing:.03em;cursor:pointer;transition:transform .25s ease,box-shadow .25s ease;animation:du-btn-pulse 2.5s ease-in-out infinite,du-gradient-shift 4s ease infinite}.du-upload-btn svg{flex-shrink:0;transition:transform .25s ease}.du-upload-btn:hover:not([disabled]){transform:translateY(-3px);box-shadow:0 10px 28px #667eea80;animation:du-gradient-shift 1.5s ease infinite}.du-upload-btn:hover:not([disabled]) svg{transform:translateY(-3px)}.du-upload-btn:active:not([disabled]){transform:translateY(-1px)}.du-upload-btn[disabled]{opacity:.45;cursor:not-allowed;animation:none}.du-upload-btn__badge{min-width:22px;height:22px;padding:0 6px;border-radius:11px;background:#ffffff38;font-size:11px;font-weight:800;display:flex;align-items:center;justify-content:center;animation:du-pop-in .3s ease}.du-saved-list{display:flex;flex-direction:column;gap:7px}.du-saved-card{display:flex;align-items:center;gap:11px;padding:10px 12px;background:linear-gradient(135deg,#fff,#f8faff);border-radius:13px;border:1px solid #e9ecf1;opacity:0;animation:du-fade-up .32s ease forwards;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease}.du-saved-card:hover{border-color:#a5b4fc;box-shadow:0 4px 18px #667eea1a;transform:translateY(-1px)}.du-saved-icon{width:32px;height:38px;flex-shrink:0}.du-saved-icon svg{width:100%;height:100%}.du-saved-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}.du-saved-name{font-size:13px;font-weight:600;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.du-saved-size{font-size:11px;color:#94a3b8;font-weight:500}.du-saved-actions{display:flex;align-items:center;gap:5px;flex-shrink:0}.du-act{width:32px;height:32px;border-radius:9px;border:1.5px solid transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:7px;transition:all .22s ease;position:relative;overflow:hidden}.du-act svg{width:100%;height:100%;transition:transform .22s ease}.du-act:after{content:\"\";position:absolute;inset:50%;border-radius:50%;transition:all 0s;pointer-events:none}.du-act:active:after{inset:0;border-radius:9px;background:#ffffff59;animation:du-ripple .4s ease}.du-act--view{background:#eff6ff;color:#3b82f6;border-color:#bfdbfe}.du-act--view:hover{background:#dbeafe;border-color:#93c5fd;box-shadow:0 3px 12px #3b82f64d}.du-act--view:hover svg{transform:scale(1.12)}.du-act--download{background:#f0fdf4;color:#22c55e;border-color:#bbf7d0}.du-act--download:hover{background:#dcfce7;border-color:#86efac;box-shadow:0 3px 12px #22c55e4d}.du-act--download:hover svg{transform:translateY(2px) scale(1.08)}.du-act--delete{background:#fef2f2;color:#ef4444;border-color:#fecaca}.du-act--delete:hover{background:#fee2e2;border-color:#fca5a5;box-shadow:0 3px 12px #ef44444d}.du-act--delete:hover svg{transform:scale(1.1) rotate(-5deg)}.du-dropzone--maxed{cursor:default;border-color:#22c55e66!important;background:linear-gradient(145deg,#f0fdf4,#dcfce7)!important;pointer-events:none}.du-dropzone--maxed .du-particles .du-p{background:radial-gradient(circle,#22c55e2e,#10b9811a)}.du-maxed-icon{width:56px;height:56px;animation:du-pop-in .4s cubic-bezier(.34,1.56,.64,1)}.du-maxed-icon svg{width:100%;height:100%}.du-gradient-text--green{background:linear-gradient(135deg,#22c55e,#059669)!important;background-size:200% 200%!important;-webkit-background-clip:text!important;-webkit-text-fill-color:transparent!important;background-clip:text!important}.du-maxed-sub{margin:0;font-size:12px;color:#6b7280;font-weight:500}.du-count-label{font-size:11px;font-weight:700;padding:2px 9px;border-radius:20px;background:#667eea1a;color:#667eea;border:1px solid rgba(102,126,234,.2);transition:all .25s ease;animation:du-pop-in .3s ease}.du-count-label--full{background:#22c55e1a;color:#16a34a;border-color:#22c55e40}.du-saved-meta{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.du-saved-by{font-size:11px;font-weight:600;color:#667eea}.du-saved-sep{font-size:11px;color:#d1d5db}.du-saved-on{font-size:11px;color:#94a3b8}\n"] }]
|
|
5535
|
+
}], propDecorators: { label: [{
|
|
5536
|
+
type: Input,
|
|
5537
|
+
args: ['label']
|
|
5538
|
+
}], required: [{
|
|
5539
|
+
type: Input,
|
|
5540
|
+
args: ['required']
|
|
5541
|
+
}], disabled: [{
|
|
5542
|
+
type: Input,
|
|
5543
|
+
args: ['disabled']
|
|
5544
|
+
}], multiple: [{
|
|
5545
|
+
type: Input,
|
|
5546
|
+
args: ['multiple']
|
|
5547
|
+
}], accept: [{
|
|
5548
|
+
type: Input,
|
|
5549
|
+
args: ['accept']
|
|
5550
|
+
}], maxSize: [{
|
|
5551
|
+
type: Input,
|
|
5552
|
+
args: ['maxSize']
|
|
5553
|
+
}], minFiles: [{
|
|
5554
|
+
type: Input,
|
|
5555
|
+
args: ['minFiles']
|
|
5556
|
+
}], maxFiles: [{
|
|
5557
|
+
type: Input,
|
|
5558
|
+
args: ['maxFiles']
|
|
5559
|
+
}], showUploadButton: [{
|
|
5560
|
+
type: Input,
|
|
5561
|
+
args: ['showUploadButton']
|
|
5562
|
+
}], uploadButtonLabel: [{
|
|
5563
|
+
type: Input,
|
|
5564
|
+
args: ['uploadButtonLabel']
|
|
5565
|
+
}], savedDocuments: [{
|
|
5566
|
+
type: Input,
|
|
5567
|
+
args: ['savedDocuments']
|
|
5568
|
+
}], skeletonLoading: [{
|
|
5569
|
+
type: Input,
|
|
5570
|
+
args: ['skeletonLoading']
|
|
5571
|
+
}], skeletonTheme: [{
|
|
5572
|
+
type: Input,
|
|
5573
|
+
args: ['skeletonTheme']
|
|
5574
|
+
}], uploadCallback: [{
|
|
5575
|
+
type: Output
|
|
5576
|
+
}], viewCallback: [{
|
|
5577
|
+
type: Output
|
|
5578
|
+
}], deleteCallback: [{
|
|
5579
|
+
type: Output
|
|
5580
|
+
}], downloadCallback: [{
|
|
5581
|
+
type: Output
|
|
5582
|
+
}], filesChanged: [{
|
|
5583
|
+
type: Output
|
|
5584
|
+
}] } });
|
|
5585
|
+
|
|
5374
5586
|
class FormStructureModule {
|
|
5375
5587
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FormStructureModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
5376
5588
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: FormStructureModule, declarations: [DynamicForm,
|
|
@@ -5394,7 +5606,8 @@ class FormStructureModule {
|
|
|
5394
5606
|
OslReportForm,
|
|
5395
5607
|
OslUserLog,
|
|
5396
5608
|
OslMenu,
|
|
5397
|
-
OslMenuTriggerFor
|
|
5609
|
+
OslMenuTriggerFor,
|
|
5610
|
+
OslDocumentUploader], imports: [NgTemplateOutlet,
|
|
5398
5611
|
NgStyle,
|
|
5399
5612
|
NgClass,
|
|
5400
5613
|
DatePipe,
|
|
@@ -5430,7 +5643,7 @@ class FormStructureModule {
|
|
|
5430
5643
|
OslButton,
|
|
5431
5644
|
OslSetup,
|
|
5432
5645
|
OslSearchbar, OslAutocompleteLister, OslReportGrid, OslReportForm,
|
|
5433
|
-
OslMenu, OslMenuTriggerFor] });
|
|
5646
|
+
OslMenu, OslMenuTriggerFor, OslDocumentUploader] });
|
|
5434
5647
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FormStructureModule, providers: [
|
|
5435
5648
|
{ provide: AUTOCOMPLETE_LISTER_COMPONENT, useValue: OslAutocompleteLister },
|
|
5436
5649
|
], imports: [FormsModule,
|
|
@@ -5476,6 +5689,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
5476
5689
|
OslUserLog,
|
|
5477
5690
|
OslMenu,
|
|
5478
5691
|
OslMenuTriggerFor,
|
|
5692
|
+
OslDocumentUploader,
|
|
5479
5693
|
],
|
|
5480
5694
|
imports: [
|
|
5481
5695
|
NgTemplateOutlet,
|
|
@@ -5516,7 +5730,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
5516
5730
|
OslButton,
|
|
5517
5731
|
OslSetup,
|
|
5518
5732
|
OslSearchbar, OslAutocompleteLister, OslReportGrid, OslReportForm,
|
|
5519
|
-
OslMenu, OslMenuTriggerFor],
|
|
5733
|
+
OslMenu, OslMenuTriggerFor, OslDocumentUploader],
|
|
5520
5734
|
providers: [
|
|
5521
5735
|
{ provide: AUTOCOMPLETE_LISTER_COMPONENT, useValue: OslAutocompleteLister },
|
|
5522
5736
|
],
|
|
@@ -6781,5 +6995,5 @@ var validation_util = /*#__PURE__*/Object.freeze({
|
|
|
6781
6995
|
* Generated bundle index. Do not edit.
|
|
6782
6996
|
*/
|
|
6783
6997
|
|
|
6784
|
-
export { array_util as ArrayUtil, date_util as DateUtil, DeleteConfirmation, DeleteConfirmationData, Dialog, DialogWrapper, DynamicForm, FormStructureModule, Httpbase, number_util as NumberUtil, object_util as ObjectUtil, OslAutocomplete, OslAutocompleteLister, OslBaseExtended, OslButton, OslCheckbox, OslDatepicker, OslDatetimepicker, OslFileUpload, OslFormGrid, OslGrid, OslMenu, OslMenuTriggerFor, OslRadio, OslReportForm, OslReportGrid, OslSearchbar, OslSelect, OslSetup, OslSkeletonDirective, OslSkeletonModule, OslSkeletonThemeService, OslSlideToggle, OslUserLog, Oslinput, Osltextarea, storage_util as StorageUtil, string_util as StringUtil, validation_util as ValidationUtil, baseComponent };
|
|
6998
|
+
export { array_util as ArrayUtil, date_util as DateUtil, DeleteConfirmation, DeleteConfirmationData, Dialog, DialogWrapper, DynamicForm, FormStructureModule, Httpbase, number_util as NumberUtil, object_util as ObjectUtil, OslAutocomplete, OslAutocompleteLister, OslBaseExtended, OslButton, OslCheckbox, OslDatepicker, OslDatetimepicker, OslDocumentUploader, OslFileUpload, OslFormGrid, OslGrid, OslMenu, OslMenuTriggerFor, OslRadio, OslReportForm, OslReportGrid, OslSearchbar, OslSelect, OslSetup, OslSkeletonDirective, OslSkeletonModule, OslSkeletonThemeService, OslSlideToggle, OslUserLog, Oslinput, Osltextarea, storage_util as StorageUtil, string_util as StringUtil, validation_util as ValidationUtil, baseComponent };
|
|
6785
6999
|
//# sourceMappingURL=osl-base-extended.mjs.map
|