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.
Files changed (87) hide show
  1. package/fesm2022/angular-matecu.mjs +1740 -0
  2. package/fesm2022/angular-matecu.mjs.map +1 -0
  3. package/package.json +16 -3
  4. package/types/angular-matecu.d.ts +490 -0
  5. package/ng-package.json +0 -7
  6. package/src/css/main.css +0 -1
  7. package/src/lib/components/matecu-alert-box/matecu-alert-box.component.html +0 -11
  8. package/src/lib/components/matecu-alert-box/matecu-alert-box.component.scss +0 -39
  9. package/src/lib/components/matecu-alert-box/matecu-alert-box.component.spec.ts +0 -25
  10. package/src/lib/components/matecu-alert-box/matecu-alert-box.component.ts +0 -60
  11. package/src/lib/components/matecu-alert-dialog/matecu-alert-dialog.component.html +0 -24
  12. package/src/lib/components/matecu-alert-dialog/matecu-alert-dialog.component.scss +0 -5
  13. package/src/lib/components/matecu-alert-dialog/matecu-alert-dialog.component.spec.ts +0 -25
  14. package/src/lib/components/matecu-alert-dialog/matecu-alert-dialog.component.ts +0 -53
  15. package/src/lib/components/matecu-alert-snack-bar/matecu-alert-snack-bar.component.html +0 -10
  16. package/src/lib/components/matecu-alert-snack-bar/matecu-alert-snack-bar.component.scss +0 -34
  17. package/src/lib/components/matecu-alert-snack-bar/matecu-alert-snack-bar.component.spec.ts +0 -25
  18. package/src/lib/components/matecu-alert-snack-bar/matecu-alert-snack-bar.component.ts +0 -45
  19. package/src/lib/components/matecu-autocomplete/matecu-autocomplete.html +0 -36
  20. package/src/lib/components/matecu-autocomplete/matecu-autocomplete.scss +0 -56
  21. package/src/lib/components/matecu-autocomplete/matecu-autocomplete.spec.ts +0 -23
  22. package/src/lib/components/matecu-autocomplete/matecu-autocomplete.ts +0 -336
  23. package/src/lib/components/matecu-autocomplete-multiple/matecu-autocomplete-multiple.html +0 -64
  24. package/src/lib/components/matecu-autocomplete-multiple/matecu-autocomplete-multiple.scss +0 -23
  25. package/src/lib/components/matecu-autocomplete-multiple/matecu-autocomplete-multiple.spec.ts +0 -23
  26. package/src/lib/components/matecu-autocomplete-multiple/matecu-autocomplete-multiple.ts +0 -314
  27. package/src/lib/components/matecu-file-input/matecu-file-input-customization.md +0 -284
  28. package/src/lib/components/matecu-file-input/matecu-file-input.example.md +0 -228
  29. package/src/lib/components/matecu-file-input/matecu-file-input.html +0 -128
  30. package/src/lib/components/matecu-file-input/matecu-file-input.scss +0 -461
  31. package/src/lib/components/matecu-file-input/matecu-file-input.spec.ts +0 -340
  32. package/src/lib/components/matecu-file-input/matecu-file-input.ts +0 -438
  33. package/src/lib/components/matecu-spinner/matecu-spinner.component.css +0 -15
  34. package/src/lib/components/matecu-spinner/matecu-spinner.component.html +0 -44
  35. package/src/lib/components/matecu-spinner/matecu-spinner.component.spec.ts +0 -25
  36. package/src/lib/components/matecu-spinner/matecu-spinner.component.ts +0 -54
  37. package/src/lib/components/matecu-spinner/spinner-loader.component.scss +0 -13
  38. package/src/lib/components/matecu-topbar-action/matecu-topbar-action.component.html +0 -1
  39. package/src/lib/components/matecu-topbar-action/matecu-topbar-action.component.scss +0 -19
  40. package/src/lib/components/matecu-topbar-action/matecu-topbar-action.component.spec.ts +0 -25
  41. package/src/lib/components/matecu-topbar-action/matecu-topbar-action.component.ts +0 -14
  42. package/src/lib/components/matecu-topbar-body/matecu-topbar-body.component.html +0 -1
  43. package/src/lib/components/matecu-topbar-body/matecu-topbar-body.component.scss +0 -14
  44. package/src/lib/components/matecu-topbar-body/matecu-topbar-body.component.spec.ts +0 -25
  45. package/src/lib/components/matecu-topbar-body/matecu-topbar-body.component.ts +0 -11
  46. package/src/lib/components/matecu-topbar-fab/matecu-topbar-fab.component.html +0 -3
  47. package/src/lib/components/matecu-topbar-fab/matecu-topbar-fab.component.scss +0 -19
  48. package/src/lib/components/matecu-topbar-fab/matecu-topbar-fab.component.spec.ts +0 -25
  49. package/src/lib/components/matecu-topbar-fab/matecu-topbar-fab.component.ts +0 -31
  50. package/src/lib/components/matecu-topbar-header-column/matecu-topbar-header-column.component.html +0 -1
  51. package/src/lib/components/matecu-topbar-header-column/matecu-topbar-header-column.component.scss +0 -8
  52. package/src/lib/components/matecu-topbar-header-column/matecu-topbar-header-column.component.spec.ts +0 -23
  53. package/src/lib/components/matecu-topbar-header-column/matecu-topbar-header-column.component.ts +0 -11
  54. package/src/lib/components/matecu-topbar-header-row/matecu-topbar-header-row.component.html +0 -9
  55. package/src/lib/components/matecu-topbar-header-row/matecu-topbar-header-row.component.scss +0 -34
  56. package/src/lib/components/matecu-topbar-header-row/matecu-topbar-header-row.component.spec.ts +0 -23
  57. package/src/lib/components/matecu-topbar-header-row/matecu-topbar-header-row.component.ts +0 -18
  58. package/src/lib/components/matecu-topbar-layout/matecu-topbar-layout.component.html +0 -7
  59. package/src/lib/components/matecu-topbar-layout/matecu-topbar-layout.component.scss +0 -49
  60. package/src/lib/components/matecu-topbar-layout/matecu-topbar-layout.component.spec.ts +0 -25
  61. package/src/lib/components/matecu-topbar-layout/matecu-topbar-layout.component.ts +0 -112
  62. package/src/lib/components/matecu-topbar-search/matecu-topbar-search.component.html +0 -20
  63. package/src/lib/components/matecu-topbar-search/matecu-topbar-search.component.scss +0 -90
  64. package/src/lib/components/matecu-topbar-search/matecu-topbar-search.component.spec.ts +0 -25
  65. package/src/lib/components/matecu-topbar-search/matecu-topbar-search.component.ts +0 -92
  66. package/src/lib/components/matecu-topbar-title/matecu-topbar-title.component.html +0 -1
  67. package/src/lib/components/matecu-topbar-title/matecu-topbar-title.component.scss +0 -91
  68. package/src/lib/components/matecu-topbar-title/matecu-topbar-title.component.spec.ts +0 -25
  69. package/src/lib/components/matecu-topbar-title/matecu-topbar-title.component.ts +0 -14
  70. package/src/lib/modules/matecu-alert-box/matecu-alert-box.module.ts +0 -16
  71. package/src/lib/modules/matecu-spinner/matecu-spinner.module.ts +0 -14
  72. package/src/lib/modules/matecu-topbar-layout/matecu-topbar-layout.module.ts +0 -45
  73. package/src/lib/services/matecu-snack-bar.service.spec.ts +0 -16
  74. package/src/lib/services/matecu-snack-bar.service.ts +0 -66
  75. package/src/lib/services/matecu-spinner.service.spec.ts +0 -16
  76. package/src/lib/services/matecu-spinner.service.ts +0 -39
  77. package/src/lib/types/matecu-alert-dialog.ts +0 -10
  78. package/src/lib/types/matecu-alert-snackbar.ts +0 -8
  79. package/src/lib/types/matecu-altert-box-type.ts +0 -6
  80. package/src/lib/types/matecu-autocomplete.ts +0 -5
  81. package/src/public-api.ts +0 -42
  82. package/src/scss/main.scss +0 -2
  83. package/src/scss/matecu-spinner-module/_matecu-spinner-component.scss +0 -8
  84. package/src/scss/matecu-topbar-layout/_variables.scss +0 -2
  85. package/tsconfig.lib.json +0 -17
  86. package/tsconfig.lib.prod.json +0 -11
  87. package/tsconfig.spec.json +0 -15
@@ -1,340 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { DebugElement } from '@angular/core';
3
- import { By } from '@angular/platform-browser';
4
-
5
- import { MatecuFileInput, FileInputState } from './matecu-file-input';
6
-
7
- describe('MatecuFileInput', () => {
8
- let component: MatecuFileInput;
9
- let fixture: ComponentFixture<MatecuFileInput>;
10
-
11
- beforeEach(async () => {
12
- await TestBed.configureTestingModule({
13
- imports: [MatecuFileInput],
14
- }).compileComponents();
15
-
16
- fixture = TestBed.createComponent(MatecuFileInput);
17
- component = fixture.componentInstance;
18
- fixture.detectChanges();
19
- });
20
-
21
- it('should create', () => {
22
- expect(component).toBeTruthy();
23
- });
24
-
25
- it('should initialize with default values', () => {
26
- expect(component.multiple).toBeFalse();
27
- expect(component.maxFiles).toBe(1);
28
- expect(component.enableDragDrop).toBeTrue();
29
- expect(component.showPreview).toBeFalse();
30
- expect(component.currentState).toBe(FileInputState.IDLE);
31
- expect(component.files).toEqual([]);
32
- expect(component.validationErrors).toEqual([]);
33
- });
34
-
35
- describe('File Validation', () => {
36
- it('should validate file size correctly', () => {
37
- component.maxFileSize = 1024; // 1KB
38
- const largeFile = new File(['x'.repeat(2048)], 'large.txt', { type: 'text/plain' });
39
- const smallFile = new File(['small'], 'small.txt', { type: 'text/plain' });
40
-
41
- let result = component['validateFile'](largeFile);
42
- expect(result.isValid).toBeFalse();
43
- expect(result.errors).toContain(component.errorMessages.invalidSize);
44
-
45
- result = component['validateFile'](smallFile);
46
- expect(result.isValid).toBeTrue();
47
- expect(result.errors).toEqual([]);
48
- });
49
-
50
- it('should validate MIME types correctly', () => {
51
- component.acceptedMimeTypes = ['image/jpeg', 'image/png'];
52
- const validFile = new File(['image'], 'image.jpg', { type: 'image/jpeg' });
53
- const invalidFile = new File(['text'], 'doc.txt', { type: 'text/plain' });
54
-
55
- let result = component['validateFile'](validFile);
56
- expect(result.isValid).toBeTrue();
57
-
58
- result = component['validateFile'](invalidFile);
59
- expect(result.isValid).toBeFalse();
60
- expect(result.errors).toContain(component.errorMessages.invalidType);
61
- });
62
-
63
- it('should validate file extensions correctly', () => {
64
- component.acceptedExtensions = ['.jpg', '.png'];
65
- const validFile = new File(['image'], 'image.jpg', { type: 'image/jpeg' });
66
- const invalidFile = new File(['text'], 'doc.txt', { type: 'text/plain' });
67
-
68
- let result = component['validateFile'](validFile);
69
- expect(result.isValid).toBeTrue();
70
-
71
- result = component['validateFile'](invalidFile);
72
- expect(result.isValid).toBeFalse();
73
- });
74
- });
75
-
76
- describe('Single File Mode', () => {
77
- beforeEach(() => {
78
- component.multiple = false;
79
- });
80
-
81
- it('should handle single file selection', () => {
82
- spyOn(component.fileSelected, 'emit');
83
- const file = new File(['content'], 'test.txt', { type: 'text/plain' });
84
-
85
- component['handleSingleFile'](file);
86
-
87
- expect(component.file).toBe(file);
88
- expect(component.fileName).toBe('test.txt');
89
- expect(component.selectedFileSize).toBeGreaterThan(0);
90
- });
91
-
92
- it('should use display name when provided', () => {
93
- component.displayName = 'Custom Name';
94
- const file = new File(['content'], 'test.txt', { type: 'text/plain' });
95
-
96
- component['handleSingleFile'](file);
97
-
98
- expect(component.fileName).toBe('Custom Name');
99
- });
100
-
101
- it('should remove file correctly', () => {
102
- const file = new File(['content'], 'test.txt', { type: 'text/plain' });
103
- component.file = file;
104
- spyOn(component.fileRemoved, 'emit');
105
- spyOn(component, 'resetComponent').and.callThrough();
106
- spyOn(component, 'notifyChange').and.callThrough();
107
-
108
- component.removeFile(file);
109
-
110
- expect(component.fileRemoved.emit).toHaveBeenCalledWith(file);
111
- expect(component.resetComponent).toHaveBeenCalled();
112
- expect(component.notifyChange).toHaveBeenCalledWith(null);
113
- });
114
- });
115
-
116
- describe('Multiple Files Mode', () => {
117
- beforeEach(() => {
118
- component.multiple = true;
119
- component.maxFiles = 3;
120
- });
121
-
122
- it('should handle multiple file selection', () => {
123
- const files = [
124
- new File(['content1'], 'test1.txt', { type: 'text/plain' }),
125
- new File(['content2'], 'test2.txt', { type: 'text/plain' }),
126
- ];
127
-
128
- component['handleMultipleFiles'](files);
129
-
130
- expect(component.files).toEqual(files);
131
- expect(component.file).toBe(files[0]);
132
- expect(component.fileName).toContain('2 archivo(s)');
133
- });
134
-
135
- it('should validate max files limit', async () => {
136
- const files = [
137
- new File(['1'], 'test1.txt', { type: 'text/plain' }),
138
- new File(['2'], 'test2.txt', { type: 'text/plain' }),
139
- new File(['3'], 'test3.txt', { type: 'text/plain' }),
140
- new File(['4'], 'test4.txt', { type: 'text/plain' }), // Exceeds limit
141
- ];
142
-
143
- await component['handleFileSelection'](files);
144
-
145
- expect(component.validationErrors).toContain(component.errorMessages.tooManyFiles);
146
- expect(component.currentState).toBe(FileInputState.ERROR);
147
- });
148
-
149
- it('should remove specific file from multiple selection', () => {
150
- const file1 = new File(['1'], 'test1.txt', { type: 'text/plain' });
151
- const file2 = new File(['2'], 'test2.txt', { type: 'text/plain' });
152
- component.files = [file1, file2];
153
-
154
- spyOn(component.filesSelected, 'emit');
155
- spyOn(component.fileRemoved, 'emit');
156
-
157
- component.removeFile(file1);
158
-
159
- expect(component.files).toEqual([file2]);
160
- expect(component.filesSelected.emit).toHaveBeenCalledWith([file2]);
161
- expect(component.fileRemoved.emit).toHaveBeenCalledWith(file1);
162
- });
163
- });
164
-
165
- describe('Drag and Drop', () => {
166
- let dragEvent: DragEvent;
167
-
168
- beforeEach(() => {
169
- dragEvent = new DragEvent('dragover');
170
- Object.defineProperty(dragEvent, 'dataTransfer', {
171
- value: {
172
- files: [new File(['test'], 'test.txt', { type: 'text/plain' })],
173
- },
174
- });
175
- component.enableDragDrop = true;
176
- });
177
-
178
- it('should handle drag over event', () => {
179
- spyOn(dragEvent, 'preventDefault');
180
- spyOn(component.dragEnter, 'emit');
181
-
182
- component.onDragOver(dragEvent);
183
-
184
- expect(dragEvent.preventDefault).toHaveBeenCalled();
185
- expect(component.isDragOver).toBeTrue();
186
- expect(component.dragEnter.emit).toHaveBeenCalledWith(dragEvent);
187
- });
188
-
189
- it('should handle drag leave event', () => {
190
- component.isDragOver = true;
191
- spyOn(component.dragLeave, 'emit');
192
-
193
- component.onDragLeave(dragEvent);
194
-
195
- expect(component.isDragOver).toBeFalse();
196
- expect(component.dragLeave.emit).toHaveBeenCalledWith(dragEvent);
197
- });
198
-
199
- it('should handle drop event', () => {
200
- spyOn(dragEvent, 'preventDefault');
201
- spyOn(component, 'handleFileSelection').and.returnValue(Promise.resolve());
202
-
203
- component.onDrop(dragEvent);
204
-
205
- expect(dragEvent.preventDefault).toHaveBeenCalled();
206
- expect(component.isDragOver).toBeFalse();
207
- expect(component.handleFileSelection).toHaveBeenCalled();
208
- });
209
-
210
- it('should ignore drag events when disabled', () => {
211
- component.enableDragDrop = false;
212
- spyOn(dragEvent, 'preventDefault');
213
-
214
- component.onDragOver(dragEvent);
215
-
216
- expect(dragEvent.preventDefault).not.toHaveBeenCalled();
217
- expect(component.isDragOver).toBeFalse();
218
- });
219
- });
220
-
221
- describe('File Icon and Preview', () => {
222
- it('should return correct icon for different file types', () => {
223
- const imageFile = new File([''], 'image.jpg', { type: 'image/jpeg' });
224
- const pdfFile = new File([''], 'document.pdf', { type: 'application/pdf' });
225
- const unknownFile = new File([''], 'file.xyz', { type: 'unknown/type' });
226
-
227
- expect(component.getFileIcon(imageFile)).toBe('🖼️');
228
- expect(component.getFileIcon(pdfFile)).toBe('📄');
229
- expect(component.getFileIcon(unknownFile)).toBe('📄');
230
- });
231
-
232
- it('should generate preview URL for images', () => {
233
- spyOn(URL, 'createObjectURL').and.returnValue('blob:test-url');
234
- const imageFile = new File([''], 'image.jpg', { type: 'image/jpeg' });
235
-
236
- const previewUrl = component.getPreviewUrl(imageFile);
237
-
238
- expect(URL.createObjectURL).toHaveBeenCalledWith(imageFile);
239
- expect(previewUrl).toBe('blob:test-url');
240
- });
241
-
242
- it('should cache preview URLs', () => {
243
- spyOn(URL, 'createObjectURL').and.returnValue('blob:test-url');
244
- const imageFile = new File([''], 'image.jpg', { type: 'image/jpeg' });
245
-
246
- const url1 = component.getPreviewUrl(imageFile);
247
- const url2 = component.getPreviewUrl(imageFile);
248
-
249
- expect(URL.createObjectURL).toHaveBeenCalledTimes(1);
250
- expect(url1).toBe(url2);
251
- });
252
- });
253
-
254
- describe('State Management', () => {
255
- it('should emit state changes', () => {
256
- spyOn(component.stateChange, 'emit');
257
-
258
- component['changeState'](FileInputState.LOADING);
259
-
260
- expect(component.currentState).toBe(FileInputState.LOADING);
261
- expect(component.stateChange.emit).toHaveBeenCalledWith(FileInputState.LOADING);
262
- });
263
-
264
- it('should not emit same state twice', () => {
265
- component.currentState = FileInputState.LOADING;
266
- spyOn(component.stateChange, 'emit');
267
-
268
- component['changeState'](FileInputState.LOADING);
269
-
270
- expect(component.stateChange.emit).not.toHaveBeenCalled();
271
- });
272
-
273
- it('should return correct computed properties', () => {
274
- component.validationErrors = ['error'];
275
- component.currentState = FileInputState.ERROR;
276
- component.files = [new File([''], 'test.txt')];
277
-
278
- expect(component.hasErrors).toBeTrue();
279
- expect(component.isLoading).toBeFalse();
280
- expect(component.hasFiles).toBeTrue();
281
- });
282
- });
283
-
284
- describe('ControlValueAccessor', () => {
285
- it('should write single file value', () => {
286
- const file = new File(['content'], 'test.txt', { type: 'text/plain' });
287
- spyOn(component, 'handleSingleFile').and.callThrough();
288
-
289
- component.writeValue(file);
290
-
291
- expect(component.handleSingleFile).toHaveBeenCalledWith(file);
292
- });
293
-
294
- it('should write multiple files value', () => {
295
- const files = [new File(['1'], 'test1.txt'), new File(['2'], 'test2.txt')];
296
- spyOn(component, 'handleMultipleFiles').and.callThrough();
297
-
298
- component.writeValue(files);
299
-
300
- expect(component.handleMultipleFiles).toHaveBeenCalledWith(files);
301
- });
302
-
303
- it('should register change and touched callbacks', () => {
304
- const changeFn = jasmine.createSpy();
305
- const touchedFn = jasmine.createSpy();
306
-
307
- component.registerOnChange(changeFn);
308
- component.registerOnTouched(touchedFn);
309
-
310
- expect(component['onChange']).toBe(changeFn);
311
- expect(component['onTouched']).toBe(touchedFn);
312
- });
313
- });
314
-
315
- describe('Memory Management', () => {
316
- it('should cleanup preview URLs on destroy', () => {
317
- spyOn(URL, 'revokeObjectURL');
318
- component.previewUrl = 'blob:test-url';
319
- component.previewUrls.set('key1', 'blob:url1');
320
- component.previewUrls.set('key2', 'blob:url2');
321
-
322
- component.ngOnDestroy();
323
-
324
- expect(URL.revokeObjectURL).toHaveBeenCalledTimes(3);
325
- expect(component.previewUrls.size).toBe(0);
326
- });
327
-
328
- it('should cleanup preview URL when removing file', () => {
329
- spyOn(URL, 'revokeObjectURL');
330
- const file = new File([''], 'test.jpg', { type: 'image/jpeg' });
331
- const fileKey = `${file.name}-${file.size}-${file.lastModified}`;
332
- component.previewUrls.set(fileKey, 'blob:test-url');
333
-
334
- component.removeFile(file);
335
-
336
- expect(URL.revokeObjectURL).toHaveBeenCalledWith('blob:test-url');
337
- expect(component.previewUrls.has(fileKey)).toBeFalse();
338
- });
339
- });
340
- });