angular-matecu 4.1.0 → 4.2.0
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/angular-matecu.mjs +1740 -0
- package/fesm2022/angular-matecu.mjs.map +1 -0
- package/package.json +16 -3
- package/types/angular-matecu.d.ts +490 -0
- package/ng-package.json +0 -7
- package/src/css/main.css +0 -1
- package/src/lib/components/matecu-alert-box/matecu-alert-box.component.html +0 -11
- package/src/lib/components/matecu-alert-box/matecu-alert-box.component.scss +0 -39
- package/src/lib/components/matecu-alert-box/matecu-alert-box.component.spec.ts +0 -25
- package/src/lib/components/matecu-alert-box/matecu-alert-box.component.ts +0 -60
- package/src/lib/components/matecu-alert-dialog/matecu-alert-dialog.component.html +0 -24
- package/src/lib/components/matecu-alert-dialog/matecu-alert-dialog.component.scss +0 -5
- package/src/lib/components/matecu-alert-dialog/matecu-alert-dialog.component.spec.ts +0 -25
- package/src/lib/components/matecu-alert-dialog/matecu-alert-dialog.component.ts +0 -53
- package/src/lib/components/matecu-alert-snack-bar/matecu-alert-snack-bar.component.html +0 -10
- package/src/lib/components/matecu-alert-snack-bar/matecu-alert-snack-bar.component.scss +0 -34
- package/src/lib/components/matecu-alert-snack-bar/matecu-alert-snack-bar.component.spec.ts +0 -25
- package/src/lib/components/matecu-alert-snack-bar/matecu-alert-snack-bar.component.ts +0 -45
- package/src/lib/components/matecu-autocomplete/matecu-autocomplete.html +0 -36
- package/src/lib/components/matecu-autocomplete/matecu-autocomplete.scss +0 -56
- package/src/lib/components/matecu-autocomplete/matecu-autocomplete.spec.ts +0 -23
- package/src/lib/components/matecu-autocomplete/matecu-autocomplete.ts +0 -336
- package/src/lib/components/matecu-autocomplete-multiple/matecu-autocomplete-multiple.html +0 -64
- package/src/lib/components/matecu-autocomplete-multiple/matecu-autocomplete-multiple.scss +0 -23
- package/src/lib/components/matecu-autocomplete-multiple/matecu-autocomplete-multiple.spec.ts +0 -23
- package/src/lib/components/matecu-autocomplete-multiple/matecu-autocomplete-multiple.ts +0 -314
- package/src/lib/components/matecu-file-input/matecu-file-input-customization.md +0 -284
- package/src/lib/components/matecu-file-input/matecu-file-input.example.md +0 -228
- package/src/lib/components/matecu-file-input/matecu-file-input.html +0 -128
- package/src/lib/components/matecu-file-input/matecu-file-input.scss +0 -461
- package/src/lib/components/matecu-file-input/matecu-file-input.spec.ts +0 -340
- package/src/lib/components/matecu-file-input/matecu-file-input.ts +0 -438
- package/src/lib/components/matecu-spinner/matecu-spinner.component.css +0 -15
- package/src/lib/components/matecu-spinner/matecu-spinner.component.html +0 -44
- package/src/lib/components/matecu-spinner/matecu-spinner.component.spec.ts +0 -25
- package/src/lib/components/matecu-spinner/matecu-spinner.component.ts +0 -54
- package/src/lib/components/matecu-spinner/spinner-loader.component.scss +0 -13
- package/src/lib/components/matecu-topbar-action/matecu-topbar-action.component.html +0 -1
- package/src/lib/components/matecu-topbar-action/matecu-topbar-action.component.scss +0 -19
- package/src/lib/components/matecu-topbar-action/matecu-topbar-action.component.spec.ts +0 -25
- package/src/lib/components/matecu-topbar-action/matecu-topbar-action.component.ts +0 -14
- package/src/lib/components/matecu-topbar-body/matecu-topbar-body.component.html +0 -1
- package/src/lib/components/matecu-topbar-body/matecu-topbar-body.component.scss +0 -14
- package/src/lib/components/matecu-topbar-body/matecu-topbar-body.component.spec.ts +0 -25
- package/src/lib/components/matecu-topbar-body/matecu-topbar-body.component.ts +0 -11
- package/src/lib/components/matecu-topbar-fab/matecu-topbar-fab.component.html +0 -3
- package/src/lib/components/matecu-topbar-fab/matecu-topbar-fab.component.scss +0 -19
- package/src/lib/components/matecu-topbar-fab/matecu-topbar-fab.component.spec.ts +0 -25
- package/src/lib/components/matecu-topbar-fab/matecu-topbar-fab.component.ts +0 -31
- package/src/lib/components/matecu-topbar-header-column/matecu-topbar-header-column.component.html +0 -1
- package/src/lib/components/matecu-topbar-header-column/matecu-topbar-header-column.component.scss +0 -8
- package/src/lib/components/matecu-topbar-header-column/matecu-topbar-header-column.component.spec.ts +0 -23
- package/src/lib/components/matecu-topbar-header-column/matecu-topbar-header-column.component.ts +0 -11
- package/src/lib/components/matecu-topbar-header-row/matecu-topbar-header-row.component.html +0 -9
- package/src/lib/components/matecu-topbar-header-row/matecu-topbar-header-row.component.scss +0 -34
- package/src/lib/components/matecu-topbar-header-row/matecu-topbar-header-row.component.spec.ts +0 -23
- package/src/lib/components/matecu-topbar-header-row/matecu-topbar-header-row.component.ts +0 -18
- package/src/lib/components/matecu-topbar-layout/matecu-topbar-layout.component.html +0 -7
- package/src/lib/components/matecu-topbar-layout/matecu-topbar-layout.component.scss +0 -49
- package/src/lib/components/matecu-topbar-layout/matecu-topbar-layout.component.spec.ts +0 -25
- package/src/lib/components/matecu-topbar-layout/matecu-topbar-layout.component.ts +0 -112
- package/src/lib/components/matecu-topbar-search/matecu-topbar-search.component.html +0 -20
- package/src/lib/components/matecu-topbar-search/matecu-topbar-search.component.scss +0 -90
- package/src/lib/components/matecu-topbar-search/matecu-topbar-search.component.spec.ts +0 -25
- package/src/lib/components/matecu-topbar-search/matecu-topbar-search.component.ts +0 -92
- package/src/lib/components/matecu-topbar-title/matecu-topbar-title.component.html +0 -1
- package/src/lib/components/matecu-topbar-title/matecu-topbar-title.component.scss +0 -91
- package/src/lib/components/matecu-topbar-title/matecu-topbar-title.component.spec.ts +0 -25
- package/src/lib/components/matecu-topbar-title/matecu-topbar-title.component.ts +0 -14
- package/src/lib/modules/matecu-alert-box/matecu-alert-box.module.ts +0 -16
- package/src/lib/modules/matecu-spinner/matecu-spinner.module.ts +0 -14
- package/src/lib/modules/matecu-topbar-layout/matecu-topbar-layout.module.ts +0 -45
- package/src/lib/services/matecu-snack-bar.service.spec.ts +0 -16
- package/src/lib/services/matecu-snack-bar.service.ts +0 -66
- package/src/lib/services/matecu-spinner.service.spec.ts +0 -16
- package/src/lib/services/matecu-spinner.service.ts +0 -39
- package/src/lib/types/matecu-alert-dialog.ts +0 -10
- package/src/lib/types/matecu-alert-snackbar.ts +0 -8
- package/src/lib/types/matecu-altert-box-type.ts +0 -6
- package/src/lib/types/matecu-autocomplete.ts +0 -5
- package/src/public-api.ts +0 -42
- package/src/scss/main.scss +0 -2
- package/src/scss/matecu-spinner-module/_matecu-spinner-component.scss +0 -8
- package/src/scss/matecu-topbar-layout/_variables.scss +0 -2
- package/tsconfig.lib.json +0 -17
- package/tsconfig.lib.prod.json +0 -11
- package/tsconfig.spec.json +0 -15
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
# MatecuFileInput - Ejemplos de Uso
|
|
2
|
-
|
|
3
|
-
## Uso Básico
|
|
4
|
-
|
|
5
|
-
### Archivo Simple
|
|
6
|
-
|
|
7
|
-
```html
|
|
8
|
-
<matecu-file-input
|
|
9
|
-
[(ngModel)]="selectedFile"
|
|
10
|
-
[maxFileSize]="5242880"
|
|
11
|
-
[acceptedMimeTypes]="['image/*', 'application/pdf']"
|
|
12
|
-
(fileSelected)="onFileSelected($event)"
|
|
13
|
-
>
|
|
14
|
-
</matecu-file-input>
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
### Múltiples Archivos
|
|
18
|
-
|
|
19
|
-
```html
|
|
20
|
-
<matecu-file-input
|
|
21
|
-
[(ngModel)]="selectedFiles"
|
|
22
|
-
[multiple]="true"
|
|
23
|
-
[maxFiles]="5"
|
|
24
|
-
[maxFileSize]="10485760"
|
|
25
|
-
[showPreview]="true"
|
|
26
|
-
[acceptedExtensions]="['.jpg', '.png', '.pdf', '.docx']"
|
|
27
|
-
(filesSelected)="onFilesSelected($event)"
|
|
28
|
-
>
|
|
29
|
-
</matecu-file-input>
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Configuraciones Avanzadas
|
|
33
|
-
|
|
34
|
-
### Con Drag & Drop y Preview
|
|
35
|
-
|
|
36
|
-
```html
|
|
37
|
-
<matecu-file-input
|
|
38
|
-
[(ngModel)]="imageFiles"
|
|
39
|
-
[multiple]="true"
|
|
40
|
-
[maxFiles]="10"
|
|
41
|
-
[enableDragDrop]="true"
|
|
42
|
-
[showPreview]="true"
|
|
43
|
-
[previewMaxWidth]="150"
|
|
44
|
-
[previewMaxHeight]="150"
|
|
45
|
-
[acceptedMimeTypes]="['image/jpeg', 'image/png', 'image/webp']"
|
|
46
|
-
[placeholder]="'Arrastra tus imágenes aquí o haz clic para seleccionar'"
|
|
47
|
-
[buttonText]="'Seleccionar Imágenes'"
|
|
48
|
-
(dragEnter)="onDragEnter($event)"
|
|
49
|
-
(dragLeave)="onDragLeave($event)"
|
|
50
|
-
(fileSelected)="onImageSelected($event)"
|
|
51
|
-
>
|
|
52
|
-
</matecu-file-input>
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Con Optimización de Imágenes
|
|
56
|
-
|
|
57
|
-
```html
|
|
58
|
-
<matecu-file-input
|
|
59
|
-
[(ngModel)]="optimizedImage"
|
|
60
|
-
[optimizeImage]="optimizeImageFunction"
|
|
61
|
-
[optimizeImageToSize]="800"
|
|
62
|
-
[acceptedMimeTypes]="['image/*']"
|
|
63
|
-
[showFileSize]="true"
|
|
64
|
-
[displayName]="'Imagen optimizada'"
|
|
65
|
-
>
|
|
66
|
-
</matecu-file-input>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Con Formato de Tamaño Personalizado
|
|
70
|
-
|
|
71
|
-
```html
|
|
72
|
-
<!-- Mostrar siempre en KB -->
|
|
73
|
-
<matecu-file-input [(ngModel)]="file" [showFileSize]="true" [fileSizeUnit]="'KB'">
|
|
74
|
-
</matecu-file-input>
|
|
75
|
-
|
|
76
|
-
<!-- Mostrar siempre en MB -->
|
|
77
|
-
<matecu-file-input [(ngModel)]="file" [showFileSize]="true" [fileSizeUnit]="'MB'">
|
|
78
|
-
</matecu-file-input>
|
|
79
|
-
|
|
80
|
-
<!-- Automático (predeterminado) - mejor unidad según tamaño -->
|
|
81
|
-
<matecu-file-input [(ngModel)]="file" [showFileSize]="true" [fileSizeUnit]="'AUTO'">
|
|
82
|
-
</matecu-file-input>
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Con Mensajes de Error Personalizados
|
|
86
|
-
|
|
87
|
-
```html
|
|
88
|
-
<matecu-file-input
|
|
89
|
-
[(ngModel)]="document"
|
|
90
|
-
[maxFileSize]="2097152"
|
|
91
|
-
[acceptedExtensions]="['.pdf', '.doc', '.docx']"
|
|
92
|
-
[errorMessages]="{
|
|
93
|
-
invalidSize: 'El documento no puede superar 2MB',
|
|
94
|
-
invalidType: 'Solo se permiten archivos PDF y Word',
|
|
95
|
-
uploadError: 'Error al procesar el documento'
|
|
96
|
-
}"
|
|
97
|
-
(validationError)="onValidationError($event)"
|
|
98
|
-
>
|
|
99
|
-
</matecu-file-input>
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Implementación en Componente TypeScript
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
import { Component } from '@angular/core';
|
|
106
|
-
import { MatecuFileInput, FileInputState, FileSizeUnit } from 'angular-matecu';
|
|
107
|
-
|
|
108
|
-
@Component({
|
|
109
|
-
selector: 'app-file-upload',
|
|
110
|
-
template: `
|
|
111
|
-
<matecu-file-input
|
|
112
|
-
[(ngModel)]="selectedFiles"
|
|
113
|
-
[multiple]="true"
|
|
114
|
-
[maxFiles]="3"
|
|
115
|
-
[maxFileSize]="maxSize"
|
|
116
|
-
[showPreview]="true"
|
|
117
|
-
[showFileSize]="true"
|
|
118
|
-
[enableDragDrop]="true"
|
|
119
|
-
[acceptedMimeTypes]="allowedTypes"
|
|
120
|
-
(filesSelected)="onFilesSelected($event)"
|
|
121
|
-
(validationError)="onError($event)"
|
|
122
|
-
(stateChange)="onStateChange($event)"
|
|
123
|
-
></matecu-file-input>
|
|
124
|
-
|
|
125
|
-
<div *ngIf="isProcessing">Procesando archivos...</div>
|
|
126
|
-
`,
|
|
127
|
-
})
|
|
128
|
-
export class FileUploadComponent {
|
|
129
|
-
selectedFiles: File[] = [];
|
|
130
|
-
maxSize = 5 * 1024 * 1024; // 5MB
|
|
131
|
-
allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
|
|
132
|
-
isProcessing = false;
|
|
133
|
-
sizeUnit: FileSizeUnit = 'AUTO'; // Nueva propiedad para controlar la unidad
|
|
134
|
-
|
|
135
|
-
onFilesSelected(files: File[]) {
|
|
136
|
-
console.log('Archivos seleccionados:', files);
|
|
137
|
-
// Procesar archivos...
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
onError(errors: string[]) {
|
|
141
|
-
console.error('Errores de validación:', errors);
|
|
142
|
-
// Mostrar errores al usuario...
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
onStateChange(state: FileInputState) {
|
|
146
|
-
this.isProcessing = state === FileInputState.LOADING;
|
|
147
|
-
console.log('Estado cambiado a:', state);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Función para optimizar imágenes
|
|
151
|
-
optimizeImageFunction = async (file: File): Promise<File> => {
|
|
152
|
-
return new Promise((resolve) => {
|
|
153
|
-
const canvas = document.createElement('canvas');
|
|
154
|
-
const ctx = canvas.getContext('2d')!;
|
|
155
|
-
const img = new Image();
|
|
156
|
-
|
|
157
|
-
img.onload = () => {
|
|
158
|
-
// Calcular nuevas dimensiones manteniendo aspecto
|
|
159
|
-
const maxSize = 800;
|
|
160
|
-
const ratio = Math.min(maxSize / img.width, maxSize / img.height);
|
|
161
|
-
const newWidth = img.width * ratio;
|
|
162
|
-
const newHeight = img.height * ratio;
|
|
163
|
-
|
|
164
|
-
canvas.width = newWidth;
|
|
165
|
-
canvas.height = newHeight;
|
|
166
|
-
|
|
167
|
-
// Dibujar imagen redimensionada
|
|
168
|
-
ctx.drawImage(img, 0, 0, newWidth, newHeight);
|
|
169
|
-
|
|
170
|
-
// Convertir a blob
|
|
171
|
-
canvas.toBlob(
|
|
172
|
-
(blob) => {
|
|
173
|
-
if (blob) {
|
|
174
|
-
const optimizedFile = new File([blob], file.name, {
|
|
175
|
-
type: file.type,
|
|
176
|
-
lastModified: Date.now(),
|
|
177
|
-
});
|
|
178
|
-
resolve(optimizedFile);
|
|
179
|
-
} else {
|
|
180
|
-
resolve(file);
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
file.type,
|
|
184
|
-
0.85, // Calidad de compresión
|
|
185
|
-
);
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
img.src = URL.createObjectURL(file);
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
## Propiedades Disponibles
|
|
195
|
-
|
|
196
|
-
### Inputs
|
|
197
|
-
|
|
198
|
-
- `multiple`: Permite selección múltiple
|
|
199
|
-
- `maxFiles`: Número máximo de archivos (para múltiple)
|
|
200
|
-
- `maxFileSize`: Tamaño máximo en bytes
|
|
201
|
-
- `acceptedMimeTypes`: Tipos MIME permitidos
|
|
202
|
-
- `acceptedExtensions`: Extensiones permitidas
|
|
203
|
-
- `enableDragDrop`: Habilita drag & drop
|
|
204
|
-
- `showPreview`: Muestra preview de imágenes
|
|
205
|
-
- `showFileSize`: Muestra tamaño del archivo
|
|
206
|
-
- `fileSizeUnit`: Unidad para mostrar tamaño ('AUTO' | 'bytes' | 'KB' | 'MB' | 'GB' | 'TB')
|
|
207
|
-
- `displayName`: Nombre personalizado a mostrar
|
|
208
|
-
- `placeholder`: Texto cuando no hay archivos
|
|
209
|
-
- `buttonText`: Texto del botón de selección
|
|
210
|
-
- `optimizeImage`: Función para optimizar imágenes
|
|
211
|
-
- `errorMessages`: Mensajes de error personalizados
|
|
212
|
-
|
|
213
|
-
### Outputs
|
|
214
|
-
|
|
215
|
-
- `fileSelected`: Emite cuando se selecciona un archivo
|
|
216
|
-
- `filesSelected`: Emite cuando se seleccionan múltiples archivos
|
|
217
|
-
- `fileRemoved`: Emite cuando se elimina un archivo
|
|
218
|
-
- `validationError`: Emite errores de validación
|
|
219
|
-
- `stateChange`: Emite cambios de estado
|
|
220
|
-
- `dragEnter`: Emite cuando se inicia drag
|
|
221
|
-
- `dragLeave`: Emite cuando se termina drag
|
|
222
|
-
|
|
223
|
-
### Estados
|
|
224
|
-
|
|
225
|
-
- `IDLE`: Estado inicial
|
|
226
|
-
- `LOADING`: Procesando archivos
|
|
227
|
-
- `SUCCESS`: Archivos procesados exitosamente
|
|
228
|
-
- `ERROR`: Error en validación o procesamiento
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
<!-- Hidden file input -->
|
|
2
|
-
<input type="file" #fileInput (change)="onFileChange($event)" [multiple]="multiple" [disabled]="isDisabled"
|
|
3
|
-
[attr.aria-label]="ariaLabel || 'Select file'" [attr.aria-describedby]="hasErrors ? 'file-input-errors' : null"
|
|
4
|
-
[accept]="acceptedMimeTypes.join(',')" />
|
|
5
|
-
|
|
6
|
-
<!-- Main drop zone and file display -->
|
|
7
|
-
<div class="file-input-container" [class.drag-over]="isDragOver" [class.disabled]="isDisabled"
|
|
8
|
-
[class.has-files]="hasFiles" [class.has-errors]="hasErrors" [class.loading]="isLoading"
|
|
9
|
-
(dragover)="onDragOver($event)" (dragleave)="onDragLeave($event)" (drop)="onDrop($event)"
|
|
10
|
-
(click)="openFileDialog()">
|
|
11
|
-
<!-- Loading state -->
|
|
12
|
-
@if (isLoading) {
|
|
13
|
-
<div class="loading-container">
|
|
14
|
-
<div class="spinner"></div>
|
|
15
|
-
<span class="loading-text">{{ loadingText }}</span>
|
|
16
|
-
</div>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
<!-- Empty state / Drop zone -->
|
|
20
|
-
@if (!hasFiles && !isLoading) {
|
|
21
|
-
<div class="drop-zone">
|
|
22
|
-
<div class="drop-zone-icon">
|
|
23
|
-
📁
|
|
24
|
-
</div>
|
|
25
|
-
<div class="drop-zone-content">
|
|
26
|
-
<p class="drop-zone-title">{{ placeholder }}</p>
|
|
27
|
-
<button type="button" class="select-button" [disabled]="isDisabled"
|
|
28
|
-
(click)="openFileDialog(); $event.stopPropagation()">
|
|
29
|
-
{{ buttonText }}
|
|
30
|
-
</button>
|
|
31
|
-
@if (enableDragDrop && !isDisabled) {
|
|
32
|
-
}
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
<!-- Single file display -->
|
|
38
|
-
@if (!multiple && file && !isLoading) {
|
|
39
|
-
<div class="single-file-display">
|
|
40
|
-
<div class="file-info">
|
|
41
|
-
<!-- File preview -->
|
|
42
|
-
@if (showPreview && file.type.startsWith('image/')) {
|
|
43
|
-
<div class="file-preview">
|
|
44
|
-
<img [src]="getPreviewUrl(file)" [alt]="file.name" [style.max-width.px]="previewMaxWidth"
|
|
45
|
-
[style.max-height.px]="previewMaxHeight" />
|
|
46
|
-
</div>
|
|
47
|
-
} @else {
|
|
48
|
-
<div class="file-icon">
|
|
49
|
-
{{ getFileIcon(file) }}
|
|
50
|
-
</div>
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
<div class="file-details">
|
|
54
|
-
<h3 class="file-name">{{ displayName || file.name }}</h3>
|
|
55
|
-
@if (showFileSize && selectedFileSize) {
|
|
56
|
-
<p class="file-size">
|
|
57
|
-
{{ formatFileSize(file) }}
|
|
58
|
-
</p>
|
|
59
|
-
}
|
|
60
|
-
<p class="file-type">{{ file.type || 'Unknown type' }}</p>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
<button type="button" class="remove-file-button" (click)="removeFile(file); $event.stopPropagation()"
|
|
65
|
-
[attr.aria-label]="'Remove ' + file.name">
|
|
66
|
-
✕
|
|
67
|
-
</button>
|
|
68
|
-
</div>
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
<!-- Multiple files display -->
|
|
72
|
-
@if (multiple && files.length > 0 && !isLoading) {
|
|
73
|
-
<div class="multiple-files-display">
|
|
74
|
-
<div class="files-header">
|
|
75
|
-
@if (maxFiles > 1) {
|
|
76
|
-
<span class="files-counter">{{ files.length }} / {{ maxFiles }}</span>
|
|
77
|
-
}
|
|
78
|
-
</div>
|
|
79
|
-
|
|
80
|
-
<div class="files-list">
|
|
81
|
-
@for (file of files; track file.name + file.size; let i = $index) {
|
|
82
|
-
<div class="file-item">
|
|
83
|
-
<!-- File preview -->
|
|
84
|
-
@if (showPreview && file.type.startsWith('image/')) {
|
|
85
|
-
<div class="file-preview-small">
|
|
86
|
-
<img [src]="getPreviewUrl(file)" [alt]="file.name" />
|
|
87
|
-
</div>
|
|
88
|
-
} @else {
|
|
89
|
-
<div class="file-icon-small">
|
|
90
|
-
{{ getFileIcon(file) }}
|
|
91
|
-
</div>
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
<div class="file-item-details">
|
|
95
|
-
<div class="file-item-name">{{ file.name }}</div>
|
|
96
|
-
@if (showFileSize) {
|
|
97
|
-
<div class="file-item-size">
|
|
98
|
-
{{ formatFileSize(file) }}
|
|
99
|
-
</div>
|
|
100
|
-
}
|
|
101
|
-
</div>
|
|
102
|
-
|
|
103
|
-
<button type="button" class="remove-file-button-small"
|
|
104
|
-
(click)="removeFile(file); $event.stopPropagation()" [attr.aria-label]="'Remove ' + file.name">
|
|
105
|
-
✕
|
|
106
|
-
</button>
|
|
107
|
-
</div>
|
|
108
|
-
}
|
|
109
|
-
</div>
|
|
110
|
-
|
|
111
|
-
<!-- Add more files button -->
|
|
112
|
-
@if (files.length < maxFiles) { <button type="button" class="add-more-button"
|
|
113
|
-
(click)="openFileDialog(); $event.stopPropagation()">
|
|
114
|
-
{{ changeSelectedFileText }}
|
|
115
|
-
</button>
|
|
116
|
-
}
|
|
117
|
-
</div>
|
|
118
|
-
}
|
|
119
|
-
</div>
|
|
120
|
-
|
|
121
|
-
<!-- Error messages -->
|
|
122
|
-
@if (hasErrors) {
|
|
123
|
-
<div id="file-input-errors" class="error-messages" role="alert">
|
|
124
|
-
@for (error of validationErrors; track error) {
|
|
125
|
-
<div class="error-message">{{ error }}</div>
|
|
126
|
-
}
|
|
127
|
-
</div>
|
|
128
|
-
}
|