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,438 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { CommonModule } from '@angular/common';
3
- import {
4
- Component,
5
- EventEmitter,
6
- Input,
7
- Output,
8
- OnDestroy,
9
- ElementRef,
10
- ViewChild,
11
- } from '@angular/core';
12
- import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
13
-
14
- interface FileValidationResult {
15
- isValid: boolean;
16
- errors: string[];
17
- }
18
-
19
- interface ErrorMessages {
20
- invalidSize: string;
21
- invalidType: string;
22
- tooManyFiles: string;
23
- uploadError: string;
24
- }
25
-
26
- type FileSizeUnit = 'AUTO' | 'bytes' | 'KB' | 'MB' | 'GB' | 'TB';
27
-
28
- export type { FileSizeUnit };
29
-
30
- export enum FileInputState {
31
- IDLE = 'idle',
32
- LOADING = 'loading',
33
- SUCCESS = 'success',
34
- ERROR = 'error',
35
- }
36
-
37
- @Component({
38
- selector: 'matecu-file-input',
39
- imports: [CommonModule],
40
- templateUrl: './matecu-file-input.html',
41
- styleUrls: ['./matecu-file-input.scss'],
42
- providers: [
43
- {
44
- provide: NG_VALUE_ACCESSOR,
45
- multi: true,
46
- useExisting: MatecuFileInput,
47
- },
48
- ],
49
- })
50
- export class MatecuFileInput implements ControlValueAccessor, OnDestroy {
51
- @ViewChild('fileInput') fileInput!: ElementRef<HTMLInputElement>;
52
-
53
- // State
54
- files: File[] = [];
55
- file?: File;
56
- isDisabled = false;
57
- fileName?: string;
58
- selectedFileSize?: number;
59
- hasInvalidSize = false;
60
- hasInvalidType = false;
61
- previewUrl?: string;
62
- previewUrls = new Map<string, string>(); // Para múltiples archivos
63
- currentState: FileInputState = FileInputState.IDLE;
64
- validationErrors: string[] = [];
65
- isDragOver = false;
66
-
67
- private onChange: ((value: any) => void) | undefined;
68
- private onTouched: (() => void) | undefined;
69
- // Inputs - Funcionalidad básica
70
- @Input() optimizeImage?: (img: File) => Promise<File>;
71
- @Input() optimizeImageToSize?: number;
72
- @Input() maxFileSize?: number; // tamaño máximo en bytes
73
- @Input() maxFiles = 1;
74
- @Input() multiple = false;
75
- @Input() showFileSize = false;
76
- @Input() fileSizeUnit: FileSizeUnit = 'AUTO';
77
- @Input() displayName?: string;
78
- @Input() placeholder = 'Select a file or drag here';
79
- @Input() buttonText = 'Select file';
80
- @Input() changeSelectedFileText = 'Change selected file(s)';
81
- @Input() loadingText = 'Processing...';
82
- @Input() ariaLabel?: string;
83
-
84
- // Inputs - Validación
85
- @Input() acceptedMimeTypes: string[] = [];
86
- @Input() acceptedExtensions: string[] = [];
87
- @Input() errorMessages: ErrorMessages = {
88
- invalidSize: 'File exceeds maximum allowed size',
89
- invalidType: 'File type not allowed',
90
- tooManyFiles: 'Maximum number of files exceeded',
91
- uploadError: 'Error processing file',
92
- };
93
-
94
- // Inputs - UI/UX
95
- @Input() enableDragDrop = true;
96
- @Input() showPreview = false;
97
- @Input() previewMaxWidth = 200;
98
- @Input() previewMaxHeight = 200;
99
- @Input() showProgress = false;
100
-
101
- // Outputs
102
- @Output() fileSelected = new EventEmitter<File>();
103
- @Output() filesSelected = new EventEmitter<File[]>();
104
- @Output() fileRemoved = new EventEmitter<File>();
105
- @Output() validationError = new EventEmitter<string[]>();
106
- @Output() dragEnter = new EventEmitter<DragEvent>();
107
- @Output() dragLeave = new EventEmitter<DragEvent>();
108
- @Output() stateChange = new EventEmitter<FileInputState>();
109
- // ControlValueAccessor Methods
110
- writeValue(value: any): void {
111
- if (value instanceof File) {
112
- this.handleSingleFile(value);
113
- } else if (Array.isArray(value)) {
114
- this.handleMultipleFiles(value);
115
- } else if (typeof value === 'string') {
116
- this.fileName = value;
117
- } else {
118
- this.resetComponent();
119
- }
120
- }
121
-
122
- registerOnChange(fn: (value: any) => void): void {
123
- this.onChange = fn;
124
- }
125
-
126
- registerOnTouched(fn: () => void): void {
127
- this.onTouched = fn;
128
- }
129
-
130
- setDisabledState(isDisabled: boolean): void {
131
- this.isDisabled = isDisabled;
132
- this.changeState(this.isDisabled ? FileInputState.IDLE : this.currentState);
133
- }
134
-
135
- ngOnDestroy(): void {
136
- this.cleanupPreview();
137
- }
138
-
139
- // Event Handlers
140
- onFileChange(event: Event): void {
141
- const input = event.target as HTMLInputElement;
142
- const selectedFiles = Array.from(input.files || []);
143
- this.handleFileSelection(selectedFiles);
144
- }
145
-
146
- onDragOver(event: DragEvent): void {
147
- if (!this.enableDragDrop || this.isDisabled) return;
148
- event.preventDefault();
149
- event.stopPropagation();
150
- if (!this.isDragOver) {
151
- this.isDragOver = true;
152
- this.dragEnter.emit(event);
153
- }
154
- }
155
-
156
- onDragLeave(event: DragEvent): void {
157
- if (!this.enableDragDrop || this.isDisabled) return;
158
- event.preventDefault();
159
- event.stopPropagation();
160
- this.isDragOver = false;
161
- this.dragLeave.emit(event);
162
- }
163
-
164
- onDrop(event: DragEvent): void {
165
- if (!this.enableDragDrop || this.isDisabled) return;
166
- event.preventDefault();
167
- event.stopPropagation();
168
-
169
- this.isDragOver = false;
170
- const files = Array.from(event.dataTransfer?.files || []);
171
- this.handleFileSelection(files);
172
- }
173
-
174
- openFileDialog(): void {
175
- if (this.isDisabled) return;
176
- this.fileInput?.nativeElement.click();
177
- }
178
-
179
- removeFile(fileToRemove: File): void {
180
- // Limpiar preview del archivo eliminado
181
- const fileKey = `${fileToRemove.name}-${fileToRemove.size}-${fileToRemove.lastModified}`;
182
- const previewUrl = this.previewUrls.get(fileKey);
183
- if (previewUrl && previewUrl.startsWith('blob:')) {
184
- URL.revokeObjectURL(previewUrl);
185
- this.previewUrls.delete(fileKey);
186
- }
187
- if (this.multiple) {
188
- this.files = this.files.filter((file) => file !== fileToRemove);
189
- this.notifyChange(this.files.length > 0 ? this.files : null);
190
- this.filesSelected.emit([...this.files]);
191
- } else {
192
- this.resetComponent();
193
- this.notifyChange(null);
194
- }
195
- this.fileRemoved.emit(fileToRemove);
196
- }
197
- // Private Methods
198
- private async handleFileSelection(selectedFiles: File[]): Promise<void> {
199
- if (selectedFiles.length === 0) return;
200
-
201
- this.changeState(FileInputState.LOADING);
202
- this.validationErrors = [];
203
-
204
- try {
205
- // Validar número máximo de archivos
206
- if (selectedFiles.length > this.maxFiles) {
207
- this.validationErrors.push(this.errorMessages.tooManyFiles);
208
- this.changeState(FileInputState.ERROR);
209
- return;
210
- }
211
-
212
- const processedFiles: File[] = [];
213
-
214
- for (const file of selectedFiles) {
215
- const validation = this.validateFile(file);
216
- if (!validation.isValid) {
217
- this.validationErrors.push(...validation.errors);
218
- continue;
219
- }
220
-
221
- try {
222
- const processedFile = await this.processFile(file);
223
- if (processedFile) {
224
- processedFiles.push(processedFile);
225
- }
226
- } catch (error) {
227
- this.validationErrors.push(this.errorMessages.uploadError);
228
- }
229
- }
230
-
231
- if (this.validationErrors.length > 0) {
232
- this.validationError.emit([...this.validationErrors]);
233
- this.changeState(FileInputState.ERROR);
234
- return;
235
- }
236
-
237
- if (processedFiles.length > 0) {
238
- if (this.multiple) {
239
- this.files = processedFiles;
240
- this.filesSelected.emit([...this.files]);
241
- this.notifyChange(this.files);
242
- } else {
243
- this.file = processedFiles[0];
244
- this.handleSingleFile(this.file);
245
- this.fileSelected.emit(this.file);
246
- this.notifyChange(this.file);
247
- }
248
-
249
- this.changeState(FileInputState.SUCCESS);
250
- }
251
- } catch (error) {
252
- this.validationErrors.push(this.errorMessages.uploadError);
253
- this.validationError.emit([...this.validationErrors]);
254
- this.changeState(FileInputState.ERROR);
255
- }
256
- }
257
-
258
- private handleSingleFile(file: File): void {
259
- this.file = file;
260
- this.fileName = this.displayName || file.name;
261
- this.selectedFileSize = this.calculateFileSizeInMB(file);
262
- this.generatePreview(file);
263
- }
264
-
265
- private handleMultipleFiles(files: File[]): void {
266
- this.files = files;
267
- this.file = files[0] || undefined;
268
- this.fileName = files.length > 0 ? `${files.length} file(s) selected` : undefined;
269
- }
270
-
271
- private async processFile(file: File): Promise<File | undefined> {
272
- if (this.optimizeImage && file.type.includes('image') && this.optimizeImageToSize) {
273
- try {
274
- return await this.optimizeImage(file);
275
- } catch (error) {
276
- console.warn('Error optimizing image:', error);
277
- return file; // Return original if optimization fails
278
- }
279
- }
280
- return file;
281
- }
282
-
283
- private validateFile(file: File): FileValidationResult {
284
- const errors: string[] = [];
285
-
286
- // Validar tamaño
287
- if (this.maxFileSize && file.size > this.maxFileSize) {
288
- errors.push(this.errorMessages.invalidSize);
289
- }
290
-
291
- // Validar tipo MIME
292
- if (this.acceptedMimeTypes.length > 0) {
293
- if (!this.acceptedMimeTypes.some((type) => file.type.includes(type))) {
294
- errors.push(this.errorMessages.invalidType);
295
- }
296
- }
297
-
298
- // Validar extensión
299
- if (this.acceptedExtensions.length > 0) {
300
- const fileExtension = '.' + file.name.split('.').pop()?.toLowerCase();
301
- if (!this.acceptedExtensions.some((ext) => ext.toLowerCase() === fileExtension)) {
302
- errors.push(this.errorMessages.invalidType);
303
- }
304
- }
305
-
306
- return {
307
- isValid: errors.length === 0,
308
- errors,
309
- };
310
- }
311
-
312
- private generatePreview(file: File): void {
313
- this.cleanupPreview();
314
-
315
- if (this.showPreview && file.type.startsWith('image/')) {
316
- const reader = new FileReader();
317
- reader.onload = (e) => {
318
- this.previewUrl = e.target?.result as string;
319
- };
320
- reader.readAsDataURL(file);
321
- }
322
- }
323
-
324
- private cleanupPreview(): void {
325
- // Limpiar preview simple
326
- if (this.previewUrl && this.previewUrl.startsWith('blob:')) {
327
- URL.revokeObjectURL(this.previewUrl);
328
- }
329
- this.previewUrl = undefined;
330
-
331
- // Limpiar previews múltiples
332
- this.previewUrls.forEach((url) => {
333
- if (url.startsWith('blob:')) {
334
- URL.revokeObjectURL(url);
335
- }
336
- });
337
- this.previewUrls.clear();
338
- }
339
-
340
- private resetComponent(): void {
341
- this.files = [];
342
- this.file = undefined;
343
- this.fileName = undefined;
344
- this.selectedFileSize = undefined;
345
- this.validationErrors = [];
346
- this.hasInvalidSize = false;
347
- this.hasInvalidType = false;
348
- this.cleanupPreview();
349
- this.changeState(FileInputState.IDLE);
350
- }
351
-
352
- private notifyChange(value: any): void {
353
- if (this.onChange) {
354
- this.onChange(value);
355
- }
356
- if (this.onTouched) {
357
- this.onTouched();
358
- }
359
- }
360
-
361
- private changeState(newState: FileInputState): void {
362
- if (this.currentState !== newState) {
363
- this.currentState = newState;
364
- this.stateChange.emit(newState);
365
- }
366
- }
367
-
368
- calculateFileSizeInMB(file: File): number {
369
- const sizeInMB = file.size / 1024 / 1024;
370
- return sizeInMB > 0.01 ? sizeInMB : 0.01;
371
- }
372
-
373
- formatFileSize(file: File): string {
374
- const bytes = file.size;
375
-
376
- if (bytes === 0) return '0 bytes';
377
-
378
- const k = 1024;
379
- const sizes = ['bytes', 'KB', 'MB', 'GB', 'TB'];
380
-
381
- // Si se especifica una unidad específica, usarla
382
- if (this.fileSizeUnit !== 'AUTO') {
383
- const targetUnitIndex = sizes.indexOf(this.fileSizeUnit);
384
- if (targetUnitIndex !== -1) {
385
- const size = bytes / Math.pow(k, targetUnitIndex);
386
- const formattedSize = targetUnitIndex === 0 ? size.toString() : size.toFixed(2);
387
- return `${formattedSize} ${this.fileSizeUnit}`;
388
- }
389
- }
390
-
391
- // Comportamiento AUTO (original)
392
- const i = Math.floor(Math.log(bytes) / Math.log(k));
393
- const size = bytes / Math.pow(k, i);
394
- const formattedSize = i === 0 ? size.toString() : size.toFixed(2);
395
-
396
- return `${formattedSize} ${sizes[i]}`;
397
- }
398
-
399
- // Public Utility Methods
400
- getFileIcon(file?: File): string {
401
- if (!file) return 'insert_drive_file';
402
-
403
- if (file.type.startsWith('image/')) return '🖼️';
404
- if (file.type.includes('pdf')) return '📄';
405
- if (file.type.startsWith('video/')) return '🎥';
406
- if (file.type.startsWith('audio/')) return '🎵';
407
- if (file.type.includes('zip') || file.type.includes('rar')) return '🗜️';
408
- if (file.type.includes('word')) return '📝';
409
- if (file.type.includes('excel') || file.type.includes('sheet')) return '📊';
410
-
411
- return '📄';
412
- }
413
-
414
- getPreviewUrl(file: File): string {
415
- if (!file.type.startsWith('image/')) return '';
416
-
417
- const fileKey = `${file.name}-${file.size}-${file.lastModified}`;
418
-
419
- if (!this.previewUrls.has(fileKey)) {
420
- const url = URL.createObjectURL(file);
421
- this.previewUrls.set(fileKey, url);
422
- }
423
-
424
- return this.previewUrls.get(fileKey) || '';
425
- }
426
-
427
- get hasErrors(): boolean {
428
- return this.validationErrors.length > 0 || this.currentState === FileInputState.ERROR;
429
- }
430
-
431
- get isLoading(): boolean {
432
- return this.currentState === FileInputState.LOADING;
433
- }
434
-
435
- get hasFiles(): boolean {
436
- return this.multiple ? this.files.length > 0 : !!this.file;
437
- }
438
- }
@@ -1,15 +0,0 @@
1
-
2
- .matecu-spinner {
3
- display: flex;
4
- align-items: center;
5
- justify-content: center;
6
-
7
-
8
- }
9
- .matecu-spinner > svg {
10
- width: 80px;;
11
- height: 80px;;
12
- }
13
- .matecu-spinner__hidden {
14
- display: none;
15
- }
@@ -1,44 +0,0 @@
1
- @if(active){
2
-
3
- <svg xmlns:svg="http://www.w3.org/2000/svg" [attr.width]="size" [attr.height]="size" xmlns="http://www.w3.org/2000/svg"
4
- xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" viewBox="0 0 128 128" xml:space="preserve">
5
- <rect x="0" y="0" width="100%" height="100%" fill="transparent" />
6
- <g>
7
- <path class="matecu-spinner__100" d="M122.5 69.25H96.47a33.1 33.1 0 0 0 0-10.5h26.05a5.25 5.25 0 0 1 0 10.5z"
8
- [attr.fill]="color" fill-opacity="1" />
9
- <path class="matecu-spinner__30"
10
- d="M112.04 97.83L89.47 84.8a33.1 33.1 0 0 0 5.25-9.1l22.57 13.03a5.25 5.25 0 0 1-5.28 9.1z"
11
- [attr.fill]="color" fill-opacity="0.3" />
12
- <path class="matecu-spinner__30"
13
- d="M88.68 117.35L75.65 94.78a33.1 33.1 0 0 0 9.1-5.25l13.02 22.57a5.25 5.25 0 1 1-9.1 5.25z"
14
- [attr.fill]="color" fill-opacity="0.3" />
15
- <path class="matecu-spinner__30" d="M58.7 122.57V96.5a33.1 33.1 0 0 0 10.5 0v26.07a5.25 5.25 0 0 1-10.5 0z"
16
- [attr.fill]="color" fill-opacity="0.3" />
17
- <path class="matecu-spinner__30"
18
- d="M30.1 112.1l13.04-22.57a33.1 33.1 0 0 0 9.1 5.25L39.2 117.35a5.25 5.25 0 1 1-9.1-5.25z"
19
- [attr.fill]="color" fill-opacity="0.3" />
20
- <path class="matecu-spinner__30"
21
- d="M10.6 88.74L33.16 75.7a33.1 33.1 0 0 0 5.25 9.1L15.88 97.83a5.25 5.25 0 1 1-5.25-9.1z"
22
- [attr.fill]="color" fill-opacity="0.3" />
23
- <path class="matecu-spinner__40" d="M5.37 58.75h26.06a33.1 33.1 0 0 0 0 10.5H5.37a5.25 5.25 0 0 1 0-10.5z"
24
- [attr.fill]="color" fill-opacity="0.4" />
25
- <path class="matecu-spinner__50"
26
- d="M15.85 30.17L38.4 43.2a33.1 33.1 0 0 0-5.24 9.1L10.6 39.25a5.25 5.25 0 1 1 5.25-9.1z" [attr.fill]="color"
27
- fill-opacity="0.5" />
28
- <path class="matecu-spinner__60"
29
- d="M39.2 10.65l13.03 22.57a33.1 33.1 0 0 0-9.1 5.25l-13-22.57a5.25 5.25 0 1 1 9.1-5.25z" [attr.fill]="color"
30
- fill-opacity="0.6" />
31
- <path class="matecu-spinner__70" d="M69.2 5.43V31.5a33.1 33.1 0 0 0-10.5 0V5.42a5.25 5.25 0 1 1 10.5 0z"
32
- [attr.fill]="color" fill-opacity="0.7" />
33
- <path class="matecu-spinner__80"
34
- d="M97.77 15.9L84.75 38.47a33.1 33.1 0 0 0-9.1-5.25l13.03-22.57a5.25 5.25 0 1 1 9.1 5.25z"
35
- [attr.fill]="color" fill-opacity="0.8" />
36
- <path class="matecu-spinner__90"
37
- d="M117.3 39.26L94.7 52.3a33.1 33.1 0 0 0-5.25-9.1l22.57-13.03a5.25 5.25 0 0 1 5.25 9.1z"
38
- [attr.fill]="color" fill-opacity="0.9" />
39
- <animateTransform attributeName="transform" type="rotate"
40
- values="0 64 64;30 64 64;60 64 64;90 64 64;120 64 64;150 64 64;180 64 64;210 64 64;240 64 64;270 64 64;300 64 64;330 64 64"
41
- calcMode="discrete" dur="600ms" repeatCount="indefinite"></animateTransform>
42
- </g>
43
- </svg>
44
- }
@@ -1,25 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
-
3
- import { MatecuSpinnerComponent } from './matecu-spinner.component';
4
-
5
- describe('MatecuSpinnerComponent', () => {
6
- let component: MatecuSpinnerComponent;
7
- let fixture: ComponentFixture<MatecuSpinnerComponent>;
8
-
9
- beforeEach(async () => {
10
- await TestBed.configureTestingModule({
11
- declarations: [ MatecuSpinnerComponent ]
12
- })
13
- .compileComponents();
14
- });
15
-
16
- beforeEach(() => {
17
- fixture = TestBed.createComponent(MatecuSpinnerComponent);
18
- component = fixture.componentInstance;
19
- fixture.detectChanges();
20
- });
21
-
22
- it('should create', () => {
23
- expect(component).toBeTruthy();
24
- });
25
- });
@@ -1,54 +0,0 @@
1
- import { CommonModule } from '@angular/common';
2
- import { ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
3
- import { Subject } from 'rxjs';
4
- import { takeUntil, tap } from 'rxjs/operators';
5
- import { MatecuSpinnerService } from '../../services/matecu-spinner.service';
6
- @Component({
7
- selector: 'matecu-spinner',
8
- templateUrl: './matecu-spinner.component.html',
9
- styleUrls: ['./matecu-spinner.component.css'],
10
- standalone: true,
11
- imports: [CommonModule],
12
- })
13
- export class MatecuSpinnerComponent implements OnInit, OnDestroy {
14
- private destroy$ = new Subject<void>();
15
- private hiddenClass = 'matecu-spinner--hidden';
16
- private activeCache = false;
17
- @HostBinding('class') className = 'matecu-spinner';
18
- @Input() color = '#2196F3';
19
- @Input() global = false;
20
- get active(): boolean {
21
- return this.activeCache;
22
- }
23
- @Input() set active(value: boolean) {
24
- if (this.global) {
25
- return;
26
- }
27
- this.activeCache = value;
28
- this.className = value
29
- ? this.className.replace(` ${this.hiddenClass}`, '')
30
- : (this.className += ` ${this.hiddenClass}`);
31
- }
32
- @Input() size = '70px';
33
-
34
- constructor(
35
- private spinnerService: MatecuSpinnerService,
36
- private cdr: ChangeDetectorRef,
37
- ) {}
38
- ngOnDestroy(): void {
39
- this.destroy$.next();
40
- this.destroy$.complete();
41
- }
42
- ngOnInit(): void {
43
- if (this.global) {
44
- this.spinnerService
45
- .watch()
46
- .pipe(
47
- tap((value) => (this.activeCache = value)),
48
- tap(() => this.cdr.detectChanges()),
49
- takeUntil(this.destroy$),
50
- )
51
- .subscribe();
52
- }
53
- }
54
- }
@@ -1,13 +0,0 @@
1
- $size: 80px;
2
- :host, .matecu-spinner {
3
- display: flex;
4
- align-items: center;
5
- justify-content: center;
6
- > svg {
7
- width: $size;
8
- height: $size;
9
- }
10
- &__hidden {
11
- display: none;
12
- }
13
- }
@@ -1 +0,0 @@
1
- <ng-content></ng-content>
@@ -1,19 +0,0 @@
1
- :host {
2
- --mtb-bar-height: 64px;
3
- --mtb-action-padding: 10px;
4
- --mtb-action-margin: 0px;
5
- }
6
- :host,
7
- .matecu-topbar-action {
8
- &,
9
- * {
10
- box-sizing: border-box;
11
- outline: none;
12
- }
13
- height: 100%;
14
- display: flex;
15
- align-items: flex-start;
16
- max-height: var(--mtb-bar-height);
17
- padding: var(--mtb-action-padding);
18
- margin: var(--mtb-action-margin);
19
- }
@@ -1,25 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
-
3
- import { MatecuTopbarActionComponent } from './matecu-topbar-action.component';
4
-
5
- describe('MatecuTopbarActionsComponent', () => {
6
- let component: MatecuTopbarActionComponent;
7
- let fixture: ComponentFixture<MatecuTopbarActionComponent>;
8
-
9
- beforeEach(async () => {
10
- await TestBed.configureTestingModule({
11
- declarations: [MatecuTopbarActionComponent]
12
- })
13
- .compileComponents();
14
- });
15
-
16
- beforeEach(() => {
17
- fixture = TestBed.createComponent(MatecuTopbarActionComponent);
18
- component = fixture.componentInstance;
19
- fixture.detectChanges();
20
- });
21
-
22
- it('should create', () => {
23
- expect(component).toBeTruthy();
24
- });
25
- });
@@ -1,14 +0,0 @@
1
- import { Component, HostBinding, OnInit } from '@angular/core';
2
-
3
- @Component({
4
- selector: 'matecu-topbar-action',
5
- templateUrl: './matecu-topbar-action.component.html',
6
- styleUrls: ['./matecu-topbar-action.component.scss'],
7
- standalone: true,
8
- })
9
- export class MatecuTopbarActionComponent implements OnInit {
10
- @HostBinding('class') className = 'matecu-topbar-action';
11
- constructor() {}
12
-
13
- ngOnInit(): void {}
14
- }
@@ -1 +0,0 @@
1
- <ng-content></ng-content>
@@ -1,14 +0,0 @@
1
- :host,
2
- .matecu-topbar-body {
3
- display: block;
4
- &,
5
- * {
6
- box-sizing: border-box;
7
- outline: none;
8
- }
9
-
10
- padding: var(--mtb-body-padding, 30px);
11
- background-color: var(--mtb-body-background, auto);
12
- overflow-y: auto;
13
- padding-bottom: var(--mtb-body-padding-button, 60px);
14
- }