cax-design-system 2.7.1 → 2.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/chips/chips.d.ts +2 -1
- package/esm2022/chips/chips.mjs +6 -3
- package/esm2022/dropdown/dropdown.mjs +3 -3
- package/esm2022/upload/upload.component.mjs +52 -40
- package/fesm2022/cax-design-system-chips.mjs +5 -2
- package/fesm2022/cax-design-system-chips.mjs.map +1 -1
- package/fesm2022/cax-design-system-dropdown.mjs +2 -2
- package/fesm2022/cax-design-system-dropdown.mjs.map +1 -1
- package/fesm2022/cax-design-system-upload.mjs +51 -39
- package/fesm2022/cax-design-system-upload.mjs.map +1 -1
- package/package.json +249 -249
- package/resources/cax.min.scss +1 -1
- package/resources/cax.scss +28 -12
- package/resources/components/chips/chips.scss +1 -0
- package/resources/components/upload/upload.component.scss +0 -2
- package/upload/upload.component.d.ts +10 -4
|
@@ -16,24 +16,37 @@ class UploadComponent {
|
|
|
16
16
|
uploadString = 'uploading the file';
|
|
17
17
|
errorText = 'Please upload a file';
|
|
18
18
|
allowMultiple = true;
|
|
19
|
+
componentId = '';
|
|
20
|
+
allowedFileTypes = [];
|
|
19
21
|
// Enhanced event emitters
|
|
20
22
|
fileSelected = new EventEmitter();
|
|
21
|
-
filesQueued = new EventEmitter();
|
|
23
|
+
filesQueued = new EventEmitter();
|
|
22
24
|
uploadStarted = new EventEmitter();
|
|
23
25
|
uploadCompleted = new EventEmitter();
|
|
24
|
-
uploadCanceled = new EventEmitter();
|
|
25
|
-
uploadError = new EventEmitter();
|
|
26
|
-
fileRemoved = new EventEmitter();
|
|
27
|
-
allFilesRemoved = new EventEmitter();
|
|
28
|
-
uploadStatusChange = new EventEmitter();
|
|
26
|
+
uploadCanceled = new EventEmitter();
|
|
27
|
+
uploadError = new EventEmitter();
|
|
28
|
+
fileRemoved = new EventEmitter();
|
|
29
|
+
allFilesRemoved = new EventEmitter();
|
|
30
|
+
uploadStatusChange = new EventEmitter();
|
|
29
31
|
isDragging = false;
|
|
30
32
|
uploadedFiles = [];
|
|
31
33
|
uploadStatus = 'idle';
|
|
32
34
|
isProcessingQueue = false;
|
|
35
|
+
uniqueId = '';
|
|
36
|
+
// Computed property for accept attribute in file input
|
|
37
|
+
get acceptFileTypes() {
|
|
38
|
+
if (!this.allowedFileTypes || this.allowedFileTypes.length === 0)
|
|
39
|
+
return '';
|
|
40
|
+
return this.allowedFileTypes.map((type) => `.${type}`).join(',');
|
|
41
|
+
}
|
|
33
42
|
// Track actual files to process (excludes canceled ones)
|
|
34
43
|
get activeFilesCount() {
|
|
35
44
|
return this.uploadedFiles.filter((file) => file.status !== 'canceled').length;
|
|
36
45
|
}
|
|
46
|
+
ngOnInit() {
|
|
47
|
+
// Generate unique ID if not provided through input
|
|
48
|
+
this.uniqueId = this.componentId || `upload-${Math.random().toString(36).substring(2, 11)}`;
|
|
49
|
+
}
|
|
37
50
|
onDragOver(event) {
|
|
38
51
|
event.preventDefault();
|
|
39
52
|
event.stopPropagation();
|
|
@@ -52,13 +65,7 @@ class UploadComponent {
|
|
|
52
65
|
if (!files || files.length === 0)
|
|
53
66
|
return;
|
|
54
67
|
const fileArray = Array.from(files);
|
|
55
|
-
const validFiles = fileArray.filter((file) =>
|
|
56
|
-
if (file.size > this.maxFileSize * 1024 * 1024) {
|
|
57
|
-
this.emitError(file, `File size should be less than ${this.maxFileSize}MB`);
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
return true;
|
|
61
|
-
});
|
|
68
|
+
const validFiles = fileArray.filter((file) => this.validateFile(file));
|
|
62
69
|
// Queue all files for upload
|
|
63
70
|
validFiles.forEach((file) => this.queueFile(file));
|
|
64
71
|
// Emit the queued files event
|
|
@@ -75,13 +82,7 @@ class UploadComponent {
|
|
|
75
82
|
if (!files)
|
|
76
83
|
return;
|
|
77
84
|
const fileArray = Array.from(files);
|
|
78
|
-
const validFiles = fileArray.filter((file) =>
|
|
79
|
-
if (file.size > this.maxFileSize * 1024 * 1024) {
|
|
80
|
-
this.emitError(file, `File size should be less than ${this.maxFileSize}MB`);
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
return true;
|
|
84
|
-
});
|
|
85
|
+
const validFiles = fileArray.filter((file) => this.validateFile(file));
|
|
85
86
|
// Queue all files for upload
|
|
86
87
|
validFiles.forEach((file) => this.queueFile(file));
|
|
87
88
|
// Emit the queued files event
|
|
@@ -93,6 +94,27 @@ class UploadComponent {
|
|
|
93
94
|
this.processQueue();
|
|
94
95
|
}
|
|
95
96
|
}
|
|
97
|
+
// New method for file validation
|
|
98
|
+
validateFile(file) {
|
|
99
|
+
// Size validation
|
|
100
|
+
if (file.size > this.maxFileSize * 1024 * 1024) {
|
|
101
|
+
this.emitError(file, `File size should be less than ${this.maxFileSize}MB`);
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
// File type validation
|
|
105
|
+
if (this.allowedFileTypes.length > 0) {
|
|
106
|
+
const fileExtension = this.getFileExtension(file.name).toLowerCase();
|
|
107
|
+
if (!this.allowedFileTypes.includes(fileExtension)) {
|
|
108
|
+
this.emitError(file, `Only ${this.allowedFileTypes.join(', ')} files are allowed`);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
// Helper method to get file extension
|
|
115
|
+
getFileExtension(filename) {
|
|
116
|
+
return filename.split('.').pop() || '';
|
|
117
|
+
}
|
|
96
118
|
// Queue a file for upload
|
|
97
119
|
queueFile(file) {
|
|
98
120
|
const uploadEntry = {
|
|
@@ -133,7 +155,7 @@ class UploadComponent {
|
|
|
133
155
|
}
|
|
134
156
|
// Trigger file input click programmatically
|
|
135
157
|
openFileSelector() {
|
|
136
|
-
const fileInput = document.getElementById(
|
|
158
|
+
const fileInput = document.getElementById(`fileInput-${this.uniqueId}`);
|
|
137
159
|
if (fileInput) {
|
|
138
160
|
fileInput.click();
|
|
139
161
|
}
|
|
@@ -158,7 +180,6 @@ class UploadComponent {
|
|
|
158
180
|
break;
|
|
159
181
|
}
|
|
160
182
|
fileEntry.progress = progress;
|
|
161
|
-
//this.uploadProgress.emit({ file: fileEntry.file, progress });
|
|
162
183
|
// Simulate network delay
|
|
163
184
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
164
185
|
}
|
|
@@ -254,21 +275,6 @@ class UploadComponent {
|
|
|
254
275
|
this.uploadedFiles = [];
|
|
255
276
|
this.updateUploadStatus('idle');
|
|
256
277
|
}
|
|
257
|
-
// Retry a failed upload
|
|
258
|
-
retryUpload(index) {
|
|
259
|
-
const fileToRetry = this.uploadedFiles[index];
|
|
260
|
-
if (fileToRetry) {
|
|
261
|
-
const currentStatus = fileToRetry.status;
|
|
262
|
-
if (currentStatus === 'error' || currentStatus === 'canceled') {
|
|
263
|
-
fileToRetry.status = 'queued';
|
|
264
|
-
fileToRetry.errorMessage = undefined;
|
|
265
|
-
// Start processing if not already doing so
|
|
266
|
-
if (!this.isProcessingQueue) {
|
|
267
|
-
this.processQueue();
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
278
|
get hasUploading() {
|
|
273
279
|
return this.uploadedFiles.some((file) => file.status === 'uploading');
|
|
274
280
|
}
|
|
@@ -310,11 +316,13 @@ class UploadComponent {
|
|
|
310
316
|
return activeFilesCount > 0 ? Math.round((totalProgress / (activeFilesCount * 100)) * 100) : 0;
|
|
311
317
|
}
|
|
312
318
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: UploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
313
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: UploadComponent, selector: "cax-upload", inputs: { invalid: "invalid", style: "style", maxFileSize: "maxFileSize", inputFiles: "inputFiles", uploadString: "uploadString", errorText: "errorText", allowMultiple: "allowMultiple" }, outputs: { fileSelected: "fileSelected", filesQueued: "filesQueued", uploadStarted: "uploadStarted", uploadCompleted: "uploadCompleted", uploadCanceled: "uploadCanceled", uploadError: "uploadError", fileRemoved: "fileRemoved", allFilesRemoved: "allFilesRemoved", uploadStatusChange: "uploadStatusChange" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" } }, ngImport: i0, template: "<p class=\"cax-files\">{{inputFiles}}</p>\r\n<div class=\"cax-upload-menu\" [ngStyle]=\"style\"\r\n [class.dragging]=\"isDragging\" \r\n (click)=\"openFileSelector()\">\r\n
|
|
319
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: UploadComponent, selector: "cax-upload", inputs: { invalid: "invalid", style: "style", maxFileSize: "maxFileSize", inputFiles: "inputFiles", uploadString: "uploadString", errorText: "errorText", allowMultiple: "allowMultiple", componentId: "componentId", allowedFileTypes: "allowedFileTypes" }, outputs: { fileSelected: "fileSelected", filesQueued: "filesQueued", uploadStarted: "uploadStarted", uploadCompleted: "uploadCompleted", uploadCanceled: "uploadCanceled", uploadError: "uploadError", fileRemoved: "fileRemoved", allFilesRemoved: "allFilesRemoved", uploadStatusChange: "uploadStatusChange" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" }, classAttribute: "cax-element" }, ngImport: i0, template: "<p class=\"cax-files\">{{inputFiles}}</p>\r\n<div class=\"cax-upload-menu\" [ngStyle]=\"style\"\r\n [class.dragging]=\"isDragging\" \r\n (click)=\"openFileSelector()\">\r\n <input\r\n type=\"file\"\r\n id=\"fileInput-{{uniqueId}}\"\r\n style=\"display:none\"\r\n [multiple]=\"allowMultiple\"\r\n [accept]=\"acceptFileTypes\"\r\n (change)=\"handleFileInput($event)\"\r\n />\r\n\r\n <!-- Default Upload State -->\r\n <ng-container *ngIf=\"uploadStatus === 'idle'\" >\r\n <div class=\"cax-upload-options\" >\r\n <p class=\"hint-text\">\r\n <span class=\"drop-files\">Drop files here</span> or browse files from your device\r\n </p>\r\n <p class=\"max-size\">Max. File Size: {{ maxFileSize }}MB</p>\r\n </div>\r\n </ng-container>\r\n\r\n\r\n <!-- Uploading State -->\r\n<div *ngIf=\"uploadStatus === 'uploading'\" class=\"cax-upload-status uploading\" >\r\n <div class=\"status-container\">\r\n <cax-progressSpinner\r\n [strokeColor]=\"'primary'\"\r\n [size]=\"'lg'\"\r\n [animationDuration]=\"'2s'\"\r\n ></cax-progressSpinner>\r\n <p >{{ uploadingProgressText }}</p>\r\n <cax-button\r\n [label]=\"'Cancel'\"\r\n [rounded]=\"false\"\r\n [severity]=\"'danger'\"\r\n [size]=\"'large'\"\r\n [outlined]=\"'false'\"\r\n [link]=\"true\"\r\n (click)=\"cancelCurrentUpload(); $event.stopPropagation()\"\r\n />\r\n </div>\r\n</div>\r\n\r\n <!-- Complete State -->\r\n <div *ngIf=\"uploadStatus === 'complete'\" class=\"cax-upload-status complete\">\r\n <div class=\"status-container\">\r\n <div class=\"success-icon\"><i class=\"cax cax-check\"></i></div>\r\n <p>{{uploadString}}</p>\r\n <cax-button\r\n [label]=\"'Remove'\"\r\n [rounded]=\"false\"\r\n [severity]=\"'danger'\"\r\n [size]=\"'large'\"\r\n [outlined]=\"'false'\"\r\n [link]=\"true\"\r\n (click)=\"removeAllFiles(); $event.stopPropagation()\"\r\n />\r\n </div>\r\n </div>\r\n <div *ngIf=\"invalid\" id=\"helper-text\" class=\"cax-error-upload\"></div>\r\n</div>\r\n<div *ngIf=\"invalid\" id=\"helper-text\" class=\"cax-error-upload\">\r\n {{ errorText }}\r\n</div>\r\n\r\n<!-- stacked file -->\r\n<div *ngIf=\"uploadedFiles.length > 0\" class=\"cax-file-preview-wrapper\" [ngStyle]=\"style\">\r\n <div\r\n *ngFor=\"let item of uploadedFiles; let i = index\"\r\n class=\"cax-file-preview\"\r\n [ngClass]=\"{\r\n 'queued': item.status === 'queued',\r\n 'uploading': item.status === 'uploading',\r\n 'complete': item.status === 'complete',\r\n 'canceled': item.status === 'canceled'\r\n }\"\r\n >\r\n <div class=\"file-info\">\r\n <p class=\"file-name\">{{ item.file.name }}</p>\r\n </div> \r\n\r\n <!-- Show spinner for queued or uploading files -->\r\n <div *ngIf=\"item.status === 'queued' || item.status === 'uploading'\" class=\"spinner\">\r\n <cax-progressSpinner\r\n [strokeColor]=\"'primary'\"\r\n [size]=\"'sm'\"\r\n [animationDuration]=\"'2s'\">\r\n </cax-progressSpinner>\r\n </div>\r\n \r\n <!-- Show remove button only for complete or canceled files -->\r\n <button\r\n *ngIf=\"item.status === 'complete' || item.status === 'canceled'\"\r\n class=\"remove-button\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\">\r\n <i class=\"cax cax-close\"></i> \r\n </button>\r\n </div>\r\n</div>", styles: ["@layer cax{.cax-files{font-size:14px;font-weight:500;margin-bottom:10px}.cax-upload-menu{border-radius:12px;padding:24px 56px}.status-container{display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;gap:16px;height:150px}.status-container p{margin:0;font-size:14px;font-weight:500}.status-container .success-icon{width:50px;height:50px;border-radius:50%;display:flex;align-items:center;justify-content:center}.status-container .success-icon i{font-size:1.5rem;font-weight:800}.cax-upload-options{text-align:center}.cax-upload-options .hint-text{font-size:14px;font-weight:500}.cax-upload-options .drop-files{font-weight:500;font-size:14px}.cax-upload-options .max-size{font-size:12px;margin-bottom:20px;font-weight:400}.cax-error-upload{font-size:14px;font-weight:400;padding-top:8px}.cax-options-container{display:flex;gap:24px;justify-content:center}.cax-upload-option{display:flex;flex-direction:column;align-items:center;cursor:pointer}.cax-upload-option .icon-container{width:48px;height:40px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:background-color .2s}.cax-upload-option span{font-size:14px;font-weight:600;padding-top:10px}.cax-file-preview-wrapper{display:flex;flex-direction:column;gap:10px;margin-top:1rem}.cax-file-preview{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-radius:8px}.cax-file-preview .file-info{display:flex;align-items:center;gap:10px}.cax-file-preview .file-info .file-icon img{width:32px;height:32px}.cax-file-preview .file-info .file-name{font-weight:500;font-size:14px}.cax-file-preview .spinner{margin-left:auto;font-size:20px!important}.cax-file-preview .remove-button{background:none;border:none;margin-left:auto;cursor:pointer}.cax-file-preview .remove-button i{font-size:20px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.ProgressSpinner, selector: "cax-progressSpinner", inputs: ["styleClass", "strokeColor", "backgroundStrokeColor", "size", "style", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i3.Button, selector: "cax-button", inputs: ["type", "iconPos", "icon", "badge", "rightIcon", "leftIcon", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }] });
|
|
314
320
|
}
|
|
315
321
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: UploadComponent, decorators: [{
|
|
316
322
|
type: Component,
|
|
317
|
-
args: [{ selector: 'cax-upload',
|
|
323
|
+
args: [{ selector: 'cax-upload', host: {
|
|
324
|
+
class: 'cax-element'
|
|
325
|
+
}, template: "<p class=\"cax-files\">{{inputFiles}}</p>\r\n<div class=\"cax-upload-menu\" [ngStyle]=\"style\"\r\n [class.dragging]=\"isDragging\" \r\n (click)=\"openFileSelector()\">\r\n <input\r\n type=\"file\"\r\n id=\"fileInput-{{uniqueId}}\"\r\n style=\"display:none\"\r\n [multiple]=\"allowMultiple\"\r\n [accept]=\"acceptFileTypes\"\r\n (change)=\"handleFileInput($event)\"\r\n />\r\n\r\n <!-- Default Upload State -->\r\n <ng-container *ngIf=\"uploadStatus === 'idle'\" >\r\n <div class=\"cax-upload-options\" >\r\n <p class=\"hint-text\">\r\n <span class=\"drop-files\">Drop files here</span> or browse files from your device\r\n </p>\r\n <p class=\"max-size\">Max. File Size: {{ maxFileSize }}MB</p>\r\n </div>\r\n </ng-container>\r\n\r\n\r\n <!-- Uploading State -->\r\n<div *ngIf=\"uploadStatus === 'uploading'\" class=\"cax-upload-status uploading\" >\r\n <div class=\"status-container\">\r\n <cax-progressSpinner\r\n [strokeColor]=\"'primary'\"\r\n [size]=\"'lg'\"\r\n [animationDuration]=\"'2s'\"\r\n ></cax-progressSpinner>\r\n <p >{{ uploadingProgressText }}</p>\r\n <cax-button\r\n [label]=\"'Cancel'\"\r\n [rounded]=\"false\"\r\n [severity]=\"'danger'\"\r\n [size]=\"'large'\"\r\n [outlined]=\"'false'\"\r\n [link]=\"true\"\r\n (click)=\"cancelCurrentUpload(); $event.stopPropagation()\"\r\n />\r\n </div>\r\n</div>\r\n\r\n <!-- Complete State -->\r\n <div *ngIf=\"uploadStatus === 'complete'\" class=\"cax-upload-status complete\">\r\n <div class=\"status-container\">\r\n <div class=\"success-icon\"><i class=\"cax cax-check\"></i></div>\r\n <p>{{uploadString}}</p>\r\n <cax-button\r\n [label]=\"'Remove'\"\r\n [rounded]=\"false\"\r\n [severity]=\"'danger'\"\r\n [size]=\"'large'\"\r\n [outlined]=\"'false'\"\r\n [link]=\"true\"\r\n (click)=\"removeAllFiles(); $event.stopPropagation()\"\r\n />\r\n </div>\r\n </div>\r\n <div *ngIf=\"invalid\" id=\"helper-text\" class=\"cax-error-upload\"></div>\r\n</div>\r\n<div *ngIf=\"invalid\" id=\"helper-text\" class=\"cax-error-upload\">\r\n {{ errorText }}\r\n</div>\r\n\r\n<!-- stacked file -->\r\n<div *ngIf=\"uploadedFiles.length > 0\" class=\"cax-file-preview-wrapper\" [ngStyle]=\"style\">\r\n <div\r\n *ngFor=\"let item of uploadedFiles; let i = index\"\r\n class=\"cax-file-preview\"\r\n [ngClass]=\"{\r\n 'queued': item.status === 'queued',\r\n 'uploading': item.status === 'uploading',\r\n 'complete': item.status === 'complete',\r\n 'canceled': item.status === 'canceled'\r\n }\"\r\n >\r\n <div class=\"file-info\">\r\n <p class=\"file-name\">{{ item.file.name }}</p>\r\n </div> \r\n\r\n <!-- Show spinner for queued or uploading files -->\r\n <div *ngIf=\"item.status === 'queued' || item.status === 'uploading'\" class=\"spinner\">\r\n <cax-progressSpinner\r\n [strokeColor]=\"'primary'\"\r\n [size]=\"'sm'\"\r\n [animationDuration]=\"'2s'\">\r\n </cax-progressSpinner>\r\n </div>\r\n \r\n <!-- Show remove button only for complete or canceled files -->\r\n <button\r\n *ngIf=\"item.status === 'complete' || item.status === 'canceled'\"\r\n class=\"remove-button\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\">\r\n <i class=\"cax cax-close\"></i> \r\n </button>\r\n </div>\r\n</div>", styles: ["@layer cax{.cax-files{font-size:14px;font-weight:500;margin-bottom:10px}.cax-upload-menu{border-radius:12px;padding:24px 56px}.status-container{display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;gap:16px;height:150px}.status-container p{margin:0;font-size:14px;font-weight:500}.status-container .success-icon{width:50px;height:50px;border-radius:50%;display:flex;align-items:center;justify-content:center}.status-container .success-icon i{font-size:1.5rem;font-weight:800}.cax-upload-options{text-align:center}.cax-upload-options .hint-text{font-size:14px;font-weight:500}.cax-upload-options .drop-files{font-weight:500;font-size:14px}.cax-upload-options .max-size{font-size:12px;margin-bottom:20px;font-weight:400}.cax-error-upload{font-size:14px;font-weight:400;padding-top:8px}.cax-options-container{display:flex;gap:24px;justify-content:center}.cax-upload-option{display:flex;flex-direction:column;align-items:center;cursor:pointer}.cax-upload-option .icon-container{width:48px;height:40px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:background-color .2s}.cax-upload-option span{font-size:14px;font-weight:600;padding-top:10px}.cax-file-preview-wrapper{display:flex;flex-direction:column;gap:10px;margin-top:1rem}.cax-file-preview{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-radius:8px}.cax-file-preview .file-info{display:flex;align-items:center;gap:10px}.cax-file-preview .file-info .file-icon img{width:32px;height:32px}.cax-file-preview .file-info .file-name{font-weight:500;font-size:14px}.cax-file-preview .spinner{margin-left:auto;font-size:20px!important}.cax-file-preview .remove-button{background:none;border:none;margin-left:auto;cursor:pointer}.cax-file-preview .remove-button i{font-size:20px}}\n"] }]
|
|
318
326
|
}], propDecorators: { invalid: [{
|
|
319
327
|
type: Input
|
|
320
328
|
}], style: [{
|
|
@@ -329,6 +337,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImpor
|
|
|
329
337
|
type: Input
|
|
330
338
|
}], allowMultiple: [{
|
|
331
339
|
type: Input
|
|
340
|
+
}], componentId: [{
|
|
341
|
+
type: Input
|
|
342
|
+
}], allowedFileTypes: [{
|
|
343
|
+
type: Input
|
|
332
344
|
}], fileSelected: [{
|
|
333
345
|
type: Output
|
|
334
346
|
}], filesQueued: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cax-design-system-upload.mjs","sources":["../../src/app/components/upload/upload.component.ts","../../src/app/components/upload/upload.component.html","../../src/app/components/upload/upload.component.module.ts","../../src/app/components/upload/cax-design-system-upload.ts"],"sourcesContent":["import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core';\n\nexport type UploadFileStatus = 'queued' | 'uploading' | 'complete' | 'canceled' | 'error';\n\nexport type UploadFile = {\n file: File;\n status: UploadFileStatus;\n progress?: number;\n errorMessage?: string;\n};\n\n@Component({\n selector: 'cax-upload',\n templateUrl: './upload.component.html',\n styleUrls: ['./upload.component.scss']\n})\nexport class UploadComponent {\n @Input() invalid: boolean = false;\n @Input() style: { [klass: string]: any } | null | undefined;\n @Input() maxFileSize: number = 30;\n @Input() inputFiles: string = 'Input Files';\n @Input() uploadString: string = 'uploading the file';\n @Input() errorText: string = 'Please upload a file';\n @Input() allowMultiple: boolean = true;\n\n // Enhanced event emitters\n @Output() fileSelected = new EventEmitter<File>();\n @Output() filesQueued = new EventEmitter<File[]>(); // Emit when files are queued for upload\n @Output() uploadStarted = new EventEmitter<File>();\n @Output() uploadCompleted = new EventEmitter<File>();\n @Output() uploadCanceled = new EventEmitter<File>(); // When user cancels an upload\n @Output() uploadError = new EventEmitter<{ file: File; error: string }>(); // When upload fails\n @Output() fileRemoved = new EventEmitter<File>(); // When a file is removed from the list\n @Output() allFilesRemoved = new EventEmitter<void>(); // When all files are cleared\n @Output() uploadStatusChange = new EventEmitter<'idle' | 'uploading' | 'complete'>(); // Status changes\n\n isDragging: boolean = false;\n uploadedFiles: UploadFile[] = [];\n uploadStatus: 'idle' | 'uploading' | 'complete' = 'idle';\n isProcessingQueue: boolean = false;\n\n // Track actual files to process (excludes canceled ones)\n private get activeFilesCount(): number {\n return this.uploadedFiles.filter((file) => file.status !== 'canceled').length;\n }\n\n @HostListener('dragover', ['$event'])\n onDragOver(event: DragEvent) {\n event.preventDefault();\n event.stopPropagation();\n this.isDragging = true;\n }\n\n @HostListener('dragleave', ['$event'])\n onDragLeave(event: DragEvent) {\n event.preventDefault();\n event.stopPropagation();\n this.isDragging = false;\n }\n\n @HostListener('drop', ['$event'])\n onDrop(event: DragEvent) {\n event.preventDefault();\n event.stopPropagation();\n this.isDragging = false;\n\n const files = event.dataTransfer?.files;\n if (!files || files.length === 0) return;\n\n const fileArray = Array.from(files);\n const validFiles = fileArray.filter((file) => {\n if (file.size > this.maxFileSize * 1024 * 1024) {\n this.emitError(file, `File size should be less than ${this.maxFileSize}MB`);\n return false;\n }\n return true;\n });\n\n // Queue all files for upload\n validFiles.forEach((file) => this.queueFile(file));\n\n // Emit the queued files event\n if (validFiles.length > 0) {\n this.filesQueued.emit(validFiles);\n }\n\n // Start processing the queue if not already processing\n if (!this.isProcessingQueue) {\n this.processQueue();\n }\n }\n\n handleFileInput(event: any): void {\n const files: FileList = event.target.files;\n if (!files) return;\n\n const fileArray = Array.from(files);\n const validFiles = fileArray.filter((file) => {\n if (file.size > this.maxFileSize * 1024 * 1024) {\n this.emitError(file, `File size should be less than ${this.maxFileSize}MB`);\n return false;\n }\n return true;\n });\n\n // Queue all files for upload\n validFiles.forEach((file) => this.queueFile(file));\n\n // Emit the queued files event\n if (validFiles.length > 0) {\n this.filesQueued.emit(validFiles);\n }\n\n // Start processing the queue if not already processing\n if (!this.isProcessingQueue) {\n this.processQueue();\n }\n }\n\n // Queue a file for upload\n private queueFile(file: File): void {\n const uploadEntry: UploadFile = {\n file,\n status: 'queued',\n\n progress: 0\n };\n\n this.uploadedFiles.push(uploadEntry);\n\n if (this.uploadStatus === 'idle') {\n this.updateUploadStatus('uploading');\n }\n }\n\n // Update upload status and emit event\n private updateUploadStatus(status: 'idle' | 'uploading' | 'complete'): void {\n if (this.uploadStatus !== status) {\n this.uploadStatus = status;\n this.uploadStatusChange.emit(status);\n }\n }\n\n // Process the queue of files sequentially\n private async processQueue(): Promise<void> {\n if (this.isProcessingQueue) return;\n\n this.isProcessingQueue = true;\n\n // Find the next file to upload\n let nextFileIndex = this.uploadedFiles.findIndex((file) => file.status === 'queued');\n\n while (nextFileIndex !== -1) {\n const currentFile = this.uploadedFiles[nextFileIndex];\n await this.processFile(currentFile, nextFileIndex);\n\n // Find the next file after processing\n nextFileIndex = this.uploadedFiles.findIndex((file) => file.status === 'queued');\n }\n\n this.isProcessingQueue = false;\n\n // Check if all uploads are complete and there are no more files to process\n if (this.uploadedFiles.length > 0 && this.uploadedFiles.some((file) => file.status === 'complete') && !this.hasQueuedOrUploading) {\n this.updateUploadStatus('complete');\n }\n }\n\n // Trigger file input click programmatically\n openFileSelector(): void {\n const fileInput = document.getElementById('fileInput') as HTMLInputElement;\n if (fileInput) {\n fileInput.click();\n }\n }\n\n // Emit error event\n private emitError(file: File, message: string): void {\n this.uploadError.emit({ file, error: message });\n }\n private async processFile(fileEntry: UploadFile, index: number): Promise<void> {\n // Update status to uploading\n fileEntry.status = 'uploading';\n fileEntry.progress = 0;\n\n this.fileSelected.emit(fileEntry.file);\n this.uploadStarted.emit(fileEntry.file);\n\n try {\n // Simulate upload with progress updates\n for (let progress = 0; progress <= 100; progress += 10) {\n // Check if upload was canceled during progress\n // Need to check current status since it might have changed\n if (fileEntry.status !== 'uploading') {\n // Either canceled or errored\n break;\n }\n\n fileEntry.progress = progress;\n //this.uploadProgress.emit({ file: fileEntry.file, progress });\n\n // Simulate network delay\n await new Promise((resolve) => setTimeout(resolve, 200));\n }\n\n // Only set to complete if still uploading (not canceled or errored)\n if (fileEntry.status === 'uploading') {\n fileEntry.status = 'complete';\n fileEntry.progress = 100;\n this.uploadCompleted.emit(fileEntry.file);\n }\n } catch (error) {\n // Handle errors\n fileEntry.status = 'error';\n const errorMessage = error instanceof Error ? error.message : 'Unknown upload error';\n fileEntry.errorMessage = errorMessage;\n this.emitError(fileEntry.file, errorMessage);\n }\n }\n\n cancelUpload(index: number): void {\n // Cancel the specified file and all files below it\n for (let i = index; i < this.uploadedFiles.length; i++) {\n const fileToCancel = this.uploadedFiles[i];\n if (fileToCancel) {\n const previousStatus = fileToCancel.status;\n if (previousStatus === 'uploading' || previousStatus === 'queued') {\n fileToCancel.status = 'canceled';\n // Only emit if it was actively uploading (not just queued)\n if (previousStatus === 'uploading') {\n this.uploadCanceled.emit(fileToCancel.file);\n }\n }\n }\n }\n // If the file at the specified index was uploading, process the next file in queue\n // (which would now be a file before the index that might be queued)\n if (this.uploadedFiles[index]?.status === 'canceled') {\n setTimeout(() => this.processQueue(), 0);\n }\n }\n\n // Cancel the current upload\n cancelCurrentUpload(): void {\n // Find the file that's currently uploading\n const currentUploadIndex = this.uploadedFiles.findIndex((file) => file.status === 'uploading');\n if (currentUploadIndex >= 0) {\n this.cancelUpload(currentUploadIndex);\n }\n }\n\n // Cancel all uploads\n cancelAllUploads(): void {\n let hadActiveUploads = false;\n\n this.uploadedFiles.forEach((file) => {\n if (file.status === 'uploading' || file.status === 'queued') {\n hadActiveUploads = true;\n const previousStatus = file.status;\n file.status = 'canceled';\n\n if (previousStatus === 'uploading') {\n this.uploadCanceled.emit(file.file);\n }\n }\n });\n\n if (hadActiveUploads && !this.hasQueuedOrUploading) {\n this.updateUploadStatus('idle');\n }\n }\n\n // Remove a file from the list\n removeFile(index: number): void {\n const fileToRemove = this.uploadedFiles[index];\n\n // Cancel first if it's active\n if (fileToRemove.status === 'uploading' || fileToRemove.status === 'queued') {\n this.cancelUpload(index);\n }\n\n // Emit removal event\n this.fileRemoved.emit(fileToRemove.file);\n\n // Remove from array\n this.uploadedFiles.splice(index, 1);\n\n // Reset status if no files left\n if (this.uploadedFiles.length === 0) {\n this.updateUploadStatus('idle');\n } else if (!this.hasQueuedOrUploading && this.uploadStatus !== 'complete') {\n // If there are no more queued or uploading files but we have completed files\n this.updateUploadStatus('complete');\n }\n }\n\n // Remove all files\n removeAllFiles(): void {\n // Cancel any active uploads\n this.cancelAllUploads();\n\n // Only emit if there were files to remove\n if (this.uploadedFiles.length > 0) {\n this.allFilesRemoved.emit();\n }\n\n this.uploadedFiles = [];\n this.updateUploadStatus('idle');\n }\n\n // Retry a failed upload\n retryUpload(index: number): void {\n const fileToRetry = this.uploadedFiles[index];\n if (fileToRetry) {\n const currentStatus = fileToRetry.status;\n if (currentStatus === 'error' || currentStatus === 'canceled') {\n fileToRetry.status = 'queued';\n fileToRetry.errorMessage = undefined;\n\n // Start processing if not already doing so\n if (!this.isProcessingQueue) {\n this.processQueue();\n }\n }\n }\n }\n\n get hasUploading(): boolean {\n return this.uploadedFiles.some((file) => file.status === 'uploading');\n }\n\n get hasQueuedOrUploading(): boolean {\n return this.uploadedFiles.some((file) => file.status === 'uploading' || file.status === 'queued');\n }\n\n get hasErrors(): boolean {\n return this.uploadedFiles.some((file) => file.status === 'error');\n }\n\n get allUploadsComplete(): boolean {\n return this.uploadedFiles.length > 0 && this.uploadedFiles.some((file) => file.status === 'complete') && !this.hasQueuedOrUploading;\n }\n\n get uploadingProgressText(): string {\n // Count active files (excluding canceled ones)\n const totalActiveFiles = this.activeFilesCount;\n const completedCount = this.uploadedFiles.filter((file) => file.status === 'complete').length;\n const uploadingFile = this.uploadedFiles.find((file) => file.status === 'uploading');\n if (uploadingFile) {\n // We're currently uploading the (completedCount + 1)th active file\n return `Uploading ${completedCount}/${totalActiveFiles} file${totalActiveFiles > 1 ? 's' : ''}...`;\n }\n if (this.uploadedFiles.some((file) => file.status === 'queued')) {\n return `Uploading ${completedCount + 1}/${totalActiveFiles} file${totalActiveFiles > 1 ? 's' : ''}...`;\n }\n return `Uploading ${completedCount}/${totalActiveFiles} file${totalActiveFiles > 1 ? 's' : ''}...`;\n }\n\n // Calculate overall progress percentage across all files\n get overallProgress(): number {\n if (this.uploadedFiles.length === 0) return 0;\n\n const totalProgress = this.uploadedFiles.reduce((sum, file) => {\n if (file.status === 'complete') return sum + 100;\n if (file.status === 'canceled' || file.status === 'error') return sum;\n return sum + (file.progress || 0);\n }, 0);\n\n const activeFilesCount = this.uploadedFiles.filter((file) => file.status !== 'canceled' && file.status !== 'error').length;\n\n return activeFilesCount > 0 ? Math.round((totalProgress / (activeFilesCount * 100)) * 100) : 0;\n }\n}\n","<p class=\"cax-files\">{{inputFiles}}</p>\r\n<div class=\"cax-upload-menu\" [ngStyle]=\"style\"\r\n [class.dragging]=\"isDragging\" \r\n (click)=\"openFileSelector()\">\r\n <input\r\n id=\"fileInput\"\r\n type=\"file\"\r\n (change)=\"handleFileInput($event)\"\r\n hidden\r\n multiple\r\n >\r\n\r\n <!-- Default Upload State -->\r\n <ng-container *ngIf=\"uploadStatus === 'idle'\" >\r\n <div class=\"cax-upload-options\" >\r\n <p class=\"hint-text\">\r\n <span class=\"drop-files\">Drop files here</span> or browse files from your device\r\n </p>\r\n <p class=\"max-size\">Max. File Size: {{ maxFileSize }}MB</p>\r\n </div>\r\n </ng-container>\r\n\r\n\r\n <!-- Uploading State -->\r\n<div *ngIf=\"uploadStatus === 'uploading'\" class=\"cax-upload-status uploading\" >\r\n <div class=\"status-container\">\r\n <cax-progressSpinner\r\n [strokeColor]=\"'primary'\"\r\n [size]=\"'lg'\"\r\n [animationDuration]=\"'2s'\"\r\n ></cax-progressSpinner>\r\n <p >{{ uploadingProgressText }}</p>\r\n <cax-button\r\n [label]=\"'Cancel'\"\r\n [rounded]=\"false\"\r\n [severity]=\"'danger'\"\r\n [size]=\"'large'\"\r\n [outlined]=\"'false'\"\r\n [link]=\"true\"\r\n (click)=\"cancelCurrentUpload(); $event.stopPropagation()\"\r\n />\r\n </div>\r\n</div>\r\n\r\n <!-- Complete State -->\r\n <div *ngIf=\"uploadStatus === 'complete'\" class=\"cax-upload-status complete\">\r\n <div class=\"status-container\">\r\n <div class=\"success-icon\"><i class=\"cax cax-check\"></i></div>\r\n <p>{{uploadString}}</p>\r\n <cax-button\r\n [label]=\"'Remove'\"\r\n [rounded]=\"false\"\r\n [severity]=\"'danger'\"\r\n [size]=\"'large'\"\r\n [outlined]=\"'false'\"\r\n [link]=\"true\"\r\n (click)=\"removeAllFiles(); $event.stopPropagation()\"\r\n />\r\n </div>\r\n </div>\r\n <div *ngIf=\"invalid\" id=\"helper-text\" class=\"cax-error-upload\"></div>\r\n</div>\r\n<div *ngIf=\"invalid\" id=\"helper-text\" class=\"cax-error-upload\">\r\n {{ errorText }}\r\n</div>\r\n\r\n<!-- stacked file -->\r\n<div *ngIf=\"uploadedFiles.length > 0\" class=\"cax-file-preview-wrapper\" [ngStyle]=\"style\">\r\n <div\r\n *ngFor=\"let item of uploadedFiles; let i = index\"\r\n class=\"cax-file-preview\"\r\n [ngClass]=\"{\r\n 'queued': item.status === 'queued',\r\n 'uploading': item.status === 'uploading',\r\n 'complete': item.status === 'complete',\r\n 'canceled': item.status === 'canceled'\r\n }\"\r\n >\r\n <div class=\"file-info\">\r\n <p class=\"file-name\">{{ item.file.name }}</p>\r\n </div> \r\n\r\n <!-- Show spinner for queued or uploading files -->\r\n <div *ngIf=\"item.status === 'queued' || item.status === 'uploading'\" class=\"spinner\">\r\n <cax-progressSpinner\r\n [strokeColor]=\"'primary'\"\r\n [size]=\"'sm'\"\r\n [animationDuration]=\"'2s'\">\r\n </cax-progressSpinner>\r\n </div>\r\n \r\n <!-- Show remove button only for complete or canceled files -->\r\n <button\r\n *ngIf=\"item.status === 'complete' || item.status === 'canceled'\"\r\n class=\"remove-button\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\">\r\n <i class=\"cax cax-close\"></i> \r\n </button>\r\n </div>\r\n</div>","import { CommonModule } from '@angular/common';\nimport { UploadComponent } from './upload.component';\nimport { FormsModule } from '@angular/forms';\nimport { NgModule } from '@angular/core';\nimport { ProgressSpinnerModule } from 'cax-design-system/progressspinner';\nimport { Button } from 'cax-design-system/button';\n\n@NgModule({\n declarations: [UploadComponent],\n imports: [CommonModule, FormsModule, ProgressSpinnerModule, Button],\n exports: [UploadComponent]\n})\nexport class UploadModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cax-design-system-upload.mjs","sources":["../../src/app/components/upload/upload.component.ts","../../src/app/components/upload/upload.component.html","../../src/app/components/upload/upload.component.module.ts","../../src/app/components/upload/cax-design-system-upload.ts"],"sourcesContent":["import { Component, EventEmitter, HostListener, Input, Output, OnInit } from '@angular/core';\n\nexport type UploadFileStatus = 'queued' | 'uploading' | 'complete' | 'canceled' | 'error';\n\nexport type UploadFile = {\n file: File;\n status: UploadFileStatus;\n progress?: number;\n errorMessage?: string;\n};\n\n@Component({\n selector: 'cax-upload',\n templateUrl: './upload.component.html',\n styleUrls: ['./upload.component.scss'],\n host: {\n class: 'cax-element'\n }\n})\nexport class UploadComponent implements OnInit {\n @Input() invalid: boolean = false;\n @Input() style: { [klass: string]: any } | null | undefined;\n @Input() maxFileSize: number = 30;\n @Input() inputFiles: string = 'Input Files';\n @Input() uploadString: string = 'uploading the file';\n @Input() errorText: string = 'Please upload a file';\n @Input() allowMultiple: boolean = true;\n @Input() componentId: string = '';\n @Input() allowedFileTypes: string[] = [];\n // Enhanced event emitters\n @Output() fileSelected = new EventEmitter<File>();\n @Output() filesQueued = new EventEmitter<File[]>();\n @Output() uploadStarted = new EventEmitter<File>();\n @Output() uploadCompleted = new EventEmitter<File>();\n @Output() uploadCanceled = new EventEmitter<File>();\n @Output() uploadError = new EventEmitter<{ file: File; error: string }>();\n @Output() fileRemoved = new EventEmitter<File>();\n @Output() allFilesRemoved = new EventEmitter<void>();\n @Output() uploadStatusChange = new EventEmitter<'idle' | 'uploading' | 'complete'>();\n\n isDragging: boolean = false;\n uploadedFiles: UploadFile[] = [];\n uploadStatus: 'idle' | 'uploading' | 'complete' = 'idle';\n isProcessingQueue: boolean = false;\n uniqueId: string = '';\n\n // Computed property for accept attribute in file input\n get acceptFileTypes(): string {\n if (!this.allowedFileTypes || this.allowedFileTypes.length === 0) return '';\n return this.allowedFileTypes.map((type) => `.${type}`).join(',');\n }\n\n // Track actual files to process (excludes canceled ones)\n private get activeFilesCount(): number {\n return this.uploadedFiles.filter((file) => file.status !== 'canceled').length;\n }\n\n ngOnInit() {\n // Generate unique ID if not provided through input\n this.uniqueId = this.componentId || `upload-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n @HostListener('dragover', ['$event'])\n onDragOver(event: DragEvent) {\n event.preventDefault();\n event.stopPropagation();\n this.isDragging = true;\n }\n\n @HostListener('dragleave', ['$event'])\n onDragLeave(event: DragEvent) {\n event.preventDefault();\n event.stopPropagation();\n this.isDragging = false;\n }\n\n @HostListener('drop', ['$event'])\n onDrop(event: DragEvent) {\n event.preventDefault();\n event.stopPropagation();\n this.isDragging = false;\n\n const files = event.dataTransfer?.files;\n if (!files || files.length === 0) return;\n\n const fileArray = Array.from(files);\n const validFiles = fileArray.filter((file) => this.validateFile(file));\n\n // Queue all files for upload\n validFiles.forEach((file) => this.queueFile(file));\n\n // Emit the queued files event\n if (validFiles.length > 0) {\n this.filesQueued.emit(validFiles);\n }\n\n // Start processing the queue if not already processing\n if (!this.isProcessingQueue) {\n this.processQueue();\n }\n }\n\n handleFileInput(event: any): void {\n const files: FileList = event.target.files;\n if (!files) return;\n\n const fileArray = Array.from(files);\n const validFiles = fileArray.filter((file) => this.validateFile(file));\n\n // Queue all files for upload\n validFiles.forEach((file) => this.queueFile(file));\n\n // Emit the queued files event\n if (validFiles.length > 0) {\n this.filesQueued.emit(validFiles);\n }\n\n // Start processing the queue if not already processing\n if (!this.isProcessingQueue) {\n this.processQueue();\n }\n }\n\n // New method for file validation\n private validateFile(file: File): boolean {\n // Size validation\n if (file.size > this.maxFileSize * 1024 * 1024) {\n this.emitError(file, `File size should be less than ${this.maxFileSize}MB`);\n return false;\n }\n\n // File type validation\n if (this.allowedFileTypes.length > 0) {\n const fileExtension = this.getFileExtension(file.name).toLowerCase();\n if (!this.allowedFileTypes.includes(fileExtension)) {\n this.emitError(file, `Only ${this.allowedFileTypes.join(', ')} files are allowed`);\n return false;\n }\n }\n\n return true;\n }\n\n // Helper method to get file extension\n private getFileExtension(filename: string): string {\n return filename.split('.').pop() || '';\n }\n\n // Queue a file for upload\n private queueFile(file: File): void {\n const uploadEntry: UploadFile = {\n file,\n status: 'queued',\n progress: 0\n };\n\n this.uploadedFiles.push(uploadEntry);\n\n if (this.uploadStatus === 'idle') {\n this.updateUploadStatus('uploading');\n }\n }\n\n // Update upload status and emit event\n private updateUploadStatus(status: 'idle' | 'uploading' | 'complete'): void {\n if (this.uploadStatus !== status) {\n this.uploadStatus = status;\n this.uploadStatusChange.emit(status);\n }\n }\n\n // Process the queue of files sequentially\n private async processQueue(): Promise<void> {\n if (this.isProcessingQueue) return;\n\n this.isProcessingQueue = true;\n\n // Find the next file to upload\n let nextFileIndex = this.uploadedFiles.findIndex((file) => file.status === 'queued');\n\n while (nextFileIndex !== -1) {\n const currentFile = this.uploadedFiles[nextFileIndex];\n await this.processFile(currentFile, nextFileIndex);\n\n // Find the next file after processing\n nextFileIndex = this.uploadedFiles.findIndex((file) => file.status === 'queued');\n }\n\n this.isProcessingQueue = false;\n\n // Check if all uploads are complete and there are no more files to process\n if (this.uploadedFiles.length > 0 && this.uploadedFiles.some((file) => file.status === 'complete') && !this.hasQueuedOrUploading) {\n this.updateUploadStatus('complete');\n }\n }\n\n // Trigger file input click programmatically\n openFileSelector(): void {\n const fileInput = document.getElementById(`fileInput-${this.uniqueId}`) as HTMLInputElement;\n if (fileInput) {\n fileInput.click();\n }\n }\n\n // Emit error event\n private emitError(file: File, message: string): void {\n this.uploadError.emit({ file, error: message });\n }\n\n private async processFile(fileEntry: UploadFile, index: number): Promise<void> {\n // Update status to uploading\n fileEntry.status = 'uploading';\n fileEntry.progress = 0;\n\n this.fileSelected.emit(fileEntry.file);\n this.uploadStarted.emit(fileEntry.file);\n\n try {\n // Simulate upload with progress updates\n for (let progress = 0; progress <= 100; progress += 10) {\n // Check if upload was canceled during progress\n // Need to check current status since it might have changed\n if (fileEntry.status !== 'uploading') {\n // Either canceled or errored\n break;\n }\n\n fileEntry.progress = progress;\n\n // Simulate network delay\n await new Promise((resolve) => setTimeout(resolve, 200));\n }\n\n // Only set to complete if still uploading (not canceled or errored)\n if (fileEntry.status === 'uploading') {\n fileEntry.status = 'complete';\n fileEntry.progress = 100;\n this.uploadCompleted.emit(fileEntry.file);\n }\n } catch (error) {\n // Handle errors\n fileEntry.status = 'error';\n const errorMessage = error instanceof Error ? error.message : 'Unknown upload error';\n fileEntry.errorMessage = errorMessage;\n this.emitError(fileEntry.file, errorMessage);\n }\n }\n\n cancelUpload(index: number): void {\n // Cancel the specified file and all files below it\n for (let i = index; i < this.uploadedFiles.length; i++) {\n const fileToCancel = this.uploadedFiles[i];\n if (fileToCancel) {\n const previousStatus = fileToCancel.status;\n if (previousStatus === 'uploading' || previousStatus === 'queued') {\n fileToCancel.status = 'canceled';\n // Only emit if it was actively uploading (not just queued)\n if (previousStatus === 'uploading') {\n this.uploadCanceled.emit(fileToCancel.file);\n }\n }\n }\n }\n // If the file at the specified index was uploading, process the next file in queue\n // (which would now be a file before the index that might be queued)\n if (this.uploadedFiles[index]?.status === 'canceled') {\n setTimeout(() => this.processQueue(), 0);\n }\n }\n\n // Cancel the current upload\n cancelCurrentUpload(): void {\n // Find the file that's currently uploading\n const currentUploadIndex = this.uploadedFiles.findIndex((file) => file.status === 'uploading');\n if (currentUploadIndex >= 0) {\n this.cancelUpload(currentUploadIndex);\n }\n }\n\n // Cancel all uploads\n cancelAllUploads(): void {\n let hadActiveUploads = false;\n\n this.uploadedFiles.forEach((file) => {\n if (file.status === 'uploading' || file.status === 'queued') {\n hadActiveUploads = true;\n const previousStatus = file.status;\n file.status = 'canceled';\n\n if (previousStatus === 'uploading') {\n this.uploadCanceled.emit(file.file);\n }\n }\n });\n\n if (hadActiveUploads && !this.hasQueuedOrUploading) {\n this.updateUploadStatus('idle');\n }\n }\n\n // Remove a file from the list\n removeFile(index: number): void {\n const fileToRemove = this.uploadedFiles[index];\n\n // Cancel first if it's active\n if (fileToRemove.status === 'uploading' || fileToRemove.status === 'queued') {\n this.cancelUpload(index);\n }\n\n // Emit removal event\n this.fileRemoved.emit(fileToRemove.file);\n\n // Remove from array\n this.uploadedFiles.splice(index, 1);\n\n // Reset status if no files left\n if (this.uploadedFiles.length === 0) {\n this.updateUploadStatus('idle');\n } else if (!this.hasQueuedOrUploading && this.uploadStatus !== 'complete') {\n // If there are no more queued or uploading files but we have completed files\n this.updateUploadStatus('complete');\n }\n }\n\n // Remove all files\n removeAllFiles(): void {\n // Cancel any active uploads\n this.cancelAllUploads();\n\n // Only emit if there were files to remove\n if (this.uploadedFiles.length > 0) {\n this.allFilesRemoved.emit();\n }\n\n this.uploadedFiles = [];\n this.updateUploadStatus('idle');\n }\n\n get hasUploading(): boolean {\n return this.uploadedFiles.some((file) => file.status === 'uploading');\n }\n\n get hasQueuedOrUploading(): boolean {\n return this.uploadedFiles.some((file) => file.status === 'uploading' || file.status === 'queued');\n }\n\n get hasErrors(): boolean {\n return this.uploadedFiles.some((file) => file.status === 'error');\n }\n\n get allUploadsComplete(): boolean {\n return this.uploadedFiles.length > 0 && this.uploadedFiles.some((file) => file.status === 'complete') && !this.hasQueuedOrUploading;\n }\n\n get uploadingProgressText(): string {\n // Count active files (excluding canceled ones)\n const totalActiveFiles = this.activeFilesCount;\n const completedCount = this.uploadedFiles.filter((file) => file.status === 'complete').length;\n const uploadingFile = this.uploadedFiles.find((file) => file.status === 'uploading');\n if (uploadingFile) {\n // We're currently uploading the (completedCount + 1)th active file\n return `Uploading ${completedCount}/${totalActiveFiles} file${totalActiveFiles > 1 ? 's' : ''}...`;\n }\n if (this.uploadedFiles.some((file) => file.status === 'queued')) {\n return `Uploading ${completedCount + 1}/${totalActiveFiles} file${totalActiveFiles > 1 ? 's' : ''}...`;\n }\n return `Uploading ${completedCount}/${totalActiveFiles} file${totalActiveFiles > 1 ? 's' : ''}...`;\n }\n\n // Calculate overall progress percentage across all files\n get overallProgress(): number {\n if (this.uploadedFiles.length === 0) return 0;\n\n const totalProgress = this.uploadedFiles.reduce((sum, file) => {\n if (file.status === 'complete') return sum + 100;\n if (file.status === 'canceled' || file.status === 'error') return sum;\n return sum + (file.progress || 0);\n }, 0);\n\n const activeFilesCount = this.uploadedFiles.filter((file) => file.status !== 'canceled' && file.status !== 'error').length;\n\n return activeFilesCount > 0 ? Math.round((totalProgress / (activeFilesCount * 100)) * 100) : 0;\n }\n}\n","<p class=\"cax-files\">{{inputFiles}}</p>\r\n<div class=\"cax-upload-menu\" [ngStyle]=\"style\"\r\n [class.dragging]=\"isDragging\" \r\n (click)=\"openFileSelector()\">\r\n <input\r\n type=\"file\"\r\n id=\"fileInput-{{uniqueId}}\"\r\n style=\"display:none\"\r\n [multiple]=\"allowMultiple\"\r\n [accept]=\"acceptFileTypes\"\r\n (change)=\"handleFileInput($event)\"\r\n />\r\n\r\n <!-- Default Upload State -->\r\n <ng-container *ngIf=\"uploadStatus === 'idle'\" >\r\n <div class=\"cax-upload-options\" >\r\n <p class=\"hint-text\">\r\n <span class=\"drop-files\">Drop files here</span> or browse files from your device\r\n </p>\r\n <p class=\"max-size\">Max. File Size: {{ maxFileSize }}MB</p>\r\n </div>\r\n </ng-container>\r\n\r\n\r\n <!-- Uploading State -->\r\n<div *ngIf=\"uploadStatus === 'uploading'\" class=\"cax-upload-status uploading\" >\r\n <div class=\"status-container\">\r\n <cax-progressSpinner\r\n [strokeColor]=\"'primary'\"\r\n [size]=\"'lg'\"\r\n [animationDuration]=\"'2s'\"\r\n ></cax-progressSpinner>\r\n <p >{{ uploadingProgressText }}</p>\r\n <cax-button\r\n [label]=\"'Cancel'\"\r\n [rounded]=\"false\"\r\n [severity]=\"'danger'\"\r\n [size]=\"'large'\"\r\n [outlined]=\"'false'\"\r\n [link]=\"true\"\r\n (click)=\"cancelCurrentUpload(); $event.stopPropagation()\"\r\n />\r\n </div>\r\n</div>\r\n\r\n <!-- Complete State -->\r\n <div *ngIf=\"uploadStatus === 'complete'\" class=\"cax-upload-status complete\">\r\n <div class=\"status-container\">\r\n <div class=\"success-icon\"><i class=\"cax cax-check\"></i></div>\r\n <p>{{uploadString}}</p>\r\n <cax-button\r\n [label]=\"'Remove'\"\r\n [rounded]=\"false\"\r\n [severity]=\"'danger'\"\r\n [size]=\"'large'\"\r\n [outlined]=\"'false'\"\r\n [link]=\"true\"\r\n (click)=\"removeAllFiles(); $event.stopPropagation()\"\r\n />\r\n </div>\r\n </div>\r\n <div *ngIf=\"invalid\" id=\"helper-text\" class=\"cax-error-upload\"></div>\r\n</div>\r\n<div *ngIf=\"invalid\" id=\"helper-text\" class=\"cax-error-upload\">\r\n {{ errorText }}\r\n</div>\r\n\r\n<!-- stacked file -->\r\n<div *ngIf=\"uploadedFiles.length > 0\" class=\"cax-file-preview-wrapper\" [ngStyle]=\"style\">\r\n <div\r\n *ngFor=\"let item of uploadedFiles; let i = index\"\r\n class=\"cax-file-preview\"\r\n [ngClass]=\"{\r\n 'queued': item.status === 'queued',\r\n 'uploading': item.status === 'uploading',\r\n 'complete': item.status === 'complete',\r\n 'canceled': item.status === 'canceled'\r\n }\"\r\n >\r\n <div class=\"file-info\">\r\n <p class=\"file-name\">{{ item.file.name }}</p>\r\n </div> \r\n\r\n <!-- Show spinner for queued or uploading files -->\r\n <div *ngIf=\"item.status === 'queued' || item.status === 'uploading'\" class=\"spinner\">\r\n <cax-progressSpinner\r\n [strokeColor]=\"'primary'\"\r\n [size]=\"'sm'\"\r\n [animationDuration]=\"'2s'\">\r\n </cax-progressSpinner>\r\n </div>\r\n \r\n <!-- Show remove button only for complete or canceled files -->\r\n <button\r\n *ngIf=\"item.status === 'complete' || item.status === 'canceled'\"\r\n class=\"remove-button\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\">\r\n <i class=\"cax cax-close\"></i> \r\n </button>\r\n </div>\r\n</div>","import { CommonModule } from '@angular/common';\nimport { UploadComponent } from './upload.component';\nimport { FormsModule } from '@angular/forms';\nimport { NgModule } from '@angular/core';\nimport { ProgressSpinnerModule } from 'cax-design-system/progressspinner';\nimport { Button } from 'cax-design-system/button';\n\n@NgModule({\n declarations: [UploadComponent],\n imports: [CommonModule, FormsModule, ProgressSpinnerModule, Button],\n exports: [UploadComponent]\n})\nexport class UploadModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|