cloud-ide-element 1.0.52 → 1.0.54
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/fesm2022/cloud-ide-element.mjs +197 -52
- package/fesm2022/cloud-ide-element.mjs.map +1 -1
- package/index.d.ts +42 -6
- package/package.json +1 -1
|
@@ -2570,18 +2570,30 @@ class CideEleFileManagerService {
|
|
|
2570
2570
|
this.http = http;
|
|
2571
2571
|
}
|
|
2572
2572
|
/**
|
|
2573
|
-
* Upload a file with base64 encoding
|
|
2573
|
+
* Upload a file with base64 encoding and progress tracking
|
|
2574
2574
|
* @param file The file to upload
|
|
2575
2575
|
* @param additionalData Additional data to include in the payload
|
|
2576
|
+
* @param progressCallback Optional callback for progress updates
|
|
2576
2577
|
* @returns Observable with the upload response
|
|
2577
2578
|
*/
|
|
2578
|
-
uploadFile(file, additionalData) {
|
|
2579
|
-
// Convert file to base64
|
|
2579
|
+
uploadFile(file, additionalData, progressCallback) {
|
|
2580
|
+
// Convert file to base64 with progress tracking
|
|
2580
2581
|
return new Observable(observer => {
|
|
2581
2582
|
const reader = new FileReader();
|
|
2583
|
+
// Track file reading progress
|
|
2584
|
+
reader.onprogress = (event) => {
|
|
2585
|
+
if (event.lengthComputable && progressCallback) {
|
|
2586
|
+
const progress = (event.loaded / event.total) * 50; // File reading is 50% of total progress
|
|
2587
|
+
progressCallback(progress);
|
|
2588
|
+
}
|
|
2589
|
+
};
|
|
2582
2590
|
reader.onload = () => {
|
|
2583
2591
|
const base64String = reader.result;
|
|
2584
2592
|
const base64Data = base64String.split(',')[1]; // Remove data:image/jpeg;base64, prefix
|
|
2593
|
+
// Update progress to 50% (file reading complete)
|
|
2594
|
+
if (progressCallback) {
|
|
2595
|
+
progressCallback(50);
|
|
2596
|
+
}
|
|
2585
2597
|
const payload = {
|
|
2586
2598
|
cyfm_name: file.name,
|
|
2587
2599
|
cyfm_alt_text: additionalData?.altText || file.name,
|
|
@@ -2598,10 +2610,24 @@ class CideEleFileManagerService {
|
|
|
2598
2610
|
fileData: base64Data, // Base64 file data
|
|
2599
2611
|
...additionalData
|
|
2600
2612
|
};
|
|
2601
|
-
// Make the HTTP request
|
|
2602
|
-
this.http.post(`${this.baseUrl}
|
|
2603
|
-
|
|
2604
|
-
|
|
2613
|
+
// Make the HTTP request with progress tracking
|
|
2614
|
+
this.http.post(`${this.baseUrl}`, payload, {
|
|
2615
|
+
reportProgress: true,
|
|
2616
|
+
observe: 'events'
|
|
2617
|
+
}).subscribe({
|
|
2618
|
+
next: (event) => {
|
|
2619
|
+
if (event.type === 1 && progressCallback) { // HttpEventType.UploadProgress
|
|
2620
|
+
const uploadProgress = (event.loaded / event.total) * 50; // Upload is remaining 50%
|
|
2621
|
+
const totalProgress = 50 + uploadProgress; // Total progress (50% file reading + upload progress)
|
|
2622
|
+
progressCallback(totalProgress);
|
|
2623
|
+
}
|
|
2624
|
+
else if (event.type === 4) { // HttpEventType.Response
|
|
2625
|
+
if (progressCallback) {
|
|
2626
|
+
progressCallback(100);
|
|
2627
|
+
}
|
|
2628
|
+
observer.next(event.body);
|
|
2629
|
+
}
|
|
2630
|
+
},
|
|
2605
2631
|
error: (error) => observer.error(error)
|
|
2606
2632
|
});
|
|
2607
2633
|
};
|
|
@@ -2849,10 +2875,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
2849
2875
|
class CideEleFileInputComponent {
|
|
2850
2876
|
fileManagerService = inject(CideEleFileManagerService);
|
|
2851
2877
|
notificationService = inject(NotificationService);
|
|
2878
|
+
elementService = inject(CideElementsService);
|
|
2852
2879
|
label = 'Choose file';
|
|
2853
2880
|
accept = '';
|
|
2854
2881
|
multiple = false;
|
|
2855
2882
|
disabled = false;
|
|
2883
|
+
required = false;
|
|
2856
2884
|
helperText = '';
|
|
2857
2885
|
errorText = '';
|
|
2858
2886
|
showPreview = false;
|
|
@@ -2867,6 +2895,7 @@ class CideEleFileInputComponent {
|
|
|
2867
2895
|
id = Math.random().toString(36).substring(2, 10);
|
|
2868
2896
|
isUploading = false;
|
|
2869
2897
|
uploadProgress = 0;
|
|
2898
|
+
uploadStatus = 'idle';
|
|
2870
2899
|
uploadNotificationId = null;
|
|
2871
2900
|
fileChange = new EventEmitter();
|
|
2872
2901
|
uploadSuccess = new EventEmitter();
|
|
@@ -2879,7 +2908,9 @@ class CideEleFileInputComponent {
|
|
|
2879
2908
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2880
2909
|
onChange = (files) => { };
|
|
2881
2910
|
onTouched = () => { };
|
|
2911
|
+
onValidatorChange = () => { };
|
|
2882
2912
|
writeValue(files) {
|
|
2913
|
+
console.log('📝 [FileInput] writeValue called with:', files ? Array.from(files).map(f => f.name) : 'null');
|
|
2883
2914
|
this.files = files;
|
|
2884
2915
|
this.fileNames = files ? Array.from(files).map(f => f.name) : [];
|
|
2885
2916
|
this.generatePreviews();
|
|
@@ -2890,81 +2921,125 @@ class CideEleFileInputComponent {
|
|
|
2890
2921
|
registerOnTouched(fn) {
|
|
2891
2922
|
this.onTouched = fn;
|
|
2892
2923
|
}
|
|
2924
|
+
registerOnValidatorChange(fn) {
|
|
2925
|
+
this.onValidatorChange = fn;
|
|
2926
|
+
}
|
|
2893
2927
|
setDisabledState(isDisabled) {
|
|
2894
2928
|
this.disabled = isDisabled;
|
|
2895
2929
|
}
|
|
2896
2930
|
onFileSelected(event) {
|
|
2931
|
+
console.log('🔍 [FileInput] onFileSelected called');
|
|
2897
2932
|
const input = event.target;
|
|
2898
2933
|
this.files = input.files;
|
|
2899
2934
|
this.fileNames = this.files ? Array.from(this.files).map(f => f.name) : [];
|
|
2935
|
+
console.log('📁 [FileInput] Files selected:', this.fileNames);
|
|
2900
2936
|
this.generatePreviews();
|
|
2937
|
+
// Reset upload status when new file is selected
|
|
2938
|
+
this.uploadStatus = 'idle';
|
|
2939
|
+
console.log('🔄 [FileInput] Upload status reset to:', this.uploadStatus);
|
|
2901
2940
|
this.onChange(this.files);
|
|
2902
2941
|
this.fileChange.emit(this.files);
|
|
2903
2942
|
this.onTouched();
|
|
2943
|
+
this.onValidatorChange();
|
|
2904
2944
|
// Auto upload if enabled
|
|
2905
2945
|
if (this.autoUpload && this.files && this.files.length > 0) {
|
|
2946
|
+
console.log('🚀 [FileInput] Auto upload enabled, starting upload for:', this.files[0].name);
|
|
2906
2947
|
this.uploadFile(this.files[0]);
|
|
2907
2948
|
}
|
|
2949
|
+
else {
|
|
2950
|
+
console.log('⏸️ [FileInput] Auto upload disabled or no files');
|
|
2951
|
+
}
|
|
2908
2952
|
}
|
|
2909
2953
|
clearFiles() {
|
|
2954
|
+
console.log('🗑️ [FileInput] clearFiles called');
|
|
2910
2955
|
this.files = null;
|
|
2911
2956
|
this.fileNames = [];
|
|
2912
2957
|
this.clearPreviews();
|
|
2958
|
+
this.uploadStatus = 'idle';
|
|
2959
|
+
console.log('🔄 [FileInput] Upload status reset to:', this.uploadStatus);
|
|
2913
2960
|
this.onChange(null);
|
|
2914
2961
|
this.fileChange.emit(null);
|
|
2962
|
+
this.onValidatorChange();
|
|
2915
2963
|
}
|
|
2916
2964
|
uploadFile(file) {
|
|
2965
|
+
console.log('📤 [FileInput] uploadFile called for:', file.name, 'Size:', file.size, 'bytes');
|
|
2966
|
+
// Set upload status to 'start' before starting upload
|
|
2967
|
+
this.uploadStatus = 'start';
|
|
2968
|
+
console.log('🔄 [FileInput] Upload status set to:', this.uploadStatus);
|
|
2969
|
+
// Trigger validation update to show upload in progress error
|
|
2970
|
+
this.onValidatorChange();
|
|
2971
|
+
console.log('✅ [FileInput] Validation triggered - should show upload in progress error');
|
|
2917
2972
|
this.isUploading = true;
|
|
2918
2973
|
this.uploadProgress = 0;
|
|
2919
2974
|
this.uploadProgressChange.emit(0);
|
|
2920
|
-
|
|
2975
|
+
console.log('📊 [FileInput] Upload progress initialized to 0%');
|
|
2976
|
+
// Make form control invalid during upload - this prevents form submission
|
|
2921
2977
|
this.onChange(null);
|
|
2922
|
-
|
|
2923
|
-
// this.fileManagerService.setBaseUrl(this.baseUrl);
|
|
2978
|
+
console.log('🚫 [FileInput] Form control value set to null to prevent submission');
|
|
2924
2979
|
// Show initial progress notification
|
|
2925
2980
|
this.uploadNotificationId = this.notificationService.showProgress('Starting file upload...', 0);
|
|
2926
|
-
|
|
2927
|
-
this.
|
|
2928
|
-
|
|
2981
|
+
console.log('🔔 [FileInput] Progress notification started with ID:', this.uploadNotificationId);
|
|
2982
|
+
this.fileManagerService.uploadFile(file, this.uploadData, (progress) => {
|
|
2983
|
+
// Real progress callback from file manager service
|
|
2984
|
+
this.uploadProgress = progress;
|
|
2985
|
+
this.uploadProgressChange.emit(progress);
|
|
2986
|
+
console.log('📈 [FileInput] Upload progress:', Math.round(progress) + '%');
|
|
2987
|
+
// Set upload status to 'uploading' when progress starts
|
|
2988
|
+
if (this.uploadStatus === 'start') {
|
|
2989
|
+
this.uploadStatus = 'uploading';
|
|
2990
|
+
console.log('🔄 [FileInput] Upload status changed to:', this.uploadStatus);
|
|
2991
|
+
this.onValidatorChange();
|
|
2992
|
+
console.log('✅ [FileInput] Validation triggered after status change to uploading');
|
|
2993
|
+
}
|
|
2994
|
+
// Update progress notification
|
|
2995
|
+
if (this.uploadNotificationId) {
|
|
2996
|
+
this.notificationService.updateProgress(this.uploadNotificationId, progress, `Uploading file... ${Math.round(progress)}%`);
|
|
2997
|
+
}
|
|
2998
|
+
}).subscribe({
|
|
2929
2999
|
next: (response) => {
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
}
|
|
3000
|
+
console.log('🎉 [FileInput] Upload SUCCESS - Response received:', response);
|
|
3001
|
+
// Set upload status to 'success'
|
|
3002
|
+
this.uploadStatus = 'success';
|
|
3003
|
+
console.log('🔄 [FileInput] Upload status set to:', this.uploadStatus);
|
|
2935
3004
|
// Complete the progress
|
|
2936
3005
|
this.uploadProgress = 100;
|
|
2937
3006
|
this.uploadProgressChange.emit(100);
|
|
3007
|
+
console.log('📊 [FileInput] Upload progress completed: 100%');
|
|
2938
3008
|
// Update progress notification to complete
|
|
2939
3009
|
if (this.uploadNotificationId) {
|
|
2940
3010
|
this.notificationService.remove(this.uploadNotificationId);
|
|
3011
|
+
console.log('🔔 [FileInput] Progress notification removed');
|
|
2941
3012
|
}
|
|
2942
3013
|
this.notificationService.success('File upload completed!');
|
|
2943
3014
|
this.uploadNotificationId = null;
|
|
2944
3015
|
// Extract ID from response - the file manager returns the _id of the created record
|
|
2945
3016
|
const uploadedId = response?._id || response?.data?._id || response?.id || response?.fileId;
|
|
2946
3017
|
if (uploadedId) {
|
|
2947
|
-
console.log('✅ File uploaded successfully with ID:', uploadedId);
|
|
3018
|
+
console.log('✅ [FileInput] File uploaded successfully with ID:', uploadedId);
|
|
2948
3019
|
this.uploadSuccess.emit(uploadedId);
|
|
2949
3020
|
// Update the form control value with the uploaded file ID
|
|
2950
3021
|
this.onChange(uploadedId);
|
|
3022
|
+
console.log('📝 [FileInput] Form control value updated with uploaded file ID');
|
|
2951
3023
|
}
|
|
2952
3024
|
else {
|
|
2953
|
-
console.error('❌ Upload successful but no ID returned:', response);
|
|
3025
|
+
console.error('❌ [FileInput] Upload successful but no ID returned:', response);
|
|
2954
3026
|
this.uploadError.emit('Upload successful but no ID returned');
|
|
2955
3027
|
}
|
|
2956
3028
|
this.isUploading = false;
|
|
3029
|
+
console.log('🔄 [FileInput] isUploading set to false');
|
|
3030
|
+
// Trigger validation update to clear upload in progress error
|
|
3031
|
+
this.onValidatorChange();
|
|
3032
|
+
console.log('✅ [FileInput] Validation triggered - should clear upload in progress error');
|
|
2957
3033
|
},
|
|
2958
3034
|
error: (error) => {
|
|
2959
|
-
console.error('
|
|
2960
|
-
//
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
this.progressInterval = null;
|
|
2964
|
-
}
|
|
3035
|
+
console.error('💥 [FileInput] Upload FAILED:', error);
|
|
3036
|
+
// Set upload status to 'error' and remove upload validation error
|
|
3037
|
+
this.uploadStatus = 'error';
|
|
3038
|
+
console.log('🔄 [FileInput] Upload status set to:', this.uploadStatus);
|
|
2965
3039
|
// Remove progress notification and show error
|
|
2966
3040
|
if (this.uploadNotificationId) {
|
|
2967
3041
|
this.notificationService.remove(this.uploadNotificationId);
|
|
3042
|
+
console.log('🔔 [FileInput] Progress notification removed due to error');
|
|
2968
3043
|
}
|
|
2969
3044
|
this.notificationService.error(`Upload failed: ${error.message || error.error?.message || 'Upload failed'}`);
|
|
2970
3045
|
this.uploadNotificationId = null;
|
|
@@ -2972,27 +3047,13 @@ class CideEleFileInputComponent {
|
|
|
2972
3047
|
this.isUploading = false;
|
|
2973
3048
|
this.uploadProgress = 0;
|
|
2974
3049
|
this.uploadProgressChange.emit(0);
|
|
3050
|
+
console.log('🔄 [FileInput] Upload state reset - isUploading: false, progress: 0%');
|
|
3051
|
+
// Trigger validation update to clear upload in progress error
|
|
3052
|
+
this.onValidatorChange();
|
|
3053
|
+
console.log('✅ [FileInput] Validation triggered - should clear upload in progress error');
|
|
2975
3054
|
}
|
|
2976
3055
|
});
|
|
2977
3056
|
}
|
|
2978
|
-
progressInterval = null;
|
|
2979
|
-
simulateProgress() {
|
|
2980
|
-
this.progressInterval = setInterval(() => {
|
|
2981
|
-
if (this.uploadProgress < 95 && this.isUploading) { // Continue until 95% and still uploading
|
|
2982
|
-
this.uploadProgress += Math.random() * 5; // Smaller increments for smoother progress
|
|
2983
|
-
this.uploadProgressChange.emit(this.uploadProgress);
|
|
2984
|
-
// Update progress notification
|
|
2985
|
-
if (this.uploadNotificationId) {
|
|
2986
|
-
this.notificationService.updateProgress(this.uploadNotificationId, this.uploadProgress, `Uploading file... ${Math.round(this.uploadProgress)}%`);
|
|
2987
|
-
}
|
|
2988
|
-
}
|
|
2989
|
-
else if (this.uploadProgress >= 95) {
|
|
2990
|
-
// Stop at 95% and wait for actual API response
|
|
2991
|
-
clearInterval(this.progressInterval);
|
|
2992
|
-
this.progressInterval = null;
|
|
2993
|
-
}
|
|
2994
|
-
}, 400); // Slightly slower updates
|
|
2995
|
-
}
|
|
2996
3057
|
generatePreviews() {
|
|
2997
3058
|
// Clear existing previews
|
|
2998
3059
|
this.clearPreviews();
|
|
@@ -3049,11 +3110,6 @@ class CideEleFileInputComponent {
|
|
|
3049
3110
|
ngOnDestroy() {
|
|
3050
3111
|
// Clean up preview URLs to prevent memory leaks
|
|
3051
3112
|
this.clearPreviews();
|
|
3052
|
-
// Clean up progress interval
|
|
3053
|
-
if (this.progressInterval) {
|
|
3054
|
-
clearInterval(this.progressInterval);
|
|
3055
|
-
this.progressInterval = null;
|
|
3056
|
-
}
|
|
3057
3113
|
// Clean up any active upload notification
|
|
3058
3114
|
if (this.uploadNotificationId) {
|
|
3059
3115
|
this.notificationService.remove(this.uploadNotificationId);
|
|
@@ -3072,14 +3128,96 @@ class CideEleFileInputComponent {
|
|
|
3072
3128
|
hasImages() {
|
|
3073
3129
|
return this.previewUrls.length > 0;
|
|
3074
3130
|
}
|
|
3131
|
+
isRequired() {
|
|
3132
|
+
return this.required;
|
|
3133
|
+
}
|
|
3134
|
+
getCurrentState() {
|
|
3135
|
+
return {
|
|
3136
|
+
id: this.id,
|
|
3137
|
+
label: this.label,
|
|
3138
|
+
required: this.required,
|
|
3139
|
+
disabled: this.disabled,
|
|
3140
|
+
accept: this.accept,
|
|
3141
|
+
multiple: this.multiple,
|
|
3142
|
+
showPreview: this.showPreview,
|
|
3143
|
+
autoUpload: this.autoUpload,
|
|
3144
|
+
uploadStatus: this.uploadStatus,
|
|
3145
|
+
isUploading: this.isUploading,
|
|
3146
|
+
uploadProgress: this.uploadProgress,
|
|
3147
|
+
files: this.files ? Array.from(this.files).map(f => ({ name: f.name, size: f.size, type: f.type })) : null,
|
|
3148
|
+
fileNames: this.fileNames,
|
|
3149
|
+
previewUrls: this.previewUrls.length,
|
|
3150
|
+
helperText: this.helperText,
|
|
3151
|
+
errorText: this.errorText,
|
|
3152
|
+
placeholderText: this.placeholderText,
|
|
3153
|
+
placeholderIcon: this.placeholderIcon,
|
|
3154
|
+
previewWidth: this.previewWidth,
|
|
3155
|
+
previewHeight: this.previewHeight,
|
|
3156
|
+
previewBoxMode: this.previewBoxMode,
|
|
3157
|
+
showFileName: this.showFileName,
|
|
3158
|
+
uploadData: this.uploadData
|
|
3159
|
+
};
|
|
3160
|
+
}
|
|
3161
|
+
async getControlData() {
|
|
3162
|
+
console.log('🔍 [FileInput] getControlData called');
|
|
3163
|
+
const cide_element_data = await this.elementService?.getElementData({ sype_key: this.id });
|
|
3164
|
+
if (cide_element_data) {
|
|
3165
|
+
console.log('📋 [FileInput] Element data loaded:', cide_element_data);
|
|
3166
|
+
// Update basic properties that exist in ICoreSype
|
|
3167
|
+
this.label = cide_element_data?.sype_label;
|
|
3168
|
+
this.required = (cide_element_data?.sype_required || false);
|
|
3169
|
+
this.placeholderText = (cide_element_data?.sype_placeholder || 'Click to select image');
|
|
3170
|
+
// Update file-input specific properties from data object if available
|
|
3171
|
+
const data = cide_element_data?.data;
|
|
3172
|
+
if (data) {
|
|
3173
|
+
this.accept = data.accept || '';
|
|
3174
|
+
this.multiple = data.multiple || false;
|
|
3175
|
+
this.showPreview = data.showPreview || false;
|
|
3176
|
+
this.autoUpload = data.autoUpload || false;
|
|
3177
|
+
this.placeholderIcon = data.placeholderIcon || '📷';
|
|
3178
|
+
this.previewWidth = data.previewWidth || '200px';
|
|
3179
|
+
this.previewHeight = data.previewHeight || '200px';
|
|
3180
|
+
this.previewBoxMode = data.previewBoxMode || false;
|
|
3181
|
+
this.showFileName = data.showFileName || true;
|
|
3182
|
+
this.uploadData = data.uploadData || {};
|
|
3183
|
+
}
|
|
3184
|
+
console.log('✅ [FileInput] Control data updated from element service');
|
|
3185
|
+
// Trigger validation update
|
|
3186
|
+
this.onValidatorChange();
|
|
3187
|
+
}
|
|
3188
|
+
else {
|
|
3189
|
+
console.log('⚠️ [FileInput] No element data found for key:', this.id);
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
// Validator implementation
|
|
3193
|
+
validate(control) {
|
|
3194
|
+
console.log('🔍 [FileInput] validate() called - uploadStatus:', this.uploadStatus, 'required:', this.required, 'files:', !!this.files, 'control.value:', control.value);
|
|
3195
|
+
// If upload is in progress (start or uploading status), return validation error
|
|
3196
|
+
if (this.uploadStatus === 'start' || this.uploadStatus === 'uploading') {
|
|
3197
|
+
console.log('⚠️ [FileInput] Validation ERROR: Upload in progress');
|
|
3198
|
+
return { 'uploadInProgress': { message: 'File upload in progress. Please wait...' } };
|
|
3199
|
+
}
|
|
3200
|
+
// If required and no file is selected and no control value (uploaded file ID), return validation error
|
|
3201
|
+
if (this.required && !this.files && !control.value) {
|
|
3202
|
+
console.log('⚠️ [FileInput] Validation ERROR: File required');
|
|
3203
|
+
return { 'required': { message: 'Please select a file to upload.' } };
|
|
3204
|
+
}
|
|
3205
|
+
console.log('✅ [FileInput] Validation PASSED: No errors');
|
|
3206
|
+
return null; // No validation errors
|
|
3207
|
+
}
|
|
3075
3208
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFileInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3076
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CideEleFileInputComponent, isStandalone: true, selector: "cide-ele-file-input", inputs: { label: "label", accept: "accept", multiple: "multiple", disabled: "disabled", helperText: "helperText", errorText: "errorText", showPreview: "showPreview", previewWidth: "previewWidth", previewHeight: "previewHeight", previewBoxMode: "previewBoxMode", showFileName: "showFileName", placeholderText: "placeholderText", placeholderIcon: "placeholderIcon", autoUpload: "autoUpload", uploadData: "uploadData" }, outputs: { fileChange: "fileChange", uploadSuccess: "uploadSuccess", uploadError: "uploadError", uploadProgressChange: "uploadProgressChange" }, providers: [
|
|
3209
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CideEleFileInputComponent, isStandalone: true, selector: "cide-ele-file-input", inputs: { label: "label", accept: "accept", multiple: "multiple", disabled: "disabled", required: "required", helperText: "helperText", errorText: "errorText", showPreview: "showPreview", previewWidth: "previewWidth", previewHeight: "previewHeight", previewBoxMode: "previewBoxMode", showFileName: "showFileName", placeholderText: "placeholderText", placeholderIcon: "placeholderIcon", autoUpload: "autoUpload", uploadData: "uploadData" }, outputs: { fileChange: "fileChange", uploadSuccess: "uploadSuccess", uploadError: "uploadError", uploadProgressChange: "uploadProgressChange" }, providers: [
|
|
3077
3210
|
{
|
|
3078
3211
|
provide: NG_VALUE_ACCESSOR,
|
|
3079
3212
|
useExisting: forwardRef(() => CideEleFileInputComponent),
|
|
3080
3213
|
multi: true
|
|
3214
|
+
},
|
|
3215
|
+
{
|
|
3216
|
+
provide: NG_VALIDATORS,
|
|
3217
|
+
useExisting: forwardRef(() => CideEleFileInputComponent),
|
|
3218
|
+
multi: true
|
|
3081
3219
|
}
|
|
3082
|
-
], ngImport: i0, template: "<div class=\"cide-file-input\">\n <!-- Label (shown when not in preview box mode or when preview box mode but no label override) -->\n <label *ngIf=\"label && !isPreviewBoxMode()\" class=\"cide-file-input-label\" [attr.for]=\"'cide-file-input-' + id\"
|
|
3220
|
+
], ngImport: i0, template: "<div class=\"cide-file-input\">\n <!-- Label (shown when not in preview box mode or when preview box mode but no label override) -->\n <label *ngIf=\"label && !isPreviewBoxMode()\" class=\"cide-file-input-label\" [attr.for]=\"'cide-file-input-' + id\">\n {{ label }}<span *ngIf=\"required\" class=\"cide-file-input-required\"> *</span>\n </label>\n \n <!-- Preview Box Mode -->\n <div *ngIf=\"isPreviewBoxMode()\" class=\"cide-file-input-preview-box-container\">\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id\"\n [attr.accept]=\"accept\"\n [attr.multiple]=\"multiple ? true : null\"\n [disabled]=\"disabled\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Preview Box -->\n <div \n class=\"cide-file-input-preview-box\"\n [class.cide-file-input-preview-box-disabled]=\"disabled\"\n [class.cide-file-input-preview-box-has-image]=\"hasImages()\"\n [style.width]=\"previewWidth\"\n [style.height]=\"previewHeight\"\n (click)=\"triggerFileSelect()\"\n [attr.title]=\"disabled ? 'File selection disabled' : placeholderText\">\n \n <!-- No Image State -->\n <div *ngIf=\"!hasImages()\" class=\"cide-file-input-preview-box-placeholder\">\n <div class=\"cide-file-input-preview-box-icon\">\n <cide-ele-icon>{{ placeholderIcon }}</cide-ele-icon>\n </div>\n <div class=\"cide-file-input-preview-box-text\">{{ placeholderText }}</div>\n </div>\n \n <!-- Image Preview State -->\n <div *ngIf=\"hasImages()\" class=\"cide-file-input-preview-box-content\">\n <img \n [src]=\"previewUrls[0]\" \n [alt]=\"fileNames[0] || 'Preview image'\"\n class=\"cide-file-input-preview-box-image\">\n <div class=\"cide-file-input-preview-box-overlay\">\n <div class=\"cide-file-input-preview-box-overlay-text\">Click to change</div>\n </div>\n <button \n *ngIf=\"!disabled\"\n type=\"button\" \n class=\"cide-file-input-preview-box-remove\"\n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Remove image\">\n \u00D7\n </button>\n </div>\n </div>\n \n <!-- File name display for preview box mode -->\n <div *ngIf=\"hasImages() && fileNames.length && showFileName\" class=\"cide-file-input-preview-box-filename\">\n {{ fileNames[0] }}\n </div>\n </div>\n\n <!-- Standard Mode -->\n <div *ngIf=\"!isPreviewBoxMode()\" class=\"cide-file-input-wrapper\">\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id\"\n [attr.accept]=\"accept\"\n [attr.multiple]=\"multiple ? true : null\"\n [disabled]=\"disabled\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-element\"\n />\n <button *ngIf=\"fileNames.length\" type=\"button\" class=\"cide-file-input-clear\" (click)=\"clearFiles()\">\n Clear\n </button>\n </div>\n <div *ngIf=\"fileNames.length && !isPreviewBoxMode()\" class=\"cide-file-input-files\">\n <span *ngFor=\"let name of fileNames\">{{ name }}</span>\n </div>\n \n <!-- Image Preview Section (only for standard mode) -->\n <div *ngIf=\"isImagePreviewAvailable() && !isPreviewBoxMode()\" class=\"cide-file-input-preview\">\n <div class=\"cide-file-input-preview-label\">Preview:</div>\n <div class=\"cide-file-input-preview-container\">\n <div \n *ngFor=\"let previewUrl of previewUrls; let i = index\" \n class=\"cide-file-input-preview-item\"\n [style.width]=\"previewWidth\"\n [style.height]=\"previewHeight\">\n <button \n type=\"button\" \n class=\"cide-file-input-preview-remove\"\n (click)=\"removePreview(i)\"\n title=\"Remove image\">\n \u00D7\n </button>\n <img \n [src]=\"previewUrl\" \n [alt]=\"fileNames[i] || 'Preview image'\"\n class=\"cide-file-input-preview-image\"\n loading=\"lazy\">\n <div class=\"cide-file-input-preview-filename\">{{ fileNames[i] }}</div>\n </div>\n </div>\n </div>\n \n <div *ngIf=\"errorText\" class=\"cide-file-input-error\">{{ errorText }}</div>\n <div *ngIf=\"helperText && !errorText\" class=\"cide-file-input-helper\">{{ helperText }}</div>\n</div> ", styles: [".cide-file-input{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-label{font-weight:500;margin-bottom:.25rem}.cide-file-input-required{color:#d32f2f;font-weight:700}.cide-file-input-wrapper{display:flex;align-items:center;gap:.5rem}.cide-file-input-element{flex:1}.cide-file-input-clear{background:none;border:none;color:#d32f2f;cursor:pointer;font-size:.9rem}.cide-file-input-files{font-size:.95rem;color:#333;margin-top:.25rem}.cide-file-input-error{color:#d32f2f;font-size:.9rem}.cide-file-input-helper{color:#666;font-size:.9rem}.cide-file-input-preview{margin-top:.75rem;padding:.75rem;background-color:#f8f9fa;border:1px solid #e1e5e9;border-radius:.375rem}.cide-file-input-preview-label{font-weight:500;margin-bottom:.5rem;color:#374151;font-size:.875rem}.cide-file-input-preview-container{display:flex;flex-wrap:wrap;gap:.75rem}.cide-file-input-preview-item{position:relative;display:flex;flex-direction:column;border:1px solid #d1d5db;border-radius:.5rem;overflow:hidden;background-color:#fff;box-shadow:0 1px 3px #0000001a;transition:box-shadow .2s ease-in-out}.cide-file-input-preview-item:hover{box-shadow:0 4px 6px -1px #0000001a}.cide-file-input-preview-image{width:100%;height:calc(100% - 2rem);object-fit:cover;object-position:center;background-color:#f3f4f6}.cide-file-input-preview-filename{padding:.375rem .5rem;background-color:#f9fafbf2;border-top:1px solid #e5e7eb;font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:2rem;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-remove{position:absolute;top:.25rem;right:.25rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;transition:all .2s ease-in-out}.cide-file-input-preview-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-hidden{display:none}.cide-file-input-preview-box-container{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-preview-box{position:relative;border:2px dashed #d1d5db;border-radius:.5rem;cursor:pointer;background-color:#f9fafb;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:all .2s ease-in-out}.cide-file-input-preview-box:hover{border-color:#3b82f6;background-color:#eff6ff}.cide-file-input-preview-box.cide-file-input-preview-box-disabled{cursor:not-allowed;opacity:.6;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-disabled:hover{border-color:#d1d5db;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image{border-style:solid;border-color:#e5e7eb;padding:0}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover{border-color:#3b82f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover .cide-file-input-preview-box-overlay{opacity:1}.cide-file-input-preview-box-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1rem;text-align:center}.cide-file-input-preview-box-icon{font-size:2rem;color:#6b7280}.cide-file-input-preview-box-text{font-size:.875rem;color:#6b7280;font-weight:500}.cide-file-input-preview-box-content{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-box-image{width:100%;height:100%;object-fit:cover;object-position:center}.cide-file-input-preview-box-overlay{position:absolute;inset:0;background-color:#0009;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease-in-out}.cide-file-input-preview-box-overlay-text{color:#fff;font-size:.875rem;font-weight:500;text-align:center}.cide-file-input-preview-box-remove{position:absolute;top:.375rem;right:.375rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:20;transition:all .2s ease-in-out}.cide-file-input-preview-box-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-box-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-preview-box-filename{font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;margin-top:.25rem}@media (max-width: 640px){.cide-file-input-preview-container{justify-content:center}.cide-file-input-preview-item{min-width:120px;max-width:150px}.cide-file-input-preview-box-icon{font-size:1.5rem}.cide-file-input-preview-box-text{font-size:.75rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
|
|
3083
3221
|
}
|
|
3084
3222
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFileInputComponent, decorators: [{
|
|
3085
3223
|
type: Component,
|
|
@@ -3088,8 +3226,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
3088
3226
|
provide: NG_VALUE_ACCESSOR,
|
|
3089
3227
|
useExisting: forwardRef(() => CideEleFileInputComponent),
|
|
3090
3228
|
multi: true
|
|
3229
|
+
},
|
|
3230
|
+
{
|
|
3231
|
+
provide: NG_VALIDATORS,
|
|
3232
|
+
useExisting: forwardRef(() => CideEleFileInputComponent),
|
|
3233
|
+
multi: true
|
|
3091
3234
|
}
|
|
3092
|
-
], template: "<div class=\"cide-file-input\">\n <!-- Label (shown when not in preview box mode or when preview box mode but no label override) -->\n <label *ngIf=\"label && !isPreviewBoxMode()\" class=\"cide-file-input-label\" [attr.for]=\"'cide-file-input-' + id\"
|
|
3235
|
+
], template: "<div class=\"cide-file-input\">\n <!-- Label (shown when not in preview box mode or when preview box mode but no label override) -->\n <label *ngIf=\"label && !isPreviewBoxMode()\" class=\"cide-file-input-label\" [attr.for]=\"'cide-file-input-' + id\">\n {{ label }}<span *ngIf=\"required\" class=\"cide-file-input-required\"> *</span>\n </label>\n \n <!-- Preview Box Mode -->\n <div *ngIf=\"isPreviewBoxMode()\" class=\"cide-file-input-preview-box-container\">\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id\"\n [attr.accept]=\"accept\"\n [attr.multiple]=\"multiple ? true : null\"\n [disabled]=\"disabled\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Preview Box -->\n <div \n class=\"cide-file-input-preview-box\"\n [class.cide-file-input-preview-box-disabled]=\"disabled\"\n [class.cide-file-input-preview-box-has-image]=\"hasImages()\"\n [style.width]=\"previewWidth\"\n [style.height]=\"previewHeight\"\n (click)=\"triggerFileSelect()\"\n [attr.title]=\"disabled ? 'File selection disabled' : placeholderText\">\n \n <!-- No Image State -->\n <div *ngIf=\"!hasImages()\" class=\"cide-file-input-preview-box-placeholder\">\n <div class=\"cide-file-input-preview-box-icon\">\n <cide-ele-icon>{{ placeholderIcon }}</cide-ele-icon>\n </div>\n <div class=\"cide-file-input-preview-box-text\">{{ placeholderText }}</div>\n </div>\n \n <!-- Image Preview State -->\n <div *ngIf=\"hasImages()\" class=\"cide-file-input-preview-box-content\">\n <img \n [src]=\"previewUrls[0]\" \n [alt]=\"fileNames[0] || 'Preview image'\"\n class=\"cide-file-input-preview-box-image\">\n <div class=\"cide-file-input-preview-box-overlay\">\n <div class=\"cide-file-input-preview-box-overlay-text\">Click to change</div>\n </div>\n <button \n *ngIf=\"!disabled\"\n type=\"button\" \n class=\"cide-file-input-preview-box-remove\"\n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Remove image\">\n \u00D7\n </button>\n </div>\n </div>\n \n <!-- File name display for preview box mode -->\n <div *ngIf=\"hasImages() && fileNames.length && showFileName\" class=\"cide-file-input-preview-box-filename\">\n {{ fileNames[0] }}\n </div>\n </div>\n\n <!-- Standard Mode -->\n <div *ngIf=\"!isPreviewBoxMode()\" class=\"cide-file-input-wrapper\">\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id\"\n [attr.accept]=\"accept\"\n [attr.multiple]=\"multiple ? true : null\"\n [disabled]=\"disabled\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-element\"\n />\n <button *ngIf=\"fileNames.length\" type=\"button\" class=\"cide-file-input-clear\" (click)=\"clearFiles()\">\n Clear\n </button>\n </div>\n <div *ngIf=\"fileNames.length && !isPreviewBoxMode()\" class=\"cide-file-input-files\">\n <span *ngFor=\"let name of fileNames\">{{ name }}</span>\n </div>\n \n <!-- Image Preview Section (only for standard mode) -->\n <div *ngIf=\"isImagePreviewAvailable() && !isPreviewBoxMode()\" class=\"cide-file-input-preview\">\n <div class=\"cide-file-input-preview-label\">Preview:</div>\n <div class=\"cide-file-input-preview-container\">\n <div \n *ngFor=\"let previewUrl of previewUrls; let i = index\" \n class=\"cide-file-input-preview-item\"\n [style.width]=\"previewWidth\"\n [style.height]=\"previewHeight\">\n <button \n type=\"button\" \n class=\"cide-file-input-preview-remove\"\n (click)=\"removePreview(i)\"\n title=\"Remove image\">\n \u00D7\n </button>\n <img \n [src]=\"previewUrl\" \n [alt]=\"fileNames[i] || 'Preview image'\"\n class=\"cide-file-input-preview-image\"\n loading=\"lazy\">\n <div class=\"cide-file-input-preview-filename\">{{ fileNames[i] }}</div>\n </div>\n </div>\n </div>\n \n <div *ngIf=\"errorText\" class=\"cide-file-input-error\">{{ errorText }}</div>\n <div *ngIf=\"helperText && !errorText\" class=\"cide-file-input-helper\">{{ helperText }}</div>\n</div> ", styles: [".cide-file-input{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-label{font-weight:500;margin-bottom:.25rem}.cide-file-input-required{color:#d32f2f;font-weight:700}.cide-file-input-wrapper{display:flex;align-items:center;gap:.5rem}.cide-file-input-element{flex:1}.cide-file-input-clear{background:none;border:none;color:#d32f2f;cursor:pointer;font-size:.9rem}.cide-file-input-files{font-size:.95rem;color:#333;margin-top:.25rem}.cide-file-input-error{color:#d32f2f;font-size:.9rem}.cide-file-input-helper{color:#666;font-size:.9rem}.cide-file-input-preview{margin-top:.75rem;padding:.75rem;background-color:#f8f9fa;border:1px solid #e1e5e9;border-radius:.375rem}.cide-file-input-preview-label{font-weight:500;margin-bottom:.5rem;color:#374151;font-size:.875rem}.cide-file-input-preview-container{display:flex;flex-wrap:wrap;gap:.75rem}.cide-file-input-preview-item{position:relative;display:flex;flex-direction:column;border:1px solid #d1d5db;border-radius:.5rem;overflow:hidden;background-color:#fff;box-shadow:0 1px 3px #0000001a;transition:box-shadow .2s ease-in-out}.cide-file-input-preview-item:hover{box-shadow:0 4px 6px -1px #0000001a}.cide-file-input-preview-image{width:100%;height:calc(100% - 2rem);object-fit:cover;object-position:center;background-color:#f3f4f6}.cide-file-input-preview-filename{padding:.375rem .5rem;background-color:#f9fafbf2;border-top:1px solid #e5e7eb;font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:2rem;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-remove{position:absolute;top:.25rem;right:.25rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;transition:all .2s ease-in-out}.cide-file-input-preview-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-hidden{display:none}.cide-file-input-preview-box-container{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-preview-box{position:relative;border:2px dashed #d1d5db;border-radius:.5rem;cursor:pointer;background-color:#f9fafb;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:all .2s ease-in-out}.cide-file-input-preview-box:hover{border-color:#3b82f6;background-color:#eff6ff}.cide-file-input-preview-box.cide-file-input-preview-box-disabled{cursor:not-allowed;opacity:.6;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-disabled:hover{border-color:#d1d5db;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image{border-style:solid;border-color:#e5e7eb;padding:0}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover{border-color:#3b82f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover .cide-file-input-preview-box-overlay{opacity:1}.cide-file-input-preview-box-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1rem;text-align:center}.cide-file-input-preview-box-icon{font-size:2rem;color:#6b7280}.cide-file-input-preview-box-text{font-size:.875rem;color:#6b7280;font-weight:500}.cide-file-input-preview-box-content{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-box-image{width:100%;height:100%;object-fit:cover;object-position:center}.cide-file-input-preview-box-overlay{position:absolute;inset:0;background-color:#0009;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease-in-out}.cide-file-input-preview-box-overlay-text{color:#fff;font-size:.875rem;font-weight:500;text-align:center}.cide-file-input-preview-box-remove{position:absolute;top:.375rem;right:.375rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:20;transition:all .2s ease-in-out}.cide-file-input-preview-box-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-box-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-preview-box-filename{font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;margin-top:.25rem}@media (max-width: 640px){.cide-file-input-preview-container{justify-content:center}.cide-file-input-preview-item{min-width:120px;max-width:150px}.cide-file-input-preview-box-icon{font-size:1.5rem}.cide-file-input-preview-box-text{font-size:.75rem}}\n"] }]
|
|
3093
3236
|
}], propDecorators: { label: [{
|
|
3094
3237
|
type: Input
|
|
3095
3238
|
}], accept: [{
|
|
@@ -3098,6 +3241,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
3098
3241
|
type: Input
|
|
3099
3242
|
}], disabled: [{
|
|
3100
3243
|
type: Input
|
|
3244
|
+
}], required: [{
|
|
3245
|
+
type: Input
|
|
3101
3246
|
}], helperText: [{
|
|
3102
3247
|
type: Input
|
|
3103
3248
|
}], errorText: [{
|