@up_si_vale/sivale-componentes-angular 1.0.0 → 1.0.1

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 (88) hide show
  1. package/esm2022/lib/atoms/button/button.component.mjs +55 -0
  2. package/esm2022/lib/atoms/checkbox/checkbox.component.mjs +174 -0
  3. package/esm2022/lib/atoms/date-picker/date-picker.component.mjs +835 -0
  4. package/esm2022/lib/atoms/input/input.component.mjs +218 -0
  5. package/esm2022/lib/atoms/loader/loader.component.mjs +81 -0
  6. package/esm2022/lib/atoms/radio/radio.component.mjs +142 -0
  7. package/esm2022/lib/atoms/textarea/textarea.component.mjs +126 -0
  8. package/esm2022/lib/directives/asset-source.directive.mjs +68 -0
  9. package/esm2022/lib/directives/icon-source.directive.mjs +65 -0
  10. package/esm2022/lib/directives/no-leading-space.directive.mjs +24 -0
  11. package/esm2022/lib/directives/only-letters.directive.mjs +25 -0
  12. package/esm2022/lib/directives/only-number.directive.mjs +21 -0
  13. package/esm2022/lib/directives/rfc.directive.mjs +67 -0
  14. package/esm2022/lib/directives/tooltip.directive.mjs +199 -0
  15. package/esm2022/lib/models/snackbar.models.mjs +2 -0
  16. package/esm2022/lib/molecules/copy-input/copy-input.component.mjs +46 -0
  17. package/esm2022/lib/molecules/multiselect/multiselect.component.mjs +466 -0
  18. package/esm2022/lib/molecules/option/option.component.mjs +55 -0
  19. package/esm2022/lib/molecules/phone-input/phone-input.component.mjs +64 -0
  20. package/esm2022/lib/molecules/select/select.component.mjs +498 -0
  21. package/esm2022/lib/molecules/snackbar/snackbar.component.mjs +581 -0
  22. package/esm2022/lib/services/snackbar.service.mjs +96 -0
  23. package/esm2022/lib/tokens/asset-base-url.token.mjs +10 -0
  24. package/esm2022/public-api.mjs +33 -0
  25. package/esm2022/up_si_vale-sivale-componentes-angular.mjs +5 -0
  26. package/fesm2022/up_si_vale-sivale-componentes-angular.mjs +3844 -0
  27. package/fesm2022/up_si_vale-sivale-componentes-angular.mjs.map +1 -0
  28. package/index.d.ts +5 -0
  29. package/lib/atoms/button/button.component.d.ts +20 -0
  30. package/lib/atoms/checkbox/checkbox.component.d.ts +31 -0
  31. package/lib/atoms/date-picker/date-picker.component.d.ts +134 -0
  32. package/lib/atoms/input/input.component.d.ts +35 -0
  33. package/lib/atoms/loader/loader.component.d.ts +10 -0
  34. package/lib/atoms/radio/radio.component.d.ts +25 -0
  35. package/lib/atoms/textarea/textarea.component.d.ts +27 -0
  36. package/lib/directives/asset-source.directive.d.ts +19 -0
  37. package/lib/directives/icon-source.directive.d.ts +18 -0
  38. package/lib/directives/no-leading-space.directive.d.ts +6 -0
  39. package/lib/directives/only-letters.directive.d.ts +7 -0
  40. package/lib/directives/only-number.directive.d.ts +6 -0
  41. package/lib/directives/rfc.directive.d.ts +12 -0
  42. package/lib/directives/tooltip.directive.d.ts +27 -0
  43. package/{src/lib/models/snackbar.models.ts → lib/models/snackbar.models.d.ts} +8 -10
  44. package/lib/molecules/copy-input/copy-input.component.d.ts +14 -0
  45. package/lib/molecules/multiselect/multiselect.component.d.ts +74 -0
  46. package/lib/molecules/option/option.component.d.ts +19 -0
  47. package/lib/molecules/phone-input/phone-input.component.d.ts +12 -0
  48. package/lib/molecules/select/select.component.d.ts +88 -0
  49. package/lib/molecules/snackbar/snackbar.component.d.ts +17 -0
  50. package/lib/services/snackbar.service.d.ts +40 -0
  51. package/{src/lib/tokens/asset-base-url.token.ts → lib/tokens/asset-base-url.token.d.ts} +1 -5
  52. package/package.json +30 -24
  53. package/{src/public-api.ts → public-api.d.ts} +0 -15
  54. package/ng-package.json +0 -9
  55. package/src/lib/atoms/button/button.component.html +0 -21
  56. package/src/lib/atoms/button/button.component.scss +0 -242
  57. package/src/lib/atoms/button/button.component.ts +0 -43
  58. package/src/lib/atoms/checkbox/checkbox.component.scss +0 -131
  59. package/src/lib/atoms/checkbox/checkbox.component.ts +0 -130
  60. package/src/lib/atoms/date-picker/date-picker.component.html +0 -295
  61. package/src/lib/atoms/date-picker/date-picker.component.scss +0 -1002
  62. package/src/lib/atoms/date-picker/date-picker.component.ts +0 -942
  63. package/src/lib/atoms/input/input.component.ts +0 -239
  64. package/src/lib/atoms/loader/loader.component.scss +0 -144
  65. package/src/lib/atoms/loader/loader.component.ts +0 -44
  66. package/src/lib/atoms/radio/radio.component.scss +0 -115
  67. package/src/lib/atoms/radio/radio.component.ts +0 -103
  68. package/src/lib/atoms/textarea/textarea.component.ts +0 -155
  69. package/src/lib/directives/asset-source.directive.ts +0 -64
  70. package/src/lib/directives/icon-source.directive.ts +0 -74
  71. package/src/lib/directives/no-leading-space.directive.ts +0 -18
  72. package/src/lib/directives/only-letters.directive.ts +0 -21
  73. package/src/lib/directives/only-number.directive.ts +0 -15
  74. package/src/lib/directives/rfc.directive.ts +0 -60
  75. package/src/lib/directives/tooltip.directive.ts +0 -211
  76. package/src/lib/molecules/copy-input/copy-input.component.html +0 -29
  77. package/src/lib/molecules/copy-input/copy-input.component.scss +0 -101
  78. package/src/lib/molecules/copy-input/copy-input.component.ts +0 -41
  79. package/src/lib/molecules/multiselect/multiselect.component.scss +0 -298
  80. package/src/lib/molecules/multiselect/multiselect.component.ts +0 -487
  81. package/src/lib/molecules/option/option.component.ts +0 -45
  82. package/src/lib/molecules/phone-input/phone-input.component.scss +0 -78
  83. package/src/lib/molecules/phone-input/phone-input.component.ts +0 -43
  84. package/src/lib/molecules/select/select.component.ts +0 -482
  85. package/src/lib/molecules/snackbar/snackbar.component.scss +0 -201
  86. package/src/lib/molecules/snackbar/snackbar.component.ts +0 -321
  87. package/src/lib/services/snackbar.service.ts +0 -103
  88. package/tsconfig.json +0 -31
@@ -0,0 +1,3844 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Injectable, Input, Optional, Inject, Directive, HostListener, Self, HostBinding, EventEmitter, Output, Component, forwardRef, ChangeDetectionStrategy, ElementRef, ViewChild, RendererStyleFlags2, ContentChild, ContentChildren } from '@angular/core';
3
+ import { Subject } from 'rxjs';
4
+ import * as i1 from '@angular/forms';
5
+ import { ReactiveFormsModule, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
6
+ import * as i1$1 from '@angular/common';
7
+ import { CommonModule, DOCUMENT } from '@angular/common';
8
+
9
+ /**
10
+ * Base URL para los assets remotos del microfrontend (íconos, imágenes).
11
+ * El consumidor debe proveerlo, normalmente con el valor de `environment.mfAssetsUrl`.
12
+ */
13
+ const ASSET_BASE_URL = new InjectionToken('ASSET_BASE_URL', {
14
+ providedIn: 'root',
15
+ factory: () => ''
16
+ });
17
+
18
+ class SnackbarService {
19
+ snackbarSubject = new Subject();
20
+ snackbar$ = this.snackbarSubject.asObservable();
21
+ dismissSubject = new Subject();
22
+ dismiss$ = this.dismissSubject.asObservable();
23
+ snackbarIdCounter = 0;
24
+ constructor() {
25
+ }
26
+ /**
27
+ * Show success snackbar
28
+ */
29
+ success(message, duration = 5000, position) {
30
+ this.show({
31
+ message,
32
+ type: 'success',
33
+ duration,
34
+ position
35
+ });
36
+ }
37
+ /**
38
+ * Show error snackbar
39
+ */
40
+ error(message, duration = 5000, position) {
41
+ this.show({
42
+ message,
43
+ type: 'error',
44
+ duration,
45
+ position
46
+ });
47
+ }
48
+ /**
49
+ * Show warning snackbar
50
+ */
51
+ warning(message, duration = 5000, position) {
52
+ this.show({
53
+ message,
54
+ type: 'warning',
55
+ duration,
56
+ position
57
+ });
58
+ }
59
+ /**
60
+ * Show info snackbar
61
+ */
62
+ info(message, duration = 5000, position) {
63
+ this.show({
64
+ message,
65
+ type: 'info',
66
+ duration,
67
+ position
68
+ });
69
+ }
70
+ /**
71
+ * Show snackbar with custom configuration
72
+ */
73
+ show(config) {
74
+ const id = `snackbar-${++this.snackbarIdCounter}`;
75
+ const snackbarData = {
76
+ ...config,
77
+ id,
78
+ duration: config.duration ?? 5000,
79
+ position: config.position ?? 'top-right'
80
+ };
81
+ this.snackbarSubject.next(snackbarData);
82
+ // Auto dismiss after duration
83
+ if (snackbarData.duration && snackbarData.duration > 0) {
84
+ setTimeout(() => {
85
+ this.dismiss(id);
86
+ }, snackbarData.duration);
87
+ }
88
+ }
89
+ /**
90
+ * Dismiss specific snackbar by id
91
+ */
92
+ dismiss(id) {
93
+ this.dismissSubject.next(id);
94
+ }
95
+ /**
96
+ * Dismiss all snackbars
97
+ */
98
+ dismissAll() {
99
+ this.dismissSubject.next('all');
100
+ }
101
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SnackbarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
102
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SnackbarService, providedIn: 'root' });
103
+ }
104
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SnackbarService, decorators: [{
105
+ type: Injectable,
106
+ args: [{
107
+ providedIn: 'root'
108
+ }]
109
+ }], ctorParameters: () => [] });
110
+
111
+ class AssetSourceDirective {
112
+ el;
113
+ assetBaseUrl;
114
+ assetSource = 'mf';
115
+ assetPath;
116
+ originalSrc = null;
117
+ constructor(el, assetBaseUrl) {
118
+ this.el = el;
119
+ this.assetBaseUrl = assetBaseUrl;
120
+ }
121
+ ngOnInit() {
122
+ this.captureOriginalSrc();
123
+ }
124
+ ngAfterViewInit() {
125
+ this.updateSrc();
126
+ }
127
+ ngOnChanges() {
128
+ this.updateSrc();
129
+ }
130
+ captureOriginalSrc() {
131
+ if (this.el.nativeElement.tagName === 'IMG') {
132
+ this.originalSrc = this.el.nativeElement.getAttribute('src');
133
+ }
134
+ }
135
+ updateSrc() {
136
+ const assetPath = this.assetPath || this.originalSrc;
137
+ if (!assetPath) {
138
+ return;
139
+ }
140
+ const baseUrl = this.getBaseUrl();
141
+ const fullPath = `${baseUrl}/${assetPath}`;
142
+ if (this.el.nativeElement.tagName === 'IMG') {
143
+ this.el.nativeElement.src = fullPath;
144
+ }
145
+ }
146
+ getBaseUrl() {
147
+ switch (this.assetSource) {
148
+ case 'mf':
149
+ return this.assetBaseUrl ?? '';
150
+ case 'main':
151
+ return '/assets';
152
+ default:
153
+ return this.assetBaseUrl ?? '';
154
+ }
155
+ }
156
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AssetSourceDirective, deps: [{ token: i0.ElementRef }, { token: ASSET_BASE_URL, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
157
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: AssetSourceDirective, isStandalone: true, selector: "[assetSource]", inputs: { assetSource: "assetSource", assetPath: "assetPath" }, usesOnChanges: true, ngImport: i0 });
158
+ }
159
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AssetSourceDirective, decorators: [{
160
+ type: Directive,
161
+ args: [{
162
+ selector: '[assetSource]',
163
+ standalone: true
164
+ }]
165
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: undefined, decorators: [{
166
+ type: Optional
167
+ }, {
168
+ type: Inject,
169
+ args: [ASSET_BASE_URL]
170
+ }] }], propDecorators: { assetSource: [{
171
+ type: Input
172
+ }], assetPath: [{
173
+ type: Input
174
+ }] } });
175
+
176
+ class IconSourceDirective {
177
+ el;
178
+ assetBaseUrl;
179
+ iconName;
180
+ assetSource = 'mf';
181
+ constructor(el, assetBaseUrl) {
182
+ this.el = el;
183
+ this.assetBaseUrl = assetBaseUrl;
184
+ }
185
+ ngOnInit() {
186
+ this.addIconClass();
187
+ }
188
+ ngAfterViewInit() {
189
+ this.setIconUrl();
190
+ }
191
+ ngOnChanges() {
192
+ this.setIconUrl();
193
+ }
194
+ addIconClass() {
195
+ if (this.iconName) {
196
+ this.el.nativeElement.classList.add(`icon-${this.iconName}`);
197
+ }
198
+ }
199
+ setIconUrl() {
200
+ if (!this.iconName) {
201
+ return;
202
+ }
203
+ const baseUrl = this.getBaseUrl();
204
+ const iconUrl = `${baseUrl}/icons/${this.iconName}.svg`;
205
+ this.el.nativeElement.style.maskImage = `url('${iconUrl}')`;
206
+ this.el.nativeElement.style.webkitMaskImage = `url('${iconUrl}')`;
207
+ }
208
+ getBaseUrl() {
209
+ switch (this.assetSource) {
210
+ case 'mf':
211
+ return this.assetBaseUrl ?? '';
212
+ case 'main':
213
+ return '/assets';
214
+ default:
215
+ return this.assetBaseUrl ?? '';
216
+ }
217
+ }
218
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IconSourceDirective, deps: [{ token: i0.ElementRef }, { token: ASSET_BASE_URL, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
219
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: IconSourceDirective, isStandalone: true, selector: "i[iconName]", inputs: { iconName: "iconName", assetSource: "assetSource" }, usesOnChanges: true, ngImport: i0 });
220
+ }
221
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IconSourceDirective, decorators: [{
222
+ type: Directive,
223
+ args: [{
224
+ selector: 'i[iconName]',
225
+ standalone: true
226
+ }]
227
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: undefined, decorators: [{
228
+ type: Optional
229
+ }, {
230
+ type: Inject,
231
+ args: [ASSET_BASE_URL]
232
+ }] }], propDecorators: { iconName: [{
233
+ type: Input
234
+ }], assetSource: [{
235
+ type: Input
236
+ }] } });
237
+
238
+ class OnlyNumberDirective {
239
+ onInput(event) {
240
+ const value = event.target.value;
241
+ event.target.value = value.replace(/\D/g, '');
242
+ }
243
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OnlyNumberDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
244
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: OnlyNumberDirective, isStandalone: true, selector: "[onlyNumber]", host: { listeners: { "input": "onInput($event)" } }, ngImport: i0 });
245
+ }
246
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OnlyNumberDirective, decorators: [{
247
+ type: Directive,
248
+ args: [{
249
+ selector: '[onlyNumber]',
250
+ standalone: true
251
+ }]
252
+ }], propDecorators: { onInput: [{
253
+ type: HostListener,
254
+ args: ['input', ['$event']]
255
+ }] } });
256
+
257
+ class OnlyLettersDirective {
258
+ regex = /^[A-Za-zÁÉÍÓÚÜÑáéíóúüñ' -]*$/;
259
+ onInput(event) {
260
+ const value = event.target.value;
261
+ event.target.value = value
262
+ .split('')
263
+ .filter(char => this.regex.test(char))
264
+ .join('');
265
+ }
266
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OnlyLettersDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
267
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: OnlyLettersDirective, isStandalone: true, selector: "[onlyLetters]", host: { listeners: { "input": "onInput($event)" } }, ngImport: i0 });
268
+ }
269
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OnlyLettersDirective, decorators: [{
270
+ type: Directive,
271
+ args: [{
272
+ selector: '[onlyLetters]',
273
+ standalone: true
274
+ }]
275
+ }], propDecorators: { onInput: [{
276
+ type: HostListener,
277
+ args: ['input', ['$event']]
278
+ }] } });
279
+
280
+ class RfcDirective {
281
+ ngControl;
282
+ tipoContribuyente = null;
283
+ constructor(ngControl) {
284
+ this.ngControl = ngControl;
285
+ }
286
+ // Función para obtener el límite según el tipo de contribuyente
287
+ getMaxLength() {
288
+ if (this.tipoContribuyente === 'fisica')
289
+ return 13;
290
+ if (this.tipoContribuyente === 'moral')
291
+ return 12;
292
+ return 13; // Default por si no llega el valor
293
+ }
294
+ onInput(event) {
295
+ const input = event.target;
296
+ let value = input.value;
297
+ // Solo letras y números
298
+ value = value.replace(/[^a-zA-Z0-9]/g, '');
299
+ // Mayúsculas
300
+ value = value.toUpperCase();
301
+ // Aplicar límite dinámico
302
+ const max = this.getMaxLength();
303
+ if (value.length > max) {
304
+ value = value.substring(0, max);
305
+ }
306
+ this.ngControl?.control?.setValue(value, { emitEvent: false });
307
+ }
308
+ onPaste(event) {
309
+ const pasted = event.clipboardData?.getData('text') || '';
310
+ const max = this.getMaxLength();
311
+ // Bloquear pegado con caracteres inválidos
312
+ if (/[^a-zA-Z0-9]/.test(pasted)) {
313
+ event.preventDefault();
314
+ return;
315
+ }
316
+ // Bloquear pegado si excede el máximo
317
+ if (pasted.length > max) {
318
+ event.preventDefault();
319
+ }
320
+ }
321
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RfcDirective, deps: [{ token: i1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive });
322
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: RfcDirective, isStandalone: true, selector: "[rfcValidator]", inputs: { tipoContribuyente: "tipoContribuyente" }, host: { listeners: { "input": "onInput($event)", "paste": "onPaste($event)" } }, ngImport: i0 });
323
+ }
324
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RfcDirective, decorators: [{
325
+ type: Directive,
326
+ args: [{
327
+ selector: '[rfcValidator]',
328
+ standalone: true
329
+ }]
330
+ }], ctorParameters: () => [{ type: i1.NgControl, decorators: [{
331
+ type: Optional
332
+ }, {
333
+ type: Self
334
+ }] }], propDecorators: { tipoContribuyente: [{
335
+ type: Input
336
+ }], onInput: [{
337
+ type: HostListener,
338
+ args: ['input', ['$event']]
339
+ }], onPaste: [{
340
+ type: HostListener,
341
+ args: ['paste', ['$event']]
342
+ }] } });
343
+
344
+ class NoLeadingSpaceDirective {
345
+ onInput(event) {
346
+ const value = event.target.value;
347
+ // Elimina espacios al inicio
348
+ if (value.startsWith(' ')) {
349
+ event.target.value = value.trimStart();
350
+ }
351
+ }
352
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NoLeadingSpaceDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
353
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: NoLeadingSpaceDirective, isStandalone: true, selector: "[noLeadingSpace]", host: { listeners: { "input": "onInput($event)" } }, ngImport: i0 });
354
+ }
355
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NoLeadingSpaceDirective, decorators: [{
356
+ type: Directive,
357
+ args: [{
358
+ selector: '[noLeadingSpace]',
359
+ standalone: true
360
+ }]
361
+ }], propDecorators: { onInput: [{
362
+ type: HostListener,
363
+ args: ['input', ['$event']]
364
+ }] } });
365
+
366
+ class TooltipDirective {
367
+ el;
368
+ renderer;
369
+ tooltipText = '';
370
+ tooltipPosition = 'auto';
371
+ tooltipDelay = 300;
372
+ tooltipMaxWidth = 280;
373
+ tooltipClass = '';
374
+ cursor = 'help';
375
+ tooltipElement = null;
376
+ showTimeout;
377
+ hideTimeout;
378
+ constructor(el, renderer) {
379
+ this.el = el;
380
+ this.renderer = renderer;
381
+ }
382
+ onMouseEnter() {
383
+ if (this.hideTimeout) {
384
+ clearTimeout(this.hideTimeout);
385
+ this.hideTimeout = undefined;
386
+ }
387
+ this.showTimeout = window.setTimeout(() => {
388
+ this.showTooltip();
389
+ }, this.tooltipDelay);
390
+ }
391
+ onMouseLeave() {
392
+ if (this.showTimeout) {
393
+ clearTimeout(this.showTimeout);
394
+ this.showTimeout = undefined;
395
+ }
396
+ this.hideTimeout = window.setTimeout(() => {
397
+ this.hideTooltip();
398
+ }, 100);
399
+ }
400
+ onClick() {
401
+ // Allow click events to propagate
402
+ }
403
+ showTooltip() {
404
+ if (!this.tooltipText || this.tooltipElement) {
405
+ return;
406
+ }
407
+ // Create tooltip element
408
+ this.tooltipElement = this.renderer.createElement('div');
409
+ this.renderer.addClass(this.tooltipElement, 'app-tooltip');
410
+ if (this.tooltipClass) {
411
+ this.renderer.addClass(this.tooltipElement, this.tooltipClass);
412
+ }
413
+ // Create tooltip content
414
+ const tooltipContent = this.renderer.createElement('div');
415
+ this.renderer.addClass(tooltipContent, 'app-tooltip-content');
416
+ this.renderer.setStyle(tooltipContent, 'max-width', `${this.tooltipMaxWidth}px`);
417
+ const textNode = this.renderer.createText(this.tooltipText);
418
+ this.renderer.appendChild(tooltipContent, textNode);
419
+ this.renderer.appendChild(this.tooltipElement, tooltipContent);
420
+ // Create arrow element
421
+ const arrow = this.renderer.createElement('div');
422
+ this.renderer.addClass(arrow, 'app-tooltip-arrow');
423
+ this.renderer.appendChild(this.tooltipElement, arrow);
424
+ // Add to body
425
+ this.renderer.appendChild(document.body, this.tooltipElement);
426
+ // Position tooltip
427
+ this.positionTooltip();
428
+ // Trigger animation
429
+ requestAnimationFrame(() => {
430
+ if (this.tooltipElement) {
431
+ this.renderer.addClass(this.tooltipElement, 'app-tooltip-show');
432
+ }
433
+ });
434
+ }
435
+ hideTooltip() {
436
+ if (!this.tooltipElement) {
437
+ return;
438
+ }
439
+ this.renderer.removeClass(this.tooltipElement, 'app-tooltip-show');
440
+ setTimeout(() => {
441
+ if (this.tooltipElement) {
442
+ this.renderer.removeChild(document.body, this.tooltipElement);
443
+ this.tooltipElement = null;
444
+ }
445
+ }, 200);
446
+ }
447
+ positionTooltip() {
448
+ if (!this.tooltipElement) {
449
+ return;
450
+ }
451
+ const hostRect = this.el.nativeElement.getBoundingClientRect();
452
+ const tooltipRect = this.tooltipElement.getBoundingClientRect();
453
+ const scrollX = window.scrollX || window.pageXOffset;
454
+ const scrollY = window.scrollY || window.pageYOffset;
455
+ const gap = 16; // Space between element and tooltip
456
+ // Calculate available space in each direction
457
+ const spaceTop = hostRect.top;
458
+ const spaceBottom = window.innerHeight - hostRect.bottom;
459
+ const spaceLeft = hostRect.left;
460
+ const spaceRight = window.innerWidth - hostRect.right;
461
+ let position = this.tooltipPosition;
462
+ let top = 0;
463
+ let left = 0;
464
+ // Auto-detect best position
465
+ if (position === 'auto') {
466
+ if (spaceTop >= tooltipRect.height + gap) {
467
+ position = 'top';
468
+ }
469
+ else if (spaceBottom >= tooltipRect.height + gap) {
470
+ position = 'bottom';
471
+ }
472
+ else if (spaceRight >= tooltipRect.width + gap) {
473
+ position = 'right';
474
+ }
475
+ else if (spaceLeft >= tooltipRect.width + gap) {
476
+ position = 'left';
477
+ }
478
+ else {
479
+ // Default to top if no space is sufficient
480
+ position = 'top';
481
+ }
482
+ }
483
+ // Calculate position based on detected/specified position
484
+ switch (position) {
485
+ case 'top':
486
+ top = hostRect.top + scrollY - tooltipRect.height - gap;
487
+ left = hostRect.left + scrollX + (hostRect.width / 2) - (tooltipRect.width / 2);
488
+ break;
489
+ case 'bottom':
490
+ top = hostRect.bottom + scrollY + gap;
491
+ left = hostRect.left + scrollX + (hostRect.width / 2) - (tooltipRect.width / 2);
492
+ break;
493
+ case 'left':
494
+ top = hostRect.top + scrollY + (hostRect.height / 2) - (tooltipRect.height / 2);
495
+ left = hostRect.left + scrollX - tooltipRect.width - gap;
496
+ break;
497
+ case 'right':
498
+ top = hostRect.top + scrollY + (hostRect.height / 2) - (tooltipRect.height / 2);
499
+ left = hostRect.right + scrollX + gap;
500
+ break;
501
+ }
502
+ // Adjust horizontal position to keep tooltip within viewport
503
+ if (position === 'top' || position === 'bottom') {
504
+ const minLeft = scrollX + 10;
505
+ const maxLeft = scrollX + window.innerWidth - tooltipRect.width - 10;
506
+ left = Math.max(minLeft, Math.min(left, maxLeft));
507
+ }
508
+ // Adjust vertical position to keep tooltip within viewport
509
+ if (position === 'left' || position === 'right') {
510
+ const minTop = scrollY + 10;
511
+ const maxTop = scrollY + window.innerHeight - tooltipRect.height - 10;
512
+ top = Math.max(minTop, Math.min(top, maxTop));
513
+ }
514
+ // Apply position
515
+ this.renderer.setStyle(this.tooltipElement, 'top', `${top}px`);
516
+ this.renderer.setStyle(this.tooltipElement, 'left', `${left}px`);
517
+ // Add position class for arrow styling
518
+ this.renderer.addClass(this.tooltipElement, `app-tooltip-${position}`);
519
+ }
520
+ ngOnDestroy() {
521
+ if (this.showTimeout) {
522
+ clearTimeout(this.showTimeout);
523
+ }
524
+ if (this.hideTimeout) {
525
+ clearTimeout(this.hideTimeout);
526
+ }
527
+ this.hideTooltip();
528
+ }
529
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
530
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: TooltipDirective, isStandalone: true, selector: "[appTooltip]", inputs: { tooltipText: ["appTooltip", "tooltipText"], tooltipPosition: "tooltipPosition", tooltipDelay: "tooltipDelay", tooltipMaxWidth: "tooltipMaxWidth", tooltipClass: "tooltipClass" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "click": "onClick()" }, properties: { "style.cursor": "this.cursor" } }, ngImport: i0 });
531
+ }
532
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TooltipDirective, decorators: [{
533
+ type: Directive,
534
+ args: [{
535
+ selector: '[appTooltip]',
536
+ standalone: true
537
+ }]
538
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { tooltipText: [{
539
+ type: Input,
540
+ args: ['appTooltip']
541
+ }], tooltipPosition: [{
542
+ type: Input
543
+ }], tooltipDelay: [{
544
+ type: Input
545
+ }], tooltipMaxWidth: [{
546
+ type: Input
547
+ }], tooltipClass: [{
548
+ type: Input
549
+ }], cursor: [{
550
+ type: HostBinding,
551
+ args: ['style.cursor']
552
+ }], onMouseEnter: [{
553
+ type: HostListener,
554
+ args: ['mouseenter']
555
+ }], onMouseLeave: [{
556
+ type: HostListener,
557
+ args: ['mouseleave']
558
+ }], onClick: [{
559
+ type: HostListener,
560
+ args: ['click']
561
+ }] } });
562
+
563
+ class ButtonComponent {
564
+ variant = 'primary';
565
+ size = 'medium';
566
+ type = 'button';
567
+ disabled = false;
568
+ loading = false;
569
+ fullWidth = false;
570
+ id;
571
+ ariaLabel;
572
+ onClick = new EventEmitter();
573
+ get buttonClasses() {
574
+ return [
575
+ 'svu-btn',
576
+ `svu-btn--${this.variant}`,
577
+ `svu-btn--${this.size}`,
578
+ this.fullWidth ? 'svu-btn--full-width' : '',
579
+ this.loading ? 'svu-btn--loading' : '',
580
+ this.disabled ? 'svu-btn--disabled' : ''
581
+ ].filter(Boolean).join(' ');
582
+ }
583
+ handleClick(event) {
584
+ if (!this.disabled && !this.loading) {
585
+ this.onClick.emit(event);
586
+ }
587
+ }
588
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
589
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ButtonComponent, isStandalone: true, selector: "app-button", inputs: { variant: "variant", size: "size", type: "type", disabled: "disabled", loading: "loading", fullWidth: "fullWidth", id: "id", ariaLabel: "ariaLabel" }, outputs: { onClick: "onClick" }, ngImport: i0, template: "<button\n [type]=\"type\"\n [class]=\"buttonClasses\"\n [disabled]=\"disabled || loading\"\n [id]=\"id\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-busy]=\"loading\"\n (click)=\"handleClick($event)\">\n\n <!-- Loading spinner -->\n <span *ngIf=\"loading\" class=\"svu-btn__spinner\">\n <svg class=\"svu-spinner\" viewBox=\"0 0 24 24\">\n <circle class=\"svu-spinner__circle\" cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke-width=\"3\"></circle>\n </svg>\n </span>\n\n <!-- Content -->\n <span [class.svu-btn__content--hidden]=\"loading\" class=\"svu-btn__content\">\n <ng-content></ng-content>\n </span>\n</button>", styles: [".svu-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:.5rem;font-family:Quicksand,sans-serif;font-weight:600;border:none;border-radius:8px;cursor:pointer;transition:all .2s ease-in-out;outline:none!important;text-decoration:none;white-space:nowrap;width:100%}.svu-btn:focus-visible{outline:2px solid transparent;outline-offset:2px}.svu-btn--small{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;height:inherit}.svu-btn--medium{padding:.75rem 1.5rem;font-size:1rem;line-height:1.5rem}.svu-btn--large{padding:1rem 2rem;font-size:1.125rem;line-height:1.75rem}.svu-btn--full-width{width:100%}.svu-btn--primary{background:#364b9f;color:#fff}.svu-btn--primary:hover:not(:disabled):not(.btn--loading){background:#2a3b7f;transform:translateY(-1px);box-shadow:0 4px 12px #364b9f4d}.svu-btn--primary:active:not(:disabled):not(.btn--loading){transform:translateY(0);background:#1f2d5f}.svu-btn--primary:focus-visible{box-shadow:0 0 0 3px #364b9f4d}.svu-btn--secondary{background:#f3f4f6;color:#374151}.svu-btn--secondary:hover:not(:disabled):not(.btn--loading){background:#e5e7eb;transform:translateY(-1px);box-shadow:0 4px 12px #0000001a}.svu-btn--secondary:active:not(:disabled):not(.btn--loading){transform:translateY(0)}.svu-btn--secondary:focus-visible{box-shadow:0 0 0 3px #37415133}.svu-btn--outline{background:transparent;color:#364b9f;border:1px solid #364B9F}.svu-btn--outline:hover:not(:disabled):not(.btn--loading){background:#364b9f0d;border-color:#2a3b7f;color:#2a3b7f;transform:translateY(-1px)}.svu-btn--outline:active:not(:disabled):not(.btn--loading){transform:translateY(0);background:#364b9f1a}.svu-btn--outline:focus-visible{box-shadow:0 0 0 3px #364b9f33}.svu-btn--ghost{background:transparent;color:#364b9f}.svu-btn--ghost:hover:not(:disabled):not(.btn--loading){background:#364b9f1a;transform:translateY(-1px)}.svu-btn--ghost:active:not(:disabled):not(.btn--loading){transform:translateY(0);background:#364b9f26}.svu-btn--ghost:focus-visible{box-shadow:0 0 0 3px #364b9f33}.svu-btn--danger{background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff}.svu-btn--danger:hover:not(:disabled):not(.btn--loading){background:linear-gradient(135deg,#dc2626,#b91c1c);transform:translateY(-1px);box-shadow:0 4px 12px #ef44444d}.svu-btn--danger:active:not(:disabled):not(.btn--loading){transform:translateY(0)}.svu-btn--danger:focus-visible{box-shadow:0 0 0 3px #ef44444d}.svu-btn--success{background:linear-gradient(135deg,#10b981,#059669);color:#fff}.svu-btn--success:hover:not(:disabled):not(.btn--loading){background:linear-gradient(135deg,#059669,#047857);transform:translateY(-1px);box-shadow:0 4px 12px #10b9814d}.svu-btn--success:active:not(:disabled):not(.btn--loading){transform:translateY(0)}.svu-btn--success:focus-visible{box-shadow:0 0 0 3px #10b9814d}.svu-btn:disabled,.svu-btn--disabled{opacity:.5;cursor:not-allowed;transform:none!important;box-shadow:none!important}.svu-btn--loading{cursor:wait;pointer-events:none}.svu-btn__spinner{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:flex;align-items:center;justify-content:center}.svu-btn__content{display:flex;align-items:center;gap:.5rem}.svu-btn__content--hidden{visibility:hidden}.svu-spinner{width:1.25rem;height:1.25rem;animation:svu-spin .8s linear infinite}.svu-spinner__circle{stroke:currentColor;stroke-dasharray:50;stroke-dashoffset:25;stroke-linecap:round;animation:svu-spinner-dash 1.5s ease-in-out infinite}@keyframes svu-spin{to{transform:rotate(360deg)}}@keyframes svu-spinner-dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:90,150;stroke-dashoffset:-124}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
590
+ }
591
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ButtonComponent, decorators: [{
592
+ type: Component,
593
+ args: [{ selector: 'app-button', standalone: true, imports: [CommonModule], template: "<button\n [type]=\"type\"\n [class]=\"buttonClasses\"\n [disabled]=\"disabled || loading\"\n [id]=\"id\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-busy]=\"loading\"\n (click)=\"handleClick($event)\">\n\n <!-- Loading spinner -->\n <span *ngIf=\"loading\" class=\"svu-btn__spinner\">\n <svg class=\"svu-spinner\" viewBox=\"0 0 24 24\">\n <circle class=\"svu-spinner__circle\" cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke-width=\"3\"></circle>\n </svg>\n </span>\n\n <!-- Content -->\n <span [class.svu-btn__content--hidden]=\"loading\" class=\"svu-btn__content\">\n <ng-content></ng-content>\n </span>\n</button>", styles: [".svu-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:.5rem;font-family:Quicksand,sans-serif;font-weight:600;border:none;border-radius:8px;cursor:pointer;transition:all .2s ease-in-out;outline:none!important;text-decoration:none;white-space:nowrap;width:100%}.svu-btn:focus-visible{outline:2px solid transparent;outline-offset:2px}.svu-btn--small{padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;height:inherit}.svu-btn--medium{padding:.75rem 1.5rem;font-size:1rem;line-height:1.5rem}.svu-btn--large{padding:1rem 2rem;font-size:1.125rem;line-height:1.75rem}.svu-btn--full-width{width:100%}.svu-btn--primary{background:#364b9f;color:#fff}.svu-btn--primary:hover:not(:disabled):not(.btn--loading){background:#2a3b7f;transform:translateY(-1px);box-shadow:0 4px 12px #364b9f4d}.svu-btn--primary:active:not(:disabled):not(.btn--loading){transform:translateY(0);background:#1f2d5f}.svu-btn--primary:focus-visible{box-shadow:0 0 0 3px #364b9f4d}.svu-btn--secondary{background:#f3f4f6;color:#374151}.svu-btn--secondary:hover:not(:disabled):not(.btn--loading){background:#e5e7eb;transform:translateY(-1px);box-shadow:0 4px 12px #0000001a}.svu-btn--secondary:active:not(:disabled):not(.btn--loading){transform:translateY(0)}.svu-btn--secondary:focus-visible{box-shadow:0 0 0 3px #37415133}.svu-btn--outline{background:transparent;color:#364b9f;border:1px solid #364B9F}.svu-btn--outline:hover:not(:disabled):not(.btn--loading){background:#364b9f0d;border-color:#2a3b7f;color:#2a3b7f;transform:translateY(-1px)}.svu-btn--outline:active:not(:disabled):not(.btn--loading){transform:translateY(0);background:#364b9f1a}.svu-btn--outline:focus-visible{box-shadow:0 0 0 3px #364b9f33}.svu-btn--ghost{background:transparent;color:#364b9f}.svu-btn--ghost:hover:not(:disabled):not(.btn--loading){background:#364b9f1a;transform:translateY(-1px)}.svu-btn--ghost:active:not(:disabled):not(.btn--loading){transform:translateY(0);background:#364b9f26}.svu-btn--ghost:focus-visible{box-shadow:0 0 0 3px #364b9f33}.svu-btn--danger{background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff}.svu-btn--danger:hover:not(:disabled):not(.btn--loading){background:linear-gradient(135deg,#dc2626,#b91c1c);transform:translateY(-1px);box-shadow:0 4px 12px #ef44444d}.svu-btn--danger:active:not(:disabled):not(.btn--loading){transform:translateY(0)}.svu-btn--danger:focus-visible{box-shadow:0 0 0 3px #ef44444d}.svu-btn--success{background:linear-gradient(135deg,#10b981,#059669);color:#fff}.svu-btn--success:hover:not(:disabled):not(.btn--loading){background:linear-gradient(135deg,#059669,#047857);transform:translateY(-1px);box-shadow:0 4px 12px #10b9814d}.svu-btn--success:active:not(:disabled):not(.btn--loading){transform:translateY(0)}.svu-btn--success:focus-visible{box-shadow:0 0 0 3px #10b9814d}.svu-btn:disabled,.svu-btn--disabled{opacity:.5;cursor:not-allowed;transform:none!important;box-shadow:none!important}.svu-btn--loading{cursor:wait;pointer-events:none}.svu-btn__spinner{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:flex;align-items:center;justify-content:center}.svu-btn__content{display:flex;align-items:center;gap:.5rem}.svu-btn__content--hidden{visibility:hidden}.svu-spinner{width:1.25rem;height:1.25rem;animation:svu-spin .8s linear infinite}.svu-spinner__circle{stroke:currentColor;stroke-dasharray:50;stroke-dashoffset:25;stroke-linecap:round;animation:svu-spinner-dash 1.5s ease-in-out infinite}@keyframes svu-spin{to{transform:rotate(360deg)}}@keyframes svu-spinner-dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:90,150;stroke-dashoffset:-124}}\n"] }]
594
+ }], propDecorators: { variant: [{
595
+ type: Input
596
+ }], size: [{
597
+ type: Input
598
+ }], type: [{
599
+ type: Input
600
+ }], disabled: [{
601
+ type: Input
602
+ }], loading: [{
603
+ type: Input
604
+ }], fullWidth: [{
605
+ type: Input
606
+ }], id: [{
607
+ type: Input
608
+ }], ariaLabel: [{
609
+ type: Input
610
+ }], onClick: [{
611
+ type: Output
612
+ }] } });
613
+
614
+ class InputComponent {
615
+ cdr;
616
+ label = '';
617
+ id = '';
618
+ placeholder = '';
619
+ type = 'text';
620
+ maxLength;
621
+ hasError = false;
622
+ errorMessage = '';
623
+ disabled = false;
624
+ readonly = false;
625
+ format = 'alphanumeric';
626
+ unstyled = false; // Para usar dentro de componentes compuestos
627
+ value = '';
628
+ formattedValue = '';
629
+ onChange = () => { };
630
+ onTouched = () => { };
631
+ constructor(cdr) {
632
+ this.cdr = cdr;
633
+ }
634
+ writeValue(value) {
635
+ let processedValue = value || '';
636
+ // For currency format, enforce maxLength on the raw value (without commas)
637
+ if (this.format === 'currency' && this.maxLength) {
638
+ const rawValue = String(processedValue).replace(/[^0-9.]/g, '');
639
+ if (rawValue.length > this.maxLength) {
640
+ processedValue = rawValue.slice(0, this.maxLength);
641
+ }
642
+ }
643
+ // For number inputs, enforce maxLength on initial value
644
+ if (this.type === 'number' && this.maxLength && String(processedValue).length > this.maxLength) {
645
+ processedValue = String(processedValue).slice(0, this.maxLength);
646
+ }
647
+ this.value = processedValue;
648
+ this.formattedValue = this.applyFormat(this.value);
649
+ this.cdr.markForCheck();
650
+ }
651
+ registerOnChange(fn) {
652
+ this.onChange = fn;
653
+ }
654
+ registerOnTouched(fn) {
655
+ this.onTouched = fn;
656
+ }
657
+ setDisabledState(isDisabled) {
658
+ this.disabled = isDisabled;
659
+ this.cdr.markForCheck();
660
+ }
661
+ onInputChange(event) {
662
+ const target = event.target;
663
+ let inputValue = target.value;
664
+ // Parse the value first (removes formatting like commas)
665
+ let rawValue = this.parseValue(inputValue);
666
+ // For currency format, enforce maxLength on the raw value (without commas)
667
+ if (this.format === 'currency' && this.maxLength && String(rawValue).length > this.maxLength) {
668
+ rawValue = String(rawValue).slice(0, this.maxLength);
669
+ }
670
+ // For number inputs or numeric format, maxLength doesn't work natively, so we handle it manually
671
+ if ((this.type === 'number' || this.format === 'numeric') && this.maxLength) {
672
+ // Check the length of the raw value (without formatting)
673
+ const rawString = String(rawValue);
674
+ if (rawString.length > this.maxLength) {
675
+ rawValue = rawString.slice(0, this.maxLength);
676
+ // Update the input value to reflect the truncation
677
+ target.value = rawValue;
678
+ }
679
+ }
680
+ this.value = rawValue;
681
+ this.formattedValue = this.applyFormat(rawValue);
682
+ // Update the input display (for formatted inputs like currency)
683
+ if (this.format === 'currency') {
684
+ target.value = this.formattedValue;
685
+ }
686
+ this.onChange(rawValue);
687
+ }
688
+ onBlur() {
689
+ this.onTouched();
690
+ }
691
+ parseValue(value) {
692
+ switch (this.format) {
693
+ case 'currency':
694
+ // Remove all non-numeric characters except decimal point
695
+ return value.replace(/[^0-9.]/g, '');
696
+ case 'numeric':
697
+ // Remove all non-numeric characters (only digits allowed)
698
+ return value.replace(/[^0-9]/g, '');
699
+ case 'alphanumeric':
700
+ default:
701
+ return value;
702
+ }
703
+ }
704
+ applyFormat(value) {
705
+ if (!value && value !== 0)
706
+ return '';
707
+ switch (this.format) {
708
+ case 'currency':
709
+ return this.formatCurrency(value);
710
+ case 'alphanumeric':
711
+ default:
712
+ return String(value);
713
+ }
714
+ }
715
+ formatCurrency(value) {
716
+ const numValue = typeof value === 'string' ? parseFloat(value.replace(/[^0-9.]/g, '')) : value;
717
+ if (isNaN(numValue))
718
+ return '';
719
+ // Format with thousands separator
720
+ return numValue.toLocaleString('es-MX', {
721
+ minimumFractionDigits: 0,
722
+ maximumFractionDigits: 2
723
+ });
724
+ }
725
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
726
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: InputComponent, isStandalone: true, selector: "app-input", inputs: { label: "label", id: "id", placeholder: "placeholder", type: "type", maxLength: "maxLength", hasError: "hasError", errorMessage: "errorMessage", disabled: "disabled", readonly: "readonly", format: "format", unstyled: "unstyled" }, providers: [
727
+ {
728
+ provide: NG_VALUE_ACCESSOR,
729
+ useExisting: forwardRef(() => InputComponent),
730
+ multi: true
731
+ }
732
+ ], ngImport: i0, template: `
733
+ <div class="input-wrapper" [class.input-wrapper--unstyled]="unstyled">
734
+ <label *ngIf="label && !unstyled" [for]="id">{{ label }}</label>
735
+ <div class="input-container" [class.error]="hasError && !unstyled" [class.input-container--unstyled]="unstyled">
736
+ <div class="input-prefix-wrapper">
737
+ <ng-content select="[prefix]"></ng-content>
738
+ </div>
739
+ <input
740
+ noLeadingSpace
741
+ [type]="type"
742
+ [id]="id"
743
+ [placeholder]="placeholder"
744
+ [attr.maxlength]="format === 'currency' ? null : maxLength"
745
+ [disabled]="disabled"
746
+ [readonly]="readonly"
747
+ class="input-field"
748
+ [class.error]="hasError && !unstyled"
749
+ [class.input-field--unstyled]="unstyled"
750
+ [value]="formattedValue"
751
+ (blur)="onBlur()"
752
+ (input)="onInputChange($event)">
753
+ <div class="input-suffix-wrapper">
754
+ <ng-content select="[suffix]"></ng-content>
755
+ </div>
756
+ </div>
757
+ <div *ngIf="hasError && errorMessage && !unstyled" class="field-error">
758
+ {{ errorMessage }}
759
+ </div>
760
+ </div>
761
+ `, isInline: true, styles: ["input:-webkit-autofill,input:-webkit-autofill:hover,input:-webkit-autofill:focus,input:-webkit-autofill:active{-webkit-box-shadow:0 0 0 30px white inset!important;box-shadow:0 0 0 30px #fff inset!important;-webkit-text-fill-color:#2E353A!important;transition:background-color 5000s ease-in-out 0s}.input-prefix-wrapper,.input-suffix-wrapper{flex-shrink:0;display:flex;align-items:center;gap:.5rem;font-family:Quicksand,sans-serif;font-size:14px;font-weight:500;color:#969a9c;position:relative;z-index:2;pointer-events:auto!important}.input-prefix-wrapper{margin-right:.5rem;&:empty{display:none;margin-right:0}}.input-suffix-wrapper{margin-left:.5rem;&:empty{display:none;margin-left:0}}.input-prefix-wrapper *,.input-suffix-wrapper *{pointer-events:auto!important}.input-field{position:relative;z-index:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: NoLeadingSpaceDirective, selector: "[noLeadingSpace]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
762
+ }
763
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InputComponent, decorators: [{
764
+ type: Component,
765
+ args: [{ selector: 'app-input', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule, IconSourceDirective, NoLeadingSpaceDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: `
766
+ <div class="input-wrapper" [class.input-wrapper--unstyled]="unstyled">
767
+ <label *ngIf="label && !unstyled" [for]="id">{{ label }}</label>
768
+ <div class="input-container" [class.error]="hasError && !unstyled" [class.input-container--unstyled]="unstyled">
769
+ <div class="input-prefix-wrapper">
770
+ <ng-content select="[prefix]"></ng-content>
771
+ </div>
772
+ <input
773
+ noLeadingSpace
774
+ [type]="type"
775
+ [id]="id"
776
+ [placeholder]="placeholder"
777
+ [attr.maxlength]="format === 'currency' ? null : maxLength"
778
+ [disabled]="disabled"
779
+ [readonly]="readonly"
780
+ class="input-field"
781
+ [class.error]="hasError && !unstyled"
782
+ [class.input-field--unstyled]="unstyled"
783
+ [value]="formattedValue"
784
+ (blur)="onBlur()"
785
+ (input)="onInputChange($event)">
786
+ <div class="input-suffix-wrapper">
787
+ <ng-content select="[suffix]"></ng-content>
788
+ </div>
789
+ </div>
790
+ <div *ngIf="hasError && errorMessage && !unstyled" class="field-error">
791
+ {{ errorMessage }}
792
+ </div>
793
+ </div>
794
+ `, providers: [
795
+ {
796
+ provide: NG_VALUE_ACCESSOR,
797
+ useExisting: forwardRef(() => InputComponent),
798
+ multi: true
799
+ }
800
+ ], styles: ["input:-webkit-autofill,input:-webkit-autofill:hover,input:-webkit-autofill:focus,input:-webkit-autofill:active{-webkit-box-shadow:0 0 0 30px white inset!important;box-shadow:0 0 0 30px #fff inset!important;-webkit-text-fill-color:#2E353A!important;transition:background-color 5000s ease-in-out 0s}.input-prefix-wrapper,.input-suffix-wrapper{flex-shrink:0;display:flex;align-items:center;gap:.5rem;font-family:Quicksand,sans-serif;font-size:14px;font-weight:500;color:#969a9c;position:relative;z-index:2;pointer-events:auto!important}.input-prefix-wrapper{margin-right:.5rem;&:empty{display:none;margin-right:0}}.input-suffix-wrapper{margin-left:.5rem;&:empty{display:none;margin-left:0}}.input-prefix-wrapper *,.input-suffix-wrapper *{pointer-events:auto!important}.input-field{position:relative;z-index:1}\n"] }]
801
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { label: [{
802
+ type: Input
803
+ }], id: [{
804
+ type: Input
805
+ }], placeholder: [{
806
+ type: Input
807
+ }], type: [{
808
+ type: Input
809
+ }], maxLength: [{
810
+ type: Input
811
+ }], hasError: [{
812
+ type: Input
813
+ }], errorMessage: [{
814
+ type: Input
815
+ }], disabled: [{
816
+ type: Input
817
+ }], readonly: [{
818
+ type: Input
819
+ }], format: [{
820
+ type: Input
821
+ }], unstyled: [{
822
+ type: Input
823
+ }] } });
824
+
825
+ class TextareaComponent {
826
+ cdr;
827
+ label = '';
828
+ id = '';
829
+ placeholder = '';
830
+ rows = 4;
831
+ maxLength;
832
+ hasError = false;
833
+ errorMessage = '';
834
+ disabled = false;
835
+ readonly = false;
836
+ value = '';
837
+ onChange = () => { };
838
+ onTouched = () => { };
839
+ constructor(cdr) {
840
+ this.cdr = cdr;
841
+ }
842
+ writeValue(value) {
843
+ this.value = value || '';
844
+ this.cdr.markForCheck();
845
+ }
846
+ registerOnChange(fn) {
847
+ this.onChange = fn;
848
+ }
849
+ registerOnTouched(fn) {
850
+ this.onTouched = fn;
851
+ }
852
+ setDisabledState(isDisabled) {
853
+ this.disabled = isDisabled;
854
+ this.cdr.markForCheck();
855
+ }
856
+ onInputChange(event) {
857
+ const target = event.target;
858
+ this.value = target.value;
859
+ this.onChange(this.value);
860
+ }
861
+ onBlur() {
862
+ this.onTouched();
863
+ }
864
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextareaComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
865
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TextareaComponent, isStandalone: true, selector: "app-textarea", inputs: { label: "label", id: "id", placeholder: "placeholder", rows: "rows", maxLength: "maxLength", hasError: "hasError", errorMessage: "errorMessage", disabled: "disabled", readonly: "readonly" }, providers: [
866
+ {
867
+ provide: NG_VALUE_ACCESSOR,
868
+ useExisting: forwardRef(() => TextareaComponent),
869
+ multi: true
870
+ }
871
+ ], ngImport: i0, template: `
872
+ <div class="textarea-wrapper">
873
+ <label *ngIf="label" [for]="id" class="textarea-label">{{ label }}</label>
874
+ <div class="textarea-container" [class.error]="hasError">
875
+ <textarea
876
+ [id]="id"
877
+ [placeholder]="placeholder"
878
+ [rows]="rows"
879
+ [disabled]="disabled"
880
+ [readonly]="readonly"
881
+ [attr.maxlength]="maxLength"
882
+ class="textarea-field"
883
+ [class.error]="hasError"
884
+ [value]="value"
885
+ (blur)="onBlur()"
886
+ (input)="onInputChange($event)"
887
+ ></textarea>
888
+ </div>
889
+ <div *ngIf="hasError && errorMessage" class="field-error">
890
+ {{ errorMessage }}
891
+ </div>
892
+ </div>
893
+ `, isInline: true, styles: [".textarea-wrapper{width:100%;display:flex;flex-direction:column;gap:6px}.textarea-label{font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;line-height:20px;color:#414651}.textarea-container{width:100%;&.error .textarea-field{border-color:#f04438}}.textarea-field{width:100%;padding:10px 14px;background:#fff;border:1px solid #D5D7DA;border-radius:8px;font-family:Quicksand,sans-serif;font-weight:400;font-size:16px;line-height:24px;color:#2e353a;resize:vertical;min-height:100px;transition:all .2s ease;box-sizing:border-box;&::placeholder{color:#a4a7ae}&:focus{outline:none;border-color:#f59100;box-shadow:0 0 0 4px #f591001a}&:disabled{background:#f9fafb;cursor:not-allowed}&.error{border-color:#f04438;&:focus{box-shadow:0 0 0 4px #f044381a}}}.field-error{color:#f04438;font-size:.875rem;font-family:Quicksand,sans-serif}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
894
+ }
895
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TextareaComponent, decorators: [{
896
+ type: Component,
897
+ args: [{ selector: 'app-textarea', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
898
+ <div class="textarea-wrapper">
899
+ <label *ngIf="label" [for]="id" class="textarea-label">{{ label }}</label>
900
+ <div class="textarea-container" [class.error]="hasError">
901
+ <textarea
902
+ [id]="id"
903
+ [placeholder]="placeholder"
904
+ [rows]="rows"
905
+ [disabled]="disabled"
906
+ [readonly]="readonly"
907
+ [attr.maxlength]="maxLength"
908
+ class="textarea-field"
909
+ [class.error]="hasError"
910
+ [value]="value"
911
+ (blur)="onBlur()"
912
+ (input)="onInputChange($event)"
913
+ ></textarea>
914
+ </div>
915
+ <div *ngIf="hasError && errorMessage" class="field-error">
916
+ {{ errorMessage }}
917
+ </div>
918
+ </div>
919
+ `, providers: [
920
+ {
921
+ provide: NG_VALUE_ACCESSOR,
922
+ useExisting: forwardRef(() => TextareaComponent),
923
+ multi: true
924
+ }
925
+ ], styles: [".textarea-wrapper{width:100%;display:flex;flex-direction:column;gap:6px}.textarea-label{font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;line-height:20px;color:#414651}.textarea-container{width:100%;&.error .textarea-field{border-color:#f04438}}.textarea-field{width:100%;padding:10px 14px;background:#fff;border:1px solid #D5D7DA;border-radius:8px;font-family:Quicksand,sans-serif;font-weight:400;font-size:16px;line-height:24px;color:#2e353a;resize:vertical;min-height:100px;transition:all .2s ease;box-sizing:border-box;&::placeholder{color:#a4a7ae}&:focus{outline:none;border-color:#f59100;box-shadow:0 0 0 4px #f591001a}&:disabled{background:#f9fafb;cursor:not-allowed}&.error{border-color:#f04438;&:focus{box-shadow:0 0 0 4px #f044381a}}}.field-error{color:#f04438;font-size:.875rem;font-family:Quicksand,sans-serif}\n"] }]
926
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { label: [{
927
+ type: Input
928
+ }], id: [{
929
+ type: Input
930
+ }], placeholder: [{
931
+ type: Input
932
+ }], rows: [{
933
+ type: Input
934
+ }], maxLength: [{
935
+ type: Input
936
+ }], hasError: [{
937
+ type: Input
938
+ }], errorMessage: [{
939
+ type: Input
940
+ }], disabled: [{
941
+ type: Input
942
+ }], readonly: [{
943
+ type: Input
944
+ }] } });
945
+
946
+ class CheckboxComponent {
947
+ cdr;
948
+ elRef;
949
+ label = '';
950
+ id = '';
951
+ hasError = false;
952
+ errorMessage = '';
953
+ disabled = false;
954
+ indeterminate = false;
955
+ set checked(value) {
956
+ this.value = !!value;
957
+ this.cdr.markForCheck();
958
+ }
959
+ get checked() {
960
+ return this.value;
961
+ }
962
+ changed = new EventEmitter();
963
+ value = false;
964
+ onChange = () => { };
965
+ onTouched = () => { };
966
+ constructor(cdr, elRef) {
967
+ this.cdr = cdr;
968
+ this.elRef = elRef;
969
+ }
970
+ ngAfterViewInit() {
971
+ this.updateNativeIndeterminate();
972
+ }
973
+ ngOnChanges(changes) {
974
+ if (changes['indeterminate']) {
975
+ this.updateNativeIndeterminate();
976
+ }
977
+ }
978
+ updateNativeIndeterminate() {
979
+ const input = this.elRef.nativeElement.querySelector('input[type="checkbox"]');
980
+ if (input)
981
+ input.indeterminate = this.indeterminate;
982
+ }
983
+ onCheckboxChange(event) {
984
+ const target = event.target;
985
+ this.value = target.checked;
986
+ this.onChange(this.value);
987
+ this.changed.emit(this.value); // ← EMITE EVENTO MANUAL PARA USO EXTERNO
988
+ this.cdr.markForCheck();
989
+ }
990
+ onTextClick(event) {
991
+ const target = event.target;
992
+ if (target.tagName === 'A' || target.closest('a')) {
993
+ return;
994
+ }
995
+ if (this.disabled) {
996
+ return;
997
+ }
998
+ this.value = !this.value;
999
+ this.onChange(this.value);
1000
+ this.changed.emit(this.value);
1001
+ this.cdr.markForCheck();
1002
+ }
1003
+ writeValue(value) {
1004
+ this.value = !!value;
1005
+ this.cdr.markForCheck();
1006
+ }
1007
+ registerOnChange(fn) {
1008
+ this.onChange = fn;
1009
+ }
1010
+ registerOnTouched(fn) {
1011
+ this.onTouched = fn;
1012
+ }
1013
+ setDisabledState(isDisabled) {
1014
+ this.disabled = isDisabled;
1015
+ this.cdr.markForCheck();
1016
+ }
1017
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CheckboxComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1018
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CheckboxComponent, isStandalone: true, selector: "app-checkbox", inputs: { label: "label", id: "id", hasError: "hasError", errorMessage: "errorMessage", disabled: "disabled", indeterminate: "indeterminate", checked: "checked" }, outputs: { changed: "changed" }, providers: [
1019
+ {
1020
+ provide: NG_VALUE_ACCESSOR,
1021
+ useExisting: forwardRef(() => CheckboxComponent),
1022
+ multi: true
1023
+ }
1024
+ ], usesOnChanges: true, ngImport: i0, template: `
1025
+ <div class="checkbox-wrapper" [class.disabled]="disabled">
1026
+ <div class="checkbox-container">
1027
+ <label [for]="id" class="checkbox-label-input">
1028
+ <input
1029
+ type="checkbox"
1030
+ [id]="id"
1031
+ [disabled]="disabled"
1032
+ [checked]="value"
1033
+ (blur)="onTouched()"
1034
+ (change)="onCheckboxChange($event)">
1035
+ <span class="checkbox-custom" [class.checked]="value" [class.indeterminate]="indeterminate">
1036
+ <!-- Paloma -->
1037
+ <svg *ngIf="value && !indeterminate" class="check-icon" width="14" height="10" viewBox="0 0 10 8" fill="none" xmlns="http://www.w3.org/2000/svg">
1038
+ <path d="M9 1L3.5 6.5L1 4" stroke="#F59100" stroke-width="1.6666" stroke-linecap="round" stroke-linejoin="round"/>
1039
+ </svg>
1040
+ <!-- Guion -->
1041
+ <svg *ngIf="indeterminate && !value" class="minus-icon" width="12" height="2" viewBox="0 0 12 2" fill="none" xmlns="http://www.w3.org/2000/svg">
1042
+ <rect width="12" height="2" rx="1" fill="#F59100"/>
1043
+ </svg>
1044
+ </span>
1045
+ </label>
1046
+ <span class="checkbox-text" (click)="onTextClick($event)">
1047
+ <ng-content></ng-content>
1048
+ <span *ngIf="label" [innerHTML]="label"></span>
1049
+ </span>
1050
+ </div>
1051
+ <div *ngIf="hasError && errorMessage" class="field-error">
1052
+ {{ errorMessage }}
1053
+ </div>
1054
+ </div>
1055
+ `, isInline: true, styles: [".checkbox-wrapper{width:100%;padding:0 4px}.checkbox-wrapper.disabled{opacity:.6;cursor:not-allowed}.checkbox-container{display:flex;align-items:flex-start;gap:.75rem}.checkbox-label-input{cursor:pointer;position:relative;display:flex;align-items:center}.checkbox-label-input input[type=checkbox]{position:absolute;opacity:0;cursor:pointer;width:22px;height:22px;margin:0;z-index:2;top:2px;left:0}.checkbox-label-input .checkbox-custom{width:22px;height:22px;min-width:22px;border:2.5px solid #D5D7D8;border-radius:6px;display:flex;align-items:center;justify-content:center;transition:all .25s cubic-bezier(.4,0,.2,1);background:#fff;margin-top:2px;position:relative}.checkbox-label-input .checkbox-custom:after{content:\"\";position:absolute;width:100%;height:100%;border-radius:4px;background:#f59100;opacity:0;transform:scale(.5);transition:all .25s cubic-bezier(.4,0,.2,1)}.checkbox-label-input .checkbox-custom.checked,.checkbox-label-input .checkbox-custom.indeterminate{background:#fff;border-color:#f59100;border-width:2.5px;box-shadow:0 3px 8px #f26d0040,0 1px 3px #f26d0026;transform:scale(1.05)}.checkbox-label-input .checkbox-custom.checked:after,.checkbox-label-input .checkbox-custom.indeterminate:after{opacity:0}.checkbox-label-input .checkbox-custom .check-icon{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;animation:checkPop .3s cubic-bezier(.68,-.55,.265,1.55)}.checkbox-label-input:hover .checkbox-custom:not(.checked){border-color:#f26d00;transform:scale(1.05)}.checkbox-text{flex:1;font-family:Quicksand,sans-serif;font-size:14px;font-weight:500;line-height:1.7;-webkit-user-select:none;user-select:none;cursor:pointer}.checkbox-text ::ng-deep a{color:#364b9f;font-family:Quicksand,sans-serif;font-size:14px;font-weight:500;line-height:1.7;cursor:pointer}.checkbox-wrapper.disabled .checkbox-text{cursor:not-allowed}@keyframes checkPop{0%{transform:scale(0);opacity:0}50%{transform:scale(1.2)}to{transform:scale(1);opacity:1}}.field-error{color:#f04438;font-size:.875rem;margin-top:.25rem;font-family:Quicksand,sans-serif}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] });
1056
+ }
1057
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CheckboxComponent, decorators: [{
1058
+ type: Component,
1059
+ args: [{ selector: 'app-checkbox', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], template: `
1060
+ <div class="checkbox-wrapper" [class.disabled]="disabled">
1061
+ <div class="checkbox-container">
1062
+ <label [for]="id" class="checkbox-label-input">
1063
+ <input
1064
+ type="checkbox"
1065
+ [id]="id"
1066
+ [disabled]="disabled"
1067
+ [checked]="value"
1068
+ (blur)="onTouched()"
1069
+ (change)="onCheckboxChange($event)">
1070
+ <span class="checkbox-custom" [class.checked]="value" [class.indeterminate]="indeterminate">
1071
+ <!-- Paloma -->
1072
+ <svg *ngIf="value && !indeterminate" class="check-icon" width="14" height="10" viewBox="0 0 10 8" fill="none" xmlns="http://www.w3.org/2000/svg">
1073
+ <path d="M9 1L3.5 6.5L1 4" stroke="#F59100" stroke-width="1.6666" stroke-linecap="round" stroke-linejoin="round"/>
1074
+ </svg>
1075
+ <!-- Guion -->
1076
+ <svg *ngIf="indeterminate && !value" class="minus-icon" width="12" height="2" viewBox="0 0 12 2" fill="none" xmlns="http://www.w3.org/2000/svg">
1077
+ <rect width="12" height="2" rx="1" fill="#F59100"/>
1078
+ </svg>
1079
+ </span>
1080
+ </label>
1081
+ <span class="checkbox-text" (click)="onTextClick($event)">
1082
+ <ng-content></ng-content>
1083
+ <span *ngIf="label" [innerHTML]="label"></span>
1084
+ </span>
1085
+ </div>
1086
+ <div *ngIf="hasError && errorMessage" class="field-error">
1087
+ {{ errorMessage }}
1088
+ </div>
1089
+ </div>
1090
+ `, providers: [
1091
+ {
1092
+ provide: NG_VALUE_ACCESSOR,
1093
+ useExisting: forwardRef(() => CheckboxComponent),
1094
+ multi: true
1095
+ }
1096
+ ], styles: [".checkbox-wrapper{width:100%;padding:0 4px}.checkbox-wrapper.disabled{opacity:.6;cursor:not-allowed}.checkbox-container{display:flex;align-items:flex-start;gap:.75rem}.checkbox-label-input{cursor:pointer;position:relative;display:flex;align-items:center}.checkbox-label-input input[type=checkbox]{position:absolute;opacity:0;cursor:pointer;width:22px;height:22px;margin:0;z-index:2;top:2px;left:0}.checkbox-label-input .checkbox-custom{width:22px;height:22px;min-width:22px;border:2.5px solid #D5D7D8;border-radius:6px;display:flex;align-items:center;justify-content:center;transition:all .25s cubic-bezier(.4,0,.2,1);background:#fff;margin-top:2px;position:relative}.checkbox-label-input .checkbox-custom:after{content:\"\";position:absolute;width:100%;height:100%;border-radius:4px;background:#f59100;opacity:0;transform:scale(.5);transition:all .25s cubic-bezier(.4,0,.2,1)}.checkbox-label-input .checkbox-custom.checked,.checkbox-label-input .checkbox-custom.indeterminate{background:#fff;border-color:#f59100;border-width:2.5px;box-shadow:0 3px 8px #f26d0040,0 1px 3px #f26d0026;transform:scale(1.05)}.checkbox-label-input .checkbox-custom.checked:after,.checkbox-label-input .checkbox-custom.indeterminate:after{opacity:0}.checkbox-label-input .checkbox-custom .check-icon{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;animation:checkPop .3s cubic-bezier(.68,-.55,.265,1.55)}.checkbox-label-input:hover .checkbox-custom:not(.checked){border-color:#f26d00;transform:scale(1.05)}.checkbox-text{flex:1;font-family:Quicksand,sans-serif;font-size:14px;font-weight:500;line-height:1.7;-webkit-user-select:none;user-select:none;cursor:pointer}.checkbox-text ::ng-deep a{color:#364b9f;font-family:Quicksand,sans-serif;font-size:14px;font-weight:500;line-height:1.7;cursor:pointer}.checkbox-wrapper.disabled .checkbox-text{cursor:not-allowed}@keyframes checkPop{0%{transform:scale(0);opacity:0}50%{transform:scale(1.2)}to{transform:scale(1);opacity:1}}.field-error{color:#f04438;font-size:.875rem;margin-top:.25rem;font-family:Quicksand,sans-serif}\n"] }]
1097
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { label: [{
1098
+ type: Input
1099
+ }], id: [{
1100
+ type: Input
1101
+ }], hasError: [{
1102
+ type: Input
1103
+ }], errorMessage: [{
1104
+ type: Input
1105
+ }], disabled: [{
1106
+ type: Input
1107
+ }], indeterminate: [{
1108
+ type: Input
1109
+ }], checked: [{
1110
+ type: Input
1111
+ }], changed: [{
1112
+ type: Output
1113
+ }] } });
1114
+
1115
+ class RadioComponent {
1116
+ cdr;
1117
+ label = '';
1118
+ id = '';
1119
+ name = '';
1120
+ radioValue = '';
1121
+ disabled = false;
1122
+ changed = new EventEmitter();
1123
+ value = null;
1124
+ onChange = () => { };
1125
+ onTouched = () => { };
1126
+ constructor(cdr) {
1127
+ this.cdr = cdr;
1128
+ }
1129
+ get isSelected() {
1130
+ return this.value === this.radioValue;
1131
+ }
1132
+ onContainerClick() {
1133
+ if (this.disabled)
1134
+ return;
1135
+ this.value = this.radioValue;
1136
+ this.onChange(this.value);
1137
+ this.changed.emit(this.value);
1138
+ this.cdr.markForCheck();
1139
+ }
1140
+ onRadioChange(event) {
1141
+ event.stopPropagation();
1142
+ const target = event.target;
1143
+ if (target.checked) {
1144
+ this.value = this.radioValue;
1145
+ this.onChange(this.value);
1146
+ this.changed.emit(this.value);
1147
+ this.cdr.markForCheck();
1148
+ }
1149
+ }
1150
+ writeValue(value) {
1151
+ this.value = value;
1152
+ this.cdr.markForCheck();
1153
+ }
1154
+ registerOnChange(fn) {
1155
+ this.onChange = fn;
1156
+ }
1157
+ registerOnTouched(fn) {
1158
+ this.onTouched = fn;
1159
+ }
1160
+ setDisabledState(isDisabled) {
1161
+ this.disabled = isDisabled;
1162
+ this.cdr.markForCheck();
1163
+ }
1164
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1165
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: RadioComponent, isStandalone: true, selector: "app-radio", inputs: { label: "label", id: "id", name: "name", radioValue: "radioValue", disabled: "disabled" }, outputs: { changed: "changed" }, providers: [
1166
+ {
1167
+ provide: NG_VALUE_ACCESSOR,
1168
+ useExisting: forwardRef(() => RadioComponent),
1169
+ multi: true
1170
+ }
1171
+ ], ngImport: i0, template: `
1172
+ <div
1173
+ class="radio-wrapper"
1174
+ [class.disabled]="disabled"
1175
+ [class.radio-wrapper--selected]="isSelected"
1176
+ (click)="onContainerClick()"
1177
+ >
1178
+ <div class="radio-container">
1179
+ <input
1180
+ type="radio"
1181
+ [id]="id"
1182
+ [name]="name"
1183
+ [value]="radioValue"
1184
+ [disabled]="disabled"
1185
+ [checked]="isSelected"
1186
+ (blur)="onTouched()"
1187
+ (change)="onRadioChange($event)"
1188
+ class="radio-input"
1189
+ />
1190
+ <span class="radio-custom" [class.checked]="isSelected">
1191
+ <span class="radio-dot" *ngIf="isSelected"></span>
1192
+ </span>
1193
+ <span class="radio-text">
1194
+ <ng-content></ng-content>
1195
+ <span *ngIf="label">{{ label }}</span>
1196
+ </span>
1197
+ </div>
1198
+ </div>
1199
+ `, isInline: true, styles: [":host{display:block;outline:none!important}:host:focus,:host:focus-visible,:host:focus-within{outline:none!important;box-shadow:none!important}.radio-wrapper{cursor:pointer;outline:none!important;box-shadow:none!important}.radio-wrapper:focus,.radio-wrapper:focus-visible,.radio-wrapper:focus-within{outline:none!important;box-shadow:none!important}.radio-wrapper.disabled{opacity:.6;cursor:not-allowed;pointer-events:none}.radio-wrapper--selected .radio-custom{border-color:#f59100}.radio-container{display:flex;align-items:center;gap:12px;padding:0;background:transparent;border:none;outline:none!important;box-shadow:none!important}.radio-container:focus,.radio-container:focus-visible,.radio-container:focus-within{outline:none!important;box-shadow:none!important}.radio-container:hover .radio-custom:not(.checked){border-color:#f59100}.radio-input{position:absolute;opacity:0;pointer-events:none;width:0;height:0;margin:0;padding:0;border:none!important;outline:none!important;box-shadow:none!important}.radio-input:focus,.radio-input:focus-visible,.radio-input:checked{outline:none!important;box-shadow:none!important;border:none!important}.radio-custom{width:20px;height:20px;min-width:20px;border:2px solid #D5D7DA;border-radius:50%;display:flex;align-items:center;justify-content:center;transition:border-color .2s ease;background:#fff;flex-shrink:0;outline:none!important;box-shadow:none!important}.radio-custom.checked{border-color:#f59100}.radio-custom .radio-dot{width:10px;height:10px;border-radius:50%;background:#f59100}.radio-text{font-family:Quicksand,sans-serif;font-size:16px;font-weight:500;line-height:24px;color:#585d61;-webkit-user-select:none;user-select:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] });
1200
+ }
1201
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioComponent, decorators: [{
1202
+ type: Component,
1203
+ args: [{ selector: 'app-radio', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], template: `
1204
+ <div
1205
+ class="radio-wrapper"
1206
+ [class.disabled]="disabled"
1207
+ [class.radio-wrapper--selected]="isSelected"
1208
+ (click)="onContainerClick()"
1209
+ >
1210
+ <div class="radio-container">
1211
+ <input
1212
+ type="radio"
1213
+ [id]="id"
1214
+ [name]="name"
1215
+ [value]="radioValue"
1216
+ [disabled]="disabled"
1217
+ [checked]="isSelected"
1218
+ (blur)="onTouched()"
1219
+ (change)="onRadioChange($event)"
1220
+ class="radio-input"
1221
+ />
1222
+ <span class="radio-custom" [class.checked]="isSelected">
1223
+ <span class="radio-dot" *ngIf="isSelected"></span>
1224
+ </span>
1225
+ <span class="radio-text">
1226
+ <ng-content></ng-content>
1227
+ <span *ngIf="label">{{ label }}</span>
1228
+ </span>
1229
+ </div>
1230
+ </div>
1231
+ `, providers: [
1232
+ {
1233
+ provide: NG_VALUE_ACCESSOR,
1234
+ useExisting: forwardRef(() => RadioComponent),
1235
+ multi: true
1236
+ }
1237
+ ], styles: [":host{display:block;outline:none!important}:host:focus,:host:focus-visible,:host:focus-within{outline:none!important;box-shadow:none!important}.radio-wrapper{cursor:pointer;outline:none!important;box-shadow:none!important}.radio-wrapper:focus,.radio-wrapper:focus-visible,.radio-wrapper:focus-within{outline:none!important;box-shadow:none!important}.radio-wrapper.disabled{opacity:.6;cursor:not-allowed;pointer-events:none}.radio-wrapper--selected .radio-custom{border-color:#f59100}.radio-container{display:flex;align-items:center;gap:12px;padding:0;background:transparent;border:none;outline:none!important;box-shadow:none!important}.radio-container:focus,.radio-container:focus-visible,.radio-container:focus-within{outline:none!important;box-shadow:none!important}.radio-container:hover .radio-custom:not(.checked){border-color:#f59100}.radio-input{position:absolute;opacity:0;pointer-events:none;width:0;height:0;margin:0;padding:0;border:none!important;outline:none!important;box-shadow:none!important}.radio-input:focus,.radio-input:focus-visible,.radio-input:checked{outline:none!important;box-shadow:none!important;border:none!important}.radio-custom{width:20px;height:20px;min-width:20px;border:2px solid #D5D7DA;border-radius:50%;display:flex;align-items:center;justify-content:center;transition:border-color .2s ease;background:#fff;flex-shrink:0;outline:none!important;box-shadow:none!important}.radio-custom.checked{border-color:#f59100}.radio-custom .radio-dot{width:10px;height:10px;border-radius:50%;background:#f59100}.radio-text{font-family:Quicksand,sans-serif;font-size:16px;font-weight:500;line-height:24px;color:#585d61;-webkit-user-select:none;user-select:none}\n"] }]
1238
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { label: [{
1239
+ type: Input
1240
+ }], id: [{
1241
+ type: Input
1242
+ }], name: [{
1243
+ type: Input
1244
+ }], radioValue: [{
1245
+ type: Input
1246
+ }], disabled: [{
1247
+ type: Input
1248
+ }], changed: [{
1249
+ type: Output
1250
+ }] } });
1251
+
1252
+ class DatePickerComponent {
1253
+ renderer;
1254
+ document;
1255
+ label = '';
1256
+ id = '';
1257
+ placeholder = 'Seleccionar fecha';
1258
+ hasError = false;
1259
+ errorMessage = '';
1260
+ disabled = false;
1261
+ minDate;
1262
+ maxDate;
1263
+ rangeMode = false; // false = single date, true = date range
1264
+ iconPosition = 'left';
1265
+ trigger;
1266
+ dropdown;
1267
+ // Single date value
1268
+ singleValue = null;
1269
+ // Range value
1270
+ rangeValue = { startDate: null, endDate: null };
1271
+ isOpen = false;
1272
+ onChange = () => { };
1273
+ onTouched = () => { };
1274
+ leftMonthDate = new Date();
1275
+ rightMonthDate = new Date();
1276
+ tempStartDate = null;
1277
+ tempEndDate = null;
1278
+ tempSingleDate = null;
1279
+ hoverDate = null;
1280
+ // Store original calendar positions for cancel
1281
+ originalLeftMonthDate = new Date();
1282
+ originalRightMonthDate = new Date();
1283
+ // Cached calendar days
1284
+ leftCalendarDays = [];
1285
+ rightCalendarDays = [];
1286
+ filterOptions = [
1287
+ { value: 'hoy', label: 'Hoy' },
1288
+ { value: 'ayer', label: 'Ayer' },
1289
+ { value: 'esta-semana', label: 'Esta semana' },
1290
+ { value: 'semana-pasada', label: 'Semana pasada' },
1291
+ { value: 'este-mes', label: 'Este mes' },
1292
+ { value: 'mes-pasado', label: 'Mes pasado' },
1293
+ { value: 'este-ano', label: 'Este año' },
1294
+ { value: 'ano-pasado', label: 'Año pasado' },
1295
+ { value: 'mostrar-todo', label: 'Mostrar todo' }
1296
+ ];
1297
+ selectedFilter = '';
1298
+ weekDays = ['Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa', 'Do'];
1299
+ months = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
1300
+ // Month/Year picker state
1301
+ showLeftMonthPicker = false;
1302
+ showRightMonthPicker = false;
1303
+ years = [];
1304
+ leftYearPickerPage = 0;
1305
+ rightYearPickerPage = 0;
1306
+ yearsPerPage = 12;
1307
+ scrollHandler = null;
1308
+ resizeHandler = null;
1309
+ dropdownPosition = { top: '0px', left: '0px' };
1310
+ constructor(renderer, document) {
1311
+ this.renderer = renderer;
1312
+ this.document = document;
1313
+ }
1314
+ ngOnInit() {
1315
+ this.initializeDates();
1316
+ }
1317
+ ngOnDestroy() {
1318
+ this.removeRepositionListeners();
1319
+ }
1320
+ initializeDates() {
1321
+ const today = new Date();
1322
+ this.leftMonthDate = new Date(today.getFullYear(), today.getMonth(), 1);
1323
+ this.rightMonthDate = new Date(today.getFullYear(), today.getMonth() + 1, 1);
1324
+ this.updateCalendarDays();
1325
+ }
1326
+ updateCalendarDays() {
1327
+ this.leftCalendarDays = this.generateCalendarDays(this.leftMonthDate);
1328
+ if (this.rangeMode) {
1329
+ this.rightCalendarDays = this.generateCalendarDays(this.rightMonthDate);
1330
+ }
1331
+ }
1332
+ onDocumentClick(event) {
1333
+ if (!this.isOpen)
1334
+ return;
1335
+ const triggerElement = this.trigger?.nativeElement;
1336
+ const dropdownElement = this.document.querySelector('.date-picker-dropdown');
1337
+ const monthYearPickers = this.document.querySelectorAll('.month-year-picker');
1338
+ const monthYearButtons = this.document.querySelectorAll('.month-year');
1339
+ let isOnMonthYearButton = false;
1340
+ monthYearButtons.forEach(button => {
1341
+ if (button.contains(event.target)) {
1342
+ isOnMonthYearButton = true;
1343
+ }
1344
+ });
1345
+ let isInsideMonthYearPicker = false;
1346
+ monthYearPickers.forEach(picker => {
1347
+ if (picker.contains(event.target)) {
1348
+ isInsideMonthYearPicker = true;
1349
+ }
1350
+ });
1351
+ if (isOnMonthYearButton || isInsideMonthYearPicker) {
1352
+ return;
1353
+ }
1354
+ if (dropdownElement && dropdownElement.contains(event.target)) {
1355
+ this.showLeftMonthPicker = false;
1356
+ this.showRightMonthPicker = false;
1357
+ return;
1358
+ }
1359
+ if (triggerElement && !triggerElement.contains(event.target)) {
1360
+ if (dropdownElement && !dropdownElement.contains(event.target)) {
1361
+ this.closeDropdown();
1362
+ }
1363
+ }
1364
+ }
1365
+ toggleDropdown(event) {
1366
+ event.stopPropagation();
1367
+ if (this.disabled)
1368
+ return;
1369
+ if (this.isOpen) {
1370
+ this.closeDropdown();
1371
+ }
1372
+ else {
1373
+ this.openDropdown();
1374
+ }
1375
+ }
1376
+ openDropdown() {
1377
+ if (!this.trigger)
1378
+ return;
1379
+ if (this.rangeMode) {
1380
+ this.tempStartDate = this.rangeValue.startDate;
1381
+ this.tempEndDate = this.rangeValue.endDate;
1382
+ }
1383
+ else {
1384
+ this.tempSingleDate = this.singleValue;
1385
+ }
1386
+ this.originalLeftMonthDate = new Date(this.leftMonthDate);
1387
+ this.originalRightMonthDate = new Date(this.rightMonthDate);
1388
+ this.leftYearPickerPage = 0;
1389
+ this.rightYearPickerPage = 0;
1390
+ this.isOpen = true;
1391
+ setTimeout(() => {
1392
+ this.updateDropdownPosition();
1393
+ this.addRepositionListeners();
1394
+ }, 0);
1395
+ }
1396
+ getDropdownStyle() {
1397
+ if (!this.trigger)
1398
+ return {};
1399
+ const position = this.calculatePosition();
1400
+ return {
1401
+ 'position': 'fixed',
1402
+ 'left': position.left,
1403
+ 'top': position.top,
1404
+ 'z-index': '10000'
1405
+ };
1406
+ }
1407
+ calculatePosition() {
1408
+ const triggerElement = this.trigger.nativeElement;
1409
+ const rect = triggerElement.getBoundingClientRect();
1410
+ let dropdownWidth = this.rangeMode ? 830 : 320;
1411
+ let dropdownHeight = this.rangeMode ? 520 : 400;
1412
+ if (this.dropdown) {
1413
+ const dropdownElement = this.dropdown.nativeElement;
1414
+ const dropdownRect = dropdownElement.getBoundingClientRect();
1415
+ if (dropdownRect.width > 0) {
1416
+ dropdownWidth = dropdownRect.width;
1417
+ }
1418
+ else {
1419
+ dropdownWidth = window.innerWidth < 768 ? 280 : (this.rangeMode ? 830 : 320);
1420
+ }
1421
+ if (dropdownRect.height > 0) {
1422
+ dropdownHeight = dropdownRect.height;
1423
+ }
1424
+ }
1425
+ else {
1426
+ dropdownWidth = window.innerWidth < 768 ? 280 : (this.rangeMode ? 830 : 320);
1427
+ }
1428
+ const spaceOnRight = window.innerWidth - rect.left;
1429
+ let left = rect.left;
1430
+ if (spaceOnRight < dropdownWidth) {
1431
+ left = rect.right - dropdownWidth;
1432
+ if (left < 0) {
1433
+ left = Math.max(8, window.innerWidth - dropdownWidth - 8);
1434
+ }
1435
+ }
1436
+ if (window.innerWidth < 768) {
1437
+ const centeredLeft = rect.left + (rect.width / 2) - (dropdownWidth / 2);
1438
+ const minLeft = 8;
1439
+ const maxLeft = window.innerWidth - dropdownWidth - 8;
1440
+ left = Math.max(minLeft, Math.min(centeredLeft, maxLeft));
1441
+ }
1442
+ const spaceBelow = window.innerHeight - rect.bottom;
1443
+ const spaceAbove = rect.top;
1444
+ let top = rect.bottom + 4;
1445
+ if (spaceBelow < dropdownHeight && spaceAbove > spaceBelow) {
1446
+ top = rect.top - dropdownHeight - 4;
1447
+ }
1448
+ return {
1449
+ top: `${top}px`,
1450
+ left: `${left}px`
1451
+ };
1452
+ }
1453
+ closeDropdown() {
1454
+ this.leftMonthDate = new Date(this.originalLeftMonthDate);
1455
+ this.rightMonthDate = new Date(this.originalRightMonthDate);
1456
+ if (this.rangeMode) {
1457
+ this.tempStartDate = this.rangeValue.startDate;
1458
+ this.tempEndDate = this.rangeValue.endDate;
1459
+ }
1460
+ else {
1461
+ this.tempSingleDate = this.singleValue;
1462
+ }
1463
+ this.updateCalendarDays();
1464
+ this.removeRepositionListeners();
1465
+ this.isOpen = false;
1466
+ this.hoverDate = null;
1467
+ this.showLeftMonthPicker = false;
1468
+ this.showRightMonthPicker = false;
1469
+ }
1470
+ addRepositionListeners() {
1471
+ const scrollHandler = () => this.updateDropdownPosition();
1472
+ const resizeHandler = () => this.updateDropdownPosition();
1473
+ window.addEventListener('scroll', scrollHandler, true);
1474
+ this.scrollHandler = () => window.removeEventListener('scroll', scrollHandler, true);
1475
+ window.addEventListener('resize', resizeHandler);
1476
+ this.resizeHandler = () => window.removeEventListener('resize', resizeHandler);
1477
+ }
1478
+ removeRepositionListeners() {
1479
+ if (this.scrollHandler) {
1480
+ this.scrollHandler();
1481
+ this.scrollHandler = null;
1482
+ }
1483
+ if (this.resizeHandler) {
1484
+ this.resizeHandler();
1485
+ this.resizeHandler = null;
1486
+ }
1487
+ }
1488
+ updateDropdownPosition() {
1489
+ if (!this.trigger)
1490
+ return;
1491
+ this.dropdownPosition = this.calculatePosition();
1492
+ }
1493
+ getDisplayValue() {
1494
+ if (this.rangeMode) {
1495
+ if (this.rangeValue.startDate && this.rangeValue.endDate) {
1496
+ const start = this.formatDateShort(this.rangeValue.startDate);
1497
+ const end = this.formatDateShort(this.rangeValue.endDate);
1498
+ return `${start} - ${end}`;
1499
+ }
1500
+ }
1501
+ else {
1502
+ if (this.singleValue) {
1503
+ return this.formatDateShort(this.singleValue);
1504
+ }
1505
+ }
1506
+ return '';
1507
+ }
1508
+ formatDateShort(date) {
1509
+ const day = String(date.getDate()).padStart(2, '0');
1510
+ const month = String(date.getMonth() + 1).padStart(2, '0');
1511
+ const year = date.getFullYear();
1512
+ return `${day}/${month}/${year}`;
1513
+ }
1514
+ generateCalendarDays(monthDate) {
1515
+ const year = monthDate.getFullYear();
1516
+ const month = monthDate.getMonth();
1517
+ const firstDay = new Date(year, month, 1);
1518
+ const lastDay = new Date(year, month + 1, 0);
1519
+ let startDay = firstDay.getDay() - 1;
1520
+ if (startDay === -1)
1521
+ startDay = 6;
1522
+ const days = [];
1523
+ const prevMonthLastDay = new Date(year, month, 0);
1524
+ for (let i = startDay - 1; i >= 0; i--) {
1525
+ const date = new Date(year, month - 1, prevMonthLastDay.getDate() - i);
1526
+ date.setHours(0, 0, 0, 0);
1527
+ days.push(this.createCalendarDay(date, false));
1528
+ }
1529
+ for (let day = 1; day <= lastDay.getDate(); day++) {
1530
+ const date = new Date(year, month, day);
1531
+ date.setHours(0, 0, 0, 0);
1532
+ days.push(this.createCalendarDay(date, true));
1533
+ }
1534
+ const remainingDays = 42 - days.length;
1535
+ for (let day = 1; day <= remainingDays; day++) {
1536
+ const date = new Date(year, month + 1, day);
1537
+ date.setHours(0, 0, 0, 0);
1538
+ days.push(this.createCalendarDay(date, false));
1539
+ }
1540
+ return days;
1541
+ }
1542
+ createCalendarDay(date, isCurrentMonth) {
1543
+ const today = new Date();
1544
+ today.setHours(0, 0, 0, 0);
1545
+ const dateOnly = new Date(date);
1546
+ dateOnly.setHours(0, 0, 0, 0);
1547
+ const isToday = dateOnly.getTime() === today.getTime();
1548
+ let isSelected = false;
1549
+ let isRangeStart = false;
1550
+ let isRangeEnd = false;
1551
+ let isInRange = false;
1552
+ if (this.rangeMode) {
1553
+ const startDate = this.tempStartDate ? new Date(this.tempStartDate) : null;
1554
+ const endDate = this.tempEndDate ? new Date(this.tempEndDate) : null;
1555
+ if (startDate)
1556
+ startDate.setHours(0, 0, 0, 0);
1557
+ if (endDate)
1558
+ endDate.setHours(0, 0, 0, 0);
1559
+ isRangeStart = isCurrentMonth && startDate ? dateOnly.getTime() === startDate.getTime() : false;
1560
+ isRangeEnd = isCurrentMonth && endDate ? dateOnly.getTime() === endDate.getTime() : false;
1561
+ isSelected = isRangeStart || isRangeEnd;
1562
+ if (isCurrentMonth && startDate && endDate) {
1563
+ isInRange = dateOnly > startDate && dateOnly < endDate;
1564
+ }
1565
+ else if (isCurrentMonth && startDate && this.hoverDate && !endDate) {
1566
+ const hoverDateOnly = new Date(this.hoverDate);
1567
+ hoverDateOnly.setHours(0, 0, 0, 0);
1568
+ if (hoverDateOnly > startDate) {
1569
+ isInRange = dateOnly > startDate && dateOnly < hoverDateOnly;
1570
+ }
1571
+ }
1572
+ }
1573
+ else {
1574
+ const selectedDate = this.tempSingleDate ? new Date(this.tempSingleDate) : null;
1575
+ if (selectedDate)
1576
+ selectedDate.setHours(0, 0, 0, 0);
1577
+ isSelected = isCurrentMonth && selectedDate ? dateOnly.getTime() === selectedDate.getTime() : false;
1578
+ }
1579
+ const isDisabled = !isCurrentMonth || this.isDateDisabled(date);
1580
+ return {
1581
+ date,
1582
+ isCurrentMonth,
1583
+ isToday,
1584
+ isSelected,
1585
+ isInRange,
1586
+ isRangeStart,
1587
+ isRangeEnd,
1588
+ isDisabled
1589
+ };
1590
+ }
1591
+ isDateDisabled(date) {
1592
+ if (this.minDate && date < this.minDate)
1593
+ return true;
1594
+ if (this.maxDate && date > this.maxDate)
1595
+ return true;
1596
+ return false;
1597
+ }
1598
+ trackByDate(index, day) {
1599
+ return day.date.getTime().toString();
1600
+ }
1601
+ isInRange(date) {
1602
+ if (!this.rangeMode)
1603
+ return false;
1604
+ const dateOnly = new Date(date);
1605
+ dateOnly.setHours(0, 0, 0, 0);
1606
+ const startDate = this.tempStartDate ? new Date(this.tempStartDate) : null;
1607
+ const endDate = this.tempEndDate ? new Date(this.tempEndDate) : null;
1608
+ if (startDate)
1609
+ startDate.setHours(0, 0, 0, 0);
1610
+ if (endDate)
1611
+ endDate.setHours(0, 0, 0, 0);
1612
+ if (startDate && endDate) {
1613
+ return dateOnly > startDate && dateOnly < endDate;
1614
+ }
1615
+ else if (startDate && this.hoverDate && !endDate) {
1616
+ const hoverDateOnly = new Date(this.hoverDate);
1617
+ hoverDateOnly.setHours(0, 0, 0, 0);
1618
+ if (hoverDateOnly > startDate) {
1619
+ return dateOnly > startDate && dateOnly < hoverDateOnly;
1620
+ }
1621
+ }
1622
+ return false;
1623
+ }
1624
+ onDayClick(day) {
1625
+ if (day.isDisabled)
1626
+ return;
1627
+ const clickedDate = new Date(day.date);
1628
+ clickedDate.setHours(0, 0, 0, 0);
1629
+ if (this.rangeMode) {
1630
+ this.selectedFilter = '';
1631
+ if (!this.tempStartDate || (this.tempStartDate && this.tempEndDate)) {
1632
+ this.tempStartDate = clickedDate;
1633
+ this.tempEndDate = null;
1634
+ this.hoverDate = null;
1635
+ }
1636
+ else if (this.tempStartDate && !this.tempEndDate) {
1637
+ const startDate = new Date(this.tempStartDate);
1638
+ startDate.setHours(0, 0, 0, 0);
1639
+ if (clickedDate.getTime() === startDate.getTime()) {
1640
+ this.tempEndDate = clickedDate;
1641
+ }
1642
+ else if (clickedDate > startDate) {
1643
+ this.tempEndDate = clickedDate;
1644
+ }
1645
+ else {
1646
+ this.tempEndDate = startDate;
1647
+ this.tempStartDate = clickedDate;
1648
+ }
1649
+ this.hoverDate = null;
1650
+ }
1651
+ }
1652
+ else {
1653
+ this.tempSingleDate = clickedDate;
1654
+ // Auto-apply for single date mode
1655
+ this.apply();
1656
+ return;
1657
+ }
1658
+ this.updateCalendarDays();
1659
+ }
1660
+ onDayHover(day) {
1661
+ if (day.isDisabled || !this.rangeMode)
1662
+ return;
1663
+ this.hoverDate = day.date;
1664
+ }
1665
+ onDayLeave() {
1666
+ this.hoverDate = null;
1667
+ }
1668
+ previousMonth() {
1669
+ if (!this.canNavigatePreviousMonth())
1670
+ return;
1671
+ this.leftMonthDate = new Date(this.leftMonthDate.getFullYear(), this.leftMonthDate.getMonth() - 1, 1);
1672
+ if (this.rangeMode) {
1673
+ this.rightMonthDate = new Date(this.rightMonthDate.getFullYear(), this.rightMonthDate.getMonth() - 1, 1);
1674
+ }
1675
+ this.updateCalendarDays();
1676
+ }
1677
+ nextMonth() {
1678
+ if (!this.canNavigateNextMonth())
1679
+ return;
1680
+ this.leftMonthDate = new Date(this.leftMonthDate.getFullYear(), this.leftMonthDate.getMonth() + 1, 1);
1681
+ if (this.rangeMode) {
1682
+ this.rightMonthDate = new Date(this.rightMonthDate.getFullYear(), this.rightMonthDate.getMonth() + 1, 1);
1683
+ }
1684
+ this.updateCalendarDays();
1685
+ }
1686
+ canNavigatePreviousMonth() {
1687
+ if (!this.minDate)
1688
+ return true;
1689
+ const newLeftMonth = new Date(this.leftMonthDate.getFullYear(), this.leftMonthDate.getMonth() - 1, 1);
1690
+ const minDateMonth = new Date(this.minDate.getFullYear(), this.minDate.getMonth(), 1);
1691
+ return newLeftMonth >= minDateMonth;
1692
+ }
1693
+ canNavigateNextMonth() {
1694
+ if (!this.maxDate)
1695
+ return true;
1696
+ const checkMonth = this.rangeMode ? this.rightMonthDate : this.leftMonthDate;
1697
+ const newMonth = new Date(checkMonth.getFullYear(), checkMonth.getMonth() + 1, 1);
1698
+ const maxDateMonth = new Date(this.maxDate.getFullYear(), this.maxDate.getMonth(), 1);
1699
+ return newMonth <= maxDateMonth;
1700
+ }
1701
+ getMonthYear(date) {
1702
+ return `${this.months[date.getMonth()]} ${date.getFullYear()}`;
1703
+ }
1704
+ selectFilter(filter) {
1705
+ this.selectedFilter = filter;
1706
+ this.applyFilter(filter);
1707
+ this.updateCalendarDays();
1708
+ }
1709
+ applyFilter(filter) {
1710
+ const today = new Date();
1711
+ today.setHours(0, 0, 0, 0);
1712
+ let startDate = null;
1713
+ let endDate = null;
1714
+ switch (filter) {
1715
+ case 'hoy':
1716
+ startDate = new Date(today);
1717
+ endDate = new Date(today);
1718
+ break;
1719
+ case 'ayer':
1720
+ startDate = new Date(today);
1721
+ startDate.setDate(startDate.getDate() - 1);
1722
+ endDate = new Date(startDate);
1723
+ break;
1724
+ case 'esta-semana':
1725
+ startDate = this.getStartOfWeek(today);
1726
+ endDate = new Date(today);
1727
+ break;
1728
+ case 'semana-pasada':
1729
+ const lastWeekEnd = new Date(this.getStartOfWeek(today));
1730
+ lastWeekEnd.setDate(lastWeekEnd.getDate() - 1);
1731
+ startDate = this.getStartOfWeek(lastWeekEnd);
1732
+ endDate = lastWeekEnd;
1733
+ break;
1734
+ case 'este-mes':
1735
+ startDate = new Date(today.getFullYear(), today.getMonth(), 1);
1736
+ endDate = new Date(today);
1737
+ break;
1738
+ case 'mes-pasado':
1739
+ startDate = new Date(today.getFullYear(), today.getMonth() - 1, 1);
1740
+ endDate = new Date(today.getFullYear(), today.getMonth(), 0);
1741
+ break;
1742
+ case 'este-ano':
1743
+ startDate = new Date(today.getFullYear(), 0, 1);
1744
+ endDate = new Date(today);
1745
+ break;
1746
+ case 'ano-pasado':
1747
+ startDate = new Date(today.getFullYear() - 1, 0, 1);
1748
+ endDate = new Date(today.getFullYear() - 1, 11, 31);
1749
+ break;
1750
+ case 'mostrar-todo':
1751
+ startDate = null;
1752
+ endDate = null;
1753
+ break;
1754
+ }
1755
+ this.tempStartDate = startDate;
1756
+ this.tempEndDate = endDate;
1757
+ if (startDate) {
1758
+ this.leftMonthDate = new Date(startDate.getFullYear(), startDate.getMonth(), 1);
1759
+ this.rightMonthDate = new Date(startDate.getFullYear(), startDate.getMonth() + 1, 1);
1760
+ }
1761
+ else {
1762
+ const currentDate = new Date();
1763
+ this.leftMonthDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
1764
+ this.rightMonthDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1);
1765
+ }
1766
+ }
1767
+ getStartOfWeek(date) {
1768
+ const day = date.getDay();
1769
+ const diff = day === 0 ? -6 : 1 - day;
1770
+ const startOfWeek = new Date(date);
1771
+ startOfWeek.setDate(date.getDate() + diff);
1772
+ return startOfWeek;
1773
+ }
1774
+ cancel() {
1775
+ if (this.rangeMode) {
1776
+ this.tempStartDate = this.rangeValue.startDate;
1777
+ this.tempEndDate = this.rangeValue.endDate;
1778
+ }
1779
+ else {
1780
+ this.tempSingleDate = this.singleValue;
1781
+ }
1782
+ this.selectedFilter = '';
1783
+ this.leftMonthDate = new Date(this.originalLeftMonthDate);
1784
+ this.rightMonthDate = new Date(this.originalRightMonthDate);
1785
+ this.updateCalendarDays();
1786
+ this.closeDropdown();
1787
+ }
1788
+ apply() {
1789
+ if (this.rangeMode) {
1790
+ this.rangeValue = {
1791
+ startDate: this.tempStartDate,
1792
+ endDate: this.tempEndDate
1793
+ };
1794
+ this.onChange(this.rangeValue);
1795
+ }
1796
+ else {
1797
+ this.singleValue = this.tempSingleDate;
1798
+ this.onChange(this.singleValue);
1799
+ }
1800
+ this.originalLeftMonthDate = new Date(this.leftMonthDate);
1801
+ this.originalRightMonthDate = new Date(this.rightMonthDate);
1802
+ this.onTouched();
1803
+ this.removeRepositionListeners();
1804
+ this.isOpen = false;
1805
+ this.hoverDate = null;
1806
+ this.showLeftMonthPicker = false;
1807
+ this.showRightMonthPicker = false;
1808
+ }
1809
+ getStartDateDisplay() {
1810
+ if (this.tempStartDate) {
1811
+ return this.formatDateForInput(this.tempStartDate);
1812
+ }
1813
+ return 'Fecha inicio';
1814
+ }
1815
+ getEndDateDisplay() {
1816
+ if (this.tempEndDate) {
1817
+ return this.formatDateForInput(this.tempEndDate);
1818
+ }
1819
+ return 'Fecha fin';
1820
+ }
1821
+ formatDateForInput(date) {
1822
+ const day = date.getDate();
1823
+ const month = date.toLocaleString('es-ES', { month: 'short' });
1824
+ const year = date.getFullYear();
1825
+ return `${day} ${month} ${year}`;
1826
+ }
1827
+ toggleLeftMonthPicker(event) {
1828
+ event.stopPropagation();
1829
+ this.showLeftMonthPicker = !this.showLeftMonthPicker;
1830
+ this.showRightMonthPicker = false;
1831
+ if (this.showLeftMonthPicker) {
1832
+ this.leftYearPickerPage = 0;
1833
+ }
1834
+ }
1835
+ toggleRightMonthPicker(event) {
1836
+ event.stopPropagation();
1837
+ this.showRightMonthPicker = !this.showRightMonthPicker;
1838
+ this.showLeftMonthPicker = false;
1839
+ if (this.showRightMonthPicker) {
1840
+ this.rightYearPickerPage = 0;
1841
+ }
1842
+ }
1843
+ getLeftYears() {
1844
+ const currentYear = this.leftMonthDate.getFullYear();
1845
+ const baseYear = currentYear + (this.leftYearPickerPage * this.yearsPerPage);
1846
+ const years = [];
1847
+ for (let i = 0; i < this.yearsPerPage; i++) {
1848
+ const year = baseYear - 5 + i;
1849
+ years.push(year);
1850
+ }
1851
+ return years;
1852
+ }
1853
+ getRightYears() {
1854
+ const currentYear = this.rightMonthDate.getFullYear();
1855
+ const baseYear = currentYear + (this.rightYearPickerPage * this.yearsPerPage);
1856
+ const years = [];
1857
+ for (let i = 0; i < this.yearsPerPage; i++) {
1858
+ const year = baseYear - 5 + i;
1859
+ years.push(year);
1860
+ }
1861
+ return years;
1862
+ }
1863
+ previousLeftYearPage(event) {
1864
+ event.stopPropagation();
1865
+ this.leftYearPickerPage--;
1866
+ }
1867
+ nextLeftYearPage(event) {
1868
+ event.stopPropagation();
1869
+ this.leftYearPickerPage++;
1870
+ }
1871
+ previousRightYearPage(event) {
1872
+ event.stopPropagation();
1873
+ this.rightYearPickerPage--;
1874
+ }
1875
+ nextRightYearPage(event) {
1876
+ event.stopPropagation();
1877
+ this.rightYearPickerPage++;
1878
+ }
1879
+ isMonthDisabled(monthIndex, calendarDate) {
1880
+ const testDate = new Date(calendarDate.getFullYear(), monthIndex, 1);
1881
+ if (this.minDate) {
1882
+ const minDateMonth = new Date(this.minDate.getFullYear(), this.minDate.getMonth(), 1);
1883
+ if (testDate < minDateMonth)
1884
+ return true;
1885
+ }
1886
+ if (this.maxDate) {
1887
+ const maxDateMonth = new Date(this.maxDate.getFullYear(), this.maxDate.getMonth(), 1);
1888
+ if (testDate > maxDateMonth)
1889
+ return true;
1890
+ }
1891
+ return false;
1892
+ }
1893
+ isYearDisabled(year) {
1894
+ if (this.minDate && year < this.minDate.getFullYear())
1895
+ return true;
1896
+ if (this.maxDate && year > this.maxDate.getFullYear())
1897
+ return true;
1898
+ return false;
1899
+ }
1900
+ getLeftYearRangeLabel() {
1901
+ const years = this.getLeftYears();
1902
+ return `${years[0]} - ${years[years.length - 1]}`;
1903
+ }
1904
+ getRightYearRangeLabel() {
1905
+ const years = this.getRightYears();
1906
+ return `${years[0]} - ${years[years.length - 1]}`;
1907
+ }
1908
+ canNavigateLeftYearsPrevious() {
1909
+ if (!this.minDate && !this.maxDate)
1910
+ return true;
1911
+ const currentYear = this.leftMonthDate.getFullYear();
1912
+ const baseYear = currentYear + ((this.leftYearPickerPage - 1) * this.yearsPerPage);
1913
+ const previousPageYears = [];
1914
+ for (let i = 0; i < this.yearsPerPage; i++) {
1915
+ previousPageYears.push(baseYear - 5 + i);
1916
+ }
1917
+ return previousPageYears.some(year => !this.isYearDisabled(year));
1918
+ }
1919
+ canNavigateLeftYearsNext() {
1920
+ if (!this.minDate && !this.maxDate)
1921
+ return true;
1922
+ const currentYear = this.leftMonthDate.getFullYear();
1923
+ const baseYear = currentYear + ((this.leftYearPickerPage + 1) * this.yearsPerPage);
1924
+ const nextPageYears = [];
1925
+ for (let i = 0; i < this.yearsPerPage; i++) {
1926
+ nextPageYears.push(baseYear - 5 + i);
1927
+ }
1928
+ return nextPageYears.some(year => !this.isYearDisabled(year));
1929
+ }
1930
+ canNavigateRightYearsPrevious() {
1931
+ if (!this.minDate && !this.maxDate)
1932
+ return true;
1933
+ const currentYear = this.rightMonthDate.getFullYear();
1934
+ const baseYear = currentYear + ((this.rightYearPickerPage - 1) * this.yearsPerPage);
1935
+ const previousPageYears = [];
1936
+ for (let i = 0; i < this.yearsPerPage; i++) {
1937
+ previousPageYears.push(baseYear - 5 + i);
1938
+ }
1939
+ return previousPageYears.some(year => !this.isYearDisabled(year));
1940
+ }
1941
+ canNavigateRightYearsNext() {
1942
+ if (!this.minDate && !this.maxDate)
1943
+ return true;
1944
+ const currentYear = this.rightMonthDate.getFullYear();
1945
+ const baseYear = currentYear + ((this.rightYearPickerPage + 1) * this.yearsPerPage);
1946
+ const nextPageYears = [];
1947
+ for (let i = 0; i < this.yearsPerPage; i++) {
1948
+ nextPageYears.push(baseYear - 5 + i);
1949
+ }
1950
+ return nextPageYears.some(year => !this.isYearDisabled(year));
1951
+ }
1952
+ selectLeftMonth(monthIndex, event) {
1953
+ if (event) {
1954
+ event.stopPropagation();
1955
+ }
1956
+ this.leftMonthDate = new Date(this.leftMonthDate.getFullYear(), monthIndex, 1);
1957
+ if (this.rangeMode) {
1958
+ this.rightMonthDate = new Date(this.leftMonthDate.getFullYear(), monthIndex + 1, 1);
1959
+ }
1960
+ this.updateCalendarDays();
1961
+ this.showLeftMonthPicker = false;
1962
+ }
1963
+ selectRightMonth(monthIndex, event) {
1964
+ if (event) {
1965
+ event.stopPropagation();
1966
+ }
1967
+ this.rightMonthDate = new Date(this.rightMonthDate.getFullYear(), monthIndex, 1);
1968
+ this.leftMonthDate = new Date(this.rightMonthDate.getFullYear(), monthIndex - 1, 1);
1969
+ this.updateCalendarDays();
1970
+ this.showRightMonthPicker = false;
1971
+ }
1972
+ selectLeftYear(year, event) {
1973
+ if (event) {
1974
+ event.stopPropagation();
1975
+ }
1976
+ this.leftMonthDate = new Date(year, this.leftMonthDate.getMonth(), 1);
1977
+ if (this.rangeMode) {
1978
+ this.rightMonthDate = new Date(year, this.leftMonthDate.getMonth() + 1, 1);
1979
+ }
1980
+ this.updateCalendarDays();
1981
+ this.showLeftMonthPicker = false;
1982
+ }
1983
+ selectRightYear(year, event) {
1984
+ if (event) {
1985
+ event.stopPropagation();
1986
+ }
1987
+ this.rightMonthDate = new Date(year, this.rightMonthDate.getMonth(), 1);
1988
+ this.leftMonthDate = new Date(year, this.rightMonthDate.getMonth() - 1, 1);
1989
+ this.updateCalendarDays();
1990
+ this.showRightMonthPicker = false;
1991
+ }
1992
+ writeValue(value) {
1993
+ if (this.rangeMode) {
1994
+ const rangeVal = value;
1995
+ this.rangeValue = rangeVal || { startDate: null, endDate: null };
1996
+ this.tempStartDate = this.rangeValue.startDate;
1997
+ this.tempEndDate = this.rangeValue.endDate;
1998
+ }
1999
+ else {
2000
+ this.singleValue = value;
2001
+ this.tempSingleDate = this.singleValue;
2002
+ }
2003
+ }
2004
+ registerOnChange(fn) {
2005
+ this.onChange = fn;
2006
+ }
2007
+ registerOnTouched(fn) {
2008
+ this.onTouched = fn;
2009
+ }
2010
+ setDisabledState(isDisabled) {
2011
+ this.disabled = isDisabled;
2012
+ }
2013
+ resetDatePicker() {
2014
+ if (this.rangeMode) {
2015
+ this.rangeValue = { startDate: null, endDate: null };
2016
+ this.tempStartDate = null;
2017
+ this.tempEndDate = null;
2018
+ this.onChange(this.rangeValue);
2019
+ }
2020
+ else {
2021
+ this.singleValue = null;
2022
+ this.tempSingleDate = null;
2023
+ this.onChange(this.singleValue);
2024
+ }
2025
+ this.selectedFilter = '';
2026
+ this.initializeDates();
2027
+ this.updateCalendarDays();
2028
+ }
2029
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DatePickerComponent, deps: [{ token: i0.Renderer2 }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component });
2030
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: DatePickerComponent, isStandalone: true, selector: "app-date-picker", inputs: { label: "label", id: "id", placeholder: "placeholder", hasError: "hasError", errorMessage: "errorMessage", disabled: "disabled", minDate: "minDate", maxDate: "maxDate", rangeMode: "rangeMode", iconPosition: "iconPosition" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
2031
+ {
2032
+ provide: NG_VALUE_ACCESSOR,
2033
+ useExisting: forwardRef(() => DatePickerComponent),
2034
+ multi: true
2035
+ }
2036
+ ], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, read: ElementRef }, { propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"date-picker-wrapper\">\n <label *ngIf=\"label\" [for]=\"id\">{{ label }}</label>\n\n <div class=\"date-picker-container\">\n <div\n #trigger\n class=\"date-picker-input\"\n [class.error]=\"hasError\"\n [class.disabled]=\"disabled\"\n [class.open]=\"isOpen\"\n [class.icon-right]=\"iconPosition === 'right'\"\n (click)=\"toggleDropdown($event)\">\n\n <svg *ngIf=\"iconPosition === 'left'\" class=\"calendar-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.66667 1.66667V4.16667M13.3333 1.66667V4.16667M2.5 7.5H17.5M4.16667 3.33333H15.8333C16.7538 3.33333 17.5 4.07953 17.5 5V16.6667C17.5 17.5871 16.7538 18.3333 15.8333 18.3333H4.16667C3.24619 18.3333 2.5 17.5871 2.5 16.6667V5C2.5 4.07953 3.24619 3.33333 4.16667 3.33333Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n\n <span class=\"date-picker-placeholder\" *ngIf=\"!getDisplayValue()\">\n {{ placeholder }}\n </span>\n <span class=\"date-picker-value\" *ngIf=\"getDisplayValue()\">\n {{ getDisplayValue() }}\n </span>\n\n <svg *ngIf=\"iconPosition === 'right'\" class=\"calendar-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.66667 1.66667V4.16667M13.3333 1.66667V4.16667M2.5 7.5H17.5M4.16667 3.33333H15.8333C16.7538 3.33333 17.5 4.07953 17.5 5V16.6667C17.5 17.5871 16.7538 18.3333 15.8333 18.3333H4.16667C3.24619 18.3333 2.5 17.5871 2.5 16.6667V5C2.5 4.07953 3.24619 3.33333 4.16667 3.33333Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </div>\n\n <div *ngIf=\"hasError && errorMessage\" class=\"field-error\">\n {{ errorMessage }}\n </div>\n</div>\n\n<!-- Dropdown content (rendered with fixed position) -->\n<div *ngIf=\"isOpen\" class=\"date-picker-overlay\">\n <div #dropdown class=\"date-picker-dropdown\" [class.open]=\"isOpen\" [class.range-mode]=\"rangeMode\" [ngStyle]=\"getDropdownStyle()\">\n <div class=\"date-picker-content\">\n <!-- Sidebar with filters (only for range mode) -->\n <div class=\"filter-sidebar\" *ngIf=\"rangeMode\">\n <div\n *ngFor=\"let option of filterOptions\"\n class=\"filter-option\"\n [class.active]=\"selectedFilter === option.value\"\n (click)=\"selectFilter(option.value)\">\n {{ option.label }}\n </div>\n </div>\n\n <!-- Main content (calendars + footer) -->\n <div class=\"date-picker-main\">\n <!-- Calendars -->\n <div class=\"calendars-container\">\n <!-- Left Calendar (or single calendar in single mode) -->\n <div class=\"calendar\">\n <div class=\"calendar-header\">\n <button\n type=\"button\"\n class=\"nav-button\"\n [disabled]=\"!canNavigatePreviousMonth()\"\n [class.disabled]=\"!canNavigatePreviousMonth()\"\n (click)=\"previousMonth()\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7.5 2L3.5 6L7.5 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <div class=\"month-year-selector\">\n <button type=\"button\" class=\"month-year\" (click)=\"toggleLeftMonthPicker($event)\">\n {{ getMonthYear(leftMonthDate) }}\n </button>\n\n <!-- Month/Year Picker Dropdown -->\n <div class=\"month-year-picker\" *ngIf=\"showLeftMonthPicker\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-section\">\n <div class=\"picker-title\">Mes</div>\n <div class=\"months-grid\">\n <button\n type=\"button\"\n *ngFor=\"let month of months; let i = index\"\n class=\"month-option\"\n [class.active]=\"i === leftMonthDate.getMonth()\"\n [class.disabled]=\"isMonthDisabled(i, leftMonthDate)\"\n [disabled]=\"isMonthDisabled(i, leftMonthDate)\"\n (click)=\"selectLeftMonth(i, $event)\">\n {{ month.substring(0, 3) }}\n </button>\n </div>\n </div>\n <div class=\"picker-section\">\n <div class=\"picker-header\">\n <button\n type=\"button\"\n class=\"year-nav-button\"\n [disabled]=\"!canNavigateLeftYearsPrevious()\"\n [class.disabled]=\"!canNavigateLeftYearsPrevious()\"\n (click)=\"previousLeftYearPage($event)\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.25 2.5L3.75 5L6.25 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <div class=\"picker-title\">{{ getLeftYearRangeLabel() }}</div>\n <button\n type=\"button\"\n class=\"year-nav-button\"\n [disabled]=\"!canNavigateLeftYearsNext()\"\n [class.disabled]=\"!canNavigateLeftYearsNext()\"\n (click)=\"nextLeftYearPage($event)\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3.75 2.5L6.25 5L3.75 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n <div class=\"years-grid\">\n <button\n type=\"button\"\n *ngFor=\"let year of getLeftYears()\"\n class=\"year-option\"\n [class.active]=\"year === leftMonthDate.getFullYear()\"\n [class.disabled]=\"isYearDisabled(year)\"\n [disabled]=\"isYearDisabled(year)\"\n (click)=\"selectLeftYear(year, $event)\">\n {{ year }}\n </button>\n </div>\n </div>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"nav-button\"\n [disabled]=\"!canNavigateNextMonth()\"\n [class.disabled]=\"!canNavigateNextMonth()\"\n (click)=\"nextMonth()\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.5 2L8.5 6L4.5 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"calendar-grid\">\n <div class=\"weekday-header\" *ngFor=\"let day of weekDays\">\n {{ day }}\n </div>\n\n <div\n *ngFor=\"let day of leftCalendarDays; trackBy: trackByDate\"\n class=\"calendar-day\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.in-range]=\"rangeMode && isInRange(day.date)\"\n [class.range-start]=\"day.isRangeStart\"\n [class.range-end]=\"day.isRangeEnd\"\n [class.disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n <span>{{ day.date.getDate() }}</span>\n </div>\n </div>\n </div>\n\n <!-- Right Calendar (only for range mode) -->\n <div class=\"calendar\" *ngIf=\"rangeMode\">\n <div class=\"calendar-header\">\n <div class=\"nav-button-placeholder\"></div>\n <div class=\"month-year-selector\">\n <button type=\"button\" class=\"month-year\" (click)=\"toggleRightMonthPicker($event)\">\n {{ getMonthYear(rightMonthDate) }}\n </button>\n\n <!-- Month/Year Picker Dropdown -->\n <div class=\"month-year-picker\" *ngIf=\"showRightMonthPicker\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-section\">\n <div class=\"picker-title\">Mes</div>\n <div class=\"months-grid\">\n <button\n type=\"button\"\n *ngFor=\"let month of months; let i = index\"\n class=\"month-option\"\n [class.active]=\"i === rightMonthDate.getMonth()\"\n [class.disabled]=\"isMonthDisabled(i, rightMonthDate)\"\n [disabled]=\"isMonthDisabled(i, rightMonthDate)\"\n (click)=\"selectRightMonth(i, $event)\">\n {{ month.substring(0, 3) }}\n </button>\n </div>\n </div>\n <div class=\"picker-section\">\n <div class=\"picker-header\">\n <button\n type=\"button\"\n class=\"year-nav-button\"\n [disabled]=\"!canNavigateRightYearsPrevious()\"\n [class.disabled]=\"!canNavigateRightYearsPrevious()\"\n (click)=\"previousRightYearPage($event)\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.25 2.5L3.75 5L6.25 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <div class=\"picker-title\">{{ getRightYearRangeLabel() }}</div>\n <button\n type=\"button\"\n class=\"year-nav-button\"\n [disabled]=\"!canNavigateRightYearsNext()\"\n [class.disabled]=\"!canNavigateRightYearsNext()\"\n (click)=\"nextRightYearPage($event)\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3.75 2.5L6.25 5L3.75 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n <div class=\"years-grid\">\n <button\n type=\"button\"\n *ngFor=\"let year of getRightYears()\"\n class=\"year-option\"\n [class.active]=\"year === rightMonthDate.getFullYear()\"\n [class.disabled]=\"isYearDisabled(year)\"\n [disabled]=\"isYearDisabled(year)\"\n (click)=\"selectRightYear(year, $event)\">\n {{ year }}\n </button>\n </div>\n </div>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"nav-button\"\n [disabled]=\"!canNavigateNextMonth()\"\n [class.disabled]=\"!canNavigateNextMonth()\"\n (click)=\"nextMonth()\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.5 2L8.5 6L4.5 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"calendar-grid\">\n <div class=\"weekday-header\" *ngFor=\"let day of weekDays\">\n {{ day }}\n </div>\n\n <div\n *ngFor=\"let day of rightCalendarDays; trackBy: trackByDate\"\n class=\"calendar-day\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.in-range]=\"isInRange(day.date)\"\n [class.range-start]=\"day.isRangeStart\"\n [class.range-end]=\"day.isRangeEnd\"\n [class.disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n <span>{{ day.date.getDate() }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Footer with dates and actions (only for range mode) -->\n <div class=\"footer\" *ngIf=\"rangeMode\">\n <div class=\"selected-dates\">\n <div class=\"date-display\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.33333 1.33333V3.33333M10.6667 1.33333V3.33333M2 6H14M3.33333 2.66667H12.6667C13.403 2.66667 14 3.26362 14 4V13.3333C14 14.0697 13.403 14.6667 12.6667 14.6667H3.33333C2.59695 14.6667 2 14.0697 2 13.3333V4C2 3.26362 2.59695 2.66667 3.33333 2.66667Z\" stroke=\"#6B7280\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"date-text\">{{ getStartDateDisplay() }}</span>\n </div>\n <span class=\"date-separator\">-</span>\n <div class=\"date-display\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.33333 1.33333V3.33333M10.6667 1.33333V3.33333M2 6H14M3.33333 2.66667H12.6667C13.403 2.66667 14 3.26362 14 4V13.3333C14 14.0697 13.403 14.6667 12.6667 14.6667H3.33333C2.59695 14.6667 2 14.0697 2 13.3333V4C2 3.26362 2.59695 2.66667 3.33333 2.66667Z\" stroke=\"#6B7280\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"date-text\">{{ getEndDateDisplay() }}</span>\n </div>\n </div>\n\n <div class=\"action-buttons\">\n <button type=\"button\" class=\"btn-cancel\" (click)=\"cancel()\">\n Cancelar\n </button>\n <button type=\"button\" class=\"btn-apply\" (click)=\"apply()\">\n Aplicar\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".date-picker-wrapper{display:flex;flex-direction:column;width:100%;margin-bottom:6px;padding:0 4px}.date-picker-wrapper label{display:block;margin-bottom:.5rem;font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;color:#585d61}.date-picker-container{position:relative;width:100%}.date-picker-input{display:flex;align-items:center;gap:.5rem;width:100%;min-height:44px;height:44px;padding:0 .75rem;border:1px solid #EAECF5;box-shadow:0 1px 2px #a1afec66;border-radius:8px;background:#fff;cursor:pointer;transition:all .2s ease;font-family:Quicksand,sans-serif}.date-picker-input:hover:not(.disabled){border-color:#fbd399}.date-picker-input.open{border-color:#fbd399;box-shadow:0 0 0 4px #ffe8c8,0 1px 2px #0a0d120d}.date-picker-input.error{border-color:#f04438}.date-picker-input.disabled{background:#f9fafb;cursor:not-allowed;opacity:.6}.date-picker-input .calendar-icon{color:#a4a7ae;flex-shrink:0}.date-picker-input .date-picker-placeholder{color:#a4a7ae;font-size:14px;flex:1}.date-picker-input .date-picker-value{color:#2e353a;font-size:14px;font-weight:500;flex:1}.field-error{color:#f04438;font-size:.875rem;margin-top:.25rem;font-family:Quicksand,sans-serif}.date-picker-overlay{position:fixed;inset:0;z-index:9999;pointer-events:none}.date-picker-dropdown{pointer-events:all;background:#fff;border-radius:12px;box-shadow:0 10px 40px #00000026;opacity:0;transform:translateY(-10px);transition:all .2s ease;overflow:visible}.date-picker-dropdown.open{opacity:1;transform:translateY(0)}.date-picker-content{display:flex;font-family:Quicksand,sans-serif;overflow:visible}.date-picker-main{display:flex;flex-direction:column;flex:1;overflow:visible}.filter-sidebar{padding:.5rem .8rem;min-width:170px;display:flex;flex-direction:column;border-right:1px solid #F3F4F6}.filter-sidebar .filter-option{font-family:Quicksand,sans-serif;padding:.625rem .8rem;color:#6b7280;cursor:pointer;transition:all .15s ease;white-space:nowrap;position:relative;font-weight:400;font-size:14px}.filter-sidebar .filter-option:hover:not(.active){background:#f9fafb}.filter-sidebar .filter-option.active{background:#fef4e6;color:#f7a733;font-weight:500;border-radius:6px}.calendars-container{display:flex;gap:3rem;padding:1rem;overflow:visible}.date-picker-dropdown:not(.range-mode) .calendars-container{gap:0;justify-content:center}.calendar{display:flex;flex-direction:column;gap:1rem;position:relative;overflow:visible}.calendar .calendar-header{display:flex;align-items:center;justify-content:space-between;padding:0 .25rem;margin-bottom:.5rem;position:relative;overflow:visible}.calendar .calendar-header .month-year-selector{position:relative;flex:1;display:flex;justify-content:center}.calendar .calendar-header .month-year{font-size:.9375rem;font-weight:600;color:#1f2937;min-width:160px;text-align:center;background:transparent;border:none;cursor:pointer;padding:.375rem .5rem;border-radius:6px;transition:all .15s ease}.calendar .calendar-header .month-year:hover{background:#f3f4f6}.calendar .calendar-header .nav-button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;cursor:pointer;color:#6b7280;transition:all .15s ease;padding:0}.calendar .calendar-header .nav-button:hover:not(:disabled):not(.disabled){background:#f3f4f6;color:#1f2937}.calendar .calendar-header .nav-button.disabled,.calendar .calendar-header .nav-button:disabled{color:#d1d5db;cursor:not-allowed;opacity:.4}.calendar .calendar-header .nav-button svg{width:10px;height:10px}.calendar .calendar-header .nav-button-placeholder{width:28px;height:28px}.calendar .month-year-picker{position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:.5rem;background:#fff;border-radius:8px;box-shadow:0 10px 30px #0003;z-index:10002;padding:1rem;min-width:280px;border:1px solid #E5E7EB}.calendar .month-year-picker .picker-section{margin-bottom:1rem}.calendar .month-year-picker .picker-section:last-child{margin-bottom:0}.calendar .month-year-picker .picker-section .picker-title{font-size:.75rem;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.5px;margin-bottom:.5rem}.calendar .month-year-picker .picker-section .picker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.5rem}.calendar .month-year-picker .picker-section .picker-header .picker-title{margin-bottom:0;font-size:.75rem;font-weight:600;color:#1f2937;text-transform:none;letter-spacing:0}.calendar .month-year-picker .picker-section .picker-header .year-nav-button{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;cursor:pointer;color:#6b7280;transition:all .15s ease;padding:0}.calendar .month-year-picker .picker-section .picker-header .year-nav-button:hover:not(:disabled):not(.disabled){background:#f3f4f6;color:#1f2937}.calendar .month-year-picker .picker-section .picker-header .year-nav-button.disabled,.calendar .month-year-picker .picker-section .picker-header .year-nav-button:disabled{color:#d1d5db;cursor:not-allowed;opacity:.5}.calendar .month-year-picker .picker-section .picker-header .year-nav-button svg{width:10px;height:10px}.calendar .month-year-picker .months-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.375rem}.calendar .month-year-picker .months-grid .month-option{padding:.5rem;border:1px solid #E5E7EB;background:#fff;border-radius:6px;font-size:.75rem;font-weight:500;color:#6b7280;cursor:pointer;transition:all .15s ease}.calendar .month-year-picker .months-grid .month-option:hover{background:#f9fafb;border-color:#d1d5db}.calendar .month-year-picker .months-grid .month-option.active{background:#f59100;color:#fff;border-color:#f59100}.calendar .month-year-picker .months-grid .month-option.disabled,.calendar .month-year-picker .months-grid .month-option:disabled{background:#f9fafb;color:#d1d5db;border-color:#e5e7eb;cursor:not-allowed;pointer-events:none}.calendar .month-year-picker .years-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.375rem;max-height:200px;overflow-y:auto}.calendar .month-year-picker .years-grid .year-option{padding:.5rem;border:1px solid #E5E7EB;background:#fff;border-radius:6px;font-size:.75rem;font-weight:500;color:#6b7280;cursor:pointer;transition:all .15s ease}.calendar .month-year-picker .years-grid .year-option:hover{background:#f9fafb;border-color:#d1d5db}.calendar .month-year-picker .years-grid .year-option.active{background:#f59100;color:#fff;border-color:#f59100}.calendar .month-year-picker .years-grid .year-option.disabled,.calendar .month-year-picker .years-grid .year-option:disabled{background:#f9fafb;color:#d1d5db;border-color:#e5e7eb;cursor:not-allowed;pointer-events:none}.calendar .calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px 0}.calendar .calendar-grid .weekday-header{display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:500;color:#9ca3af;padding:.5rem 0;text-transform:uppercase;letter-spacing:.5px}.calendar .calendar-grid .calendar-day{display:flex;align-items:center;justify-content:center;width:36px;height:36px;font-size:.8125rem;color:#1f2937;cursor:pointer;transition:all .15s ease;position:relative;font-weight:400;border-radius:0}.calendar .calendar-grid .calendar-day.other-month{color:#d1d5db}.calendar .calendar-grid .calendar-day.today{font-weight:600;color:#f59100;background:transparent}.calendar .calendar-grid .calendar-day.today:after{content:\"\";position:absolute;bottom:4px;left:50%;transform:translate(-50%);width:4px;height:4px;background:#f59100;border-radius:50%}.calendar .calendar-grid .calendar-day:hover:not(.disabled):not(.selected):not(.range-start):not(.range-end):not(.in-range){background:#fef4e6;border-radius:50%}.calendar .calendar-grid .calendar-day.in-range:hover:not(.disabled):not(.range-start):not(.range-end){position:relative;background:transparent}.calendar .calendar-grid .calendar-day.in-range:hover:not(.disabled):not(.range-start):not(.range-end):before{content:\"\";position:absolute;inset:0;background:#fef4e6;z-index:-1;border-radius:0}.calendar .calendar-grid .calendar-day.in-range:hover:not(.disabled):not(.range-start):not(.range-end):after{content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:100%;height:100%;background:#fef4e6;border-radius:50%;z-index:0}.calendar .calendar-grid .calendar-day.in-range:hover:not(.disabled):not(.range-start):not(.range-end) span{position:relative;z-index:1;color:#f59100}.calendar .calendar-grid .calendar-day.in-range:not(.disabled):not(.range-start):not(.range-end){background:#fef4e6;color:#f59100;border-radius:0}.calendar .calendar-grid .calendar-day.in-range:not(.disabled):not(.range-start):not(.range-end):nth-child(7n+8){border-radius:50% 0 0 50%}.calendar .calendar-grid .calendar-day.in-range:not(.disabled):not(.range-start):not(.range-end):nth-child(7n+14){border-radius:0 50% 50% 0}.calendar .calendar-grid .calendar-day.in-range:not(.disabled):not(.range-start):not(.range-end):nth-child(7n+8):nth-child(7n+14){border-radius:50%}.calendar .calendar-grid .calendar-day.range-start:not(.disabled){position:relative;background:transparent;color:#fff;font-weight:600;z-index:2}.calendar .calendar-grid .calendar-day.range-start:not(.disabled):before{content:\"\";position:absolute;inset:0;background:#fef4e6;z-index:-1;border-radius:50% 0 0 50%}.calendar .calendar-grid .calendar-day.range-start:not(.disabled):after{content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:100%;height:100%;background:#f59100;border-radius:50%;z-index:1}.calendar .calendar-grid .calendar-day.range-start:not(.disabled) span{position:relative;z-index:2}.calendar .calendar-grid .calendar-day.range-start:not(.disabled).range-end:before{border-radius:50%}.calendar .calendar-grid .calendar-day.range-end:not(.disabled){position:relative;background:transparent;color:#fff;font-weight:600;z-index:2}.calendar .calendar-grid .calendar-day.range-end:not(.disabled):before{content:\"\";position:absolute;inset:0;background:#fef4e6;z-index:-1;border-radius:0 50% 50% 0}.calendar .calendar-grid .calendar-day.range-end:not(.disabled):after{content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:100%;height:100%;background:#f59100;border-radius:50%;z-index:1}.calendar .calendar-grid .calendar-day.range-end:not(.disabled) span{position:relative;z-index:2}.calendar .calendar-grid .calendar-day.range-end:not(.disabled).range-start:before{border-radius:50%}.calendar .calendar-grid .calendar-day.range-start.in-range:not(.disabled){position:relative}.calendar .calendar-grid .calendar-day.range-start.in-range:not(.disabled):before{content:\"\";position:absolute;inset:0 -2px 0 50%;background:#fef4e6;z-index:-1}.calendar .calendar-grid .calendar-day.range-end.in-range:not(.disabled){position:relative}.calendar .calendar-grid .calendar-day.range-end.in-range:not(.disabled):before{content:\"\";position:absolute;inset:0 50% 0 -2px;background:#fef4e6;z-index:-1}.calendar .calendar-grid .calendar-day.selected:not(.range-start):not(.range-end){background:#f59100;color:#fff;font-weight:600;border-radius:50%}.calendar .calendar-grid .calendar-day.disabled{color:#e5e7eb;cursor:not-allowed;pointer-events:none}.footer{display:flex;align-items:center;justify-content:space-between;padding:1rem;border-top:1px solid #E5E7EB}.footer .selected-dates{display:flex;align-items:center;gap:.75rem}.footer .selected-dates .date-display{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:#fff;border:1px solid #E5E7EB;border-radius:6px;font-size:.8125rem;color:#6b7280}.footer .selected-dates .date-display svg{flex-shrink:0;color:#9ca3af}.footer .selected-dates .date-display .date-text{font-weight:400;white-space:nowrap;-webkit-user-select:none;user-select:none}.footer .selected-dates .date-separator{color:#9ca3af;font-weight:400;font-size:.875rem}.footer .action-buttons{display:flex;gap:.75rem}.footer .action-buttons button{padding:.625rem 1.75rem;border-radius:8px;font-size:.875rem;font-weight:500;font-family:Quicksand,sans-serif;cursor:pointer;transition:all .15s ease;border:none;outline:none}.footer .action-buttons button:focus-visible{outline:2px solid rgba(245,145,0,.3);outline-offset:2px}.footer .action-buttons .btn-cancel{background:#fff;color:#6b7280;border:1px solid #D1D5DB}.footer .action-buttons .btn-cancel:hover{background:#f9fafb;border-color:#9ca3af}.footer .action-buttons .btn-apply{background:#f59100;color:#fff;border:1px solid #F59100}.footer .action-buttons .btn-apply:hover{background:#e08500;border-color:#e08500}.footer .action-buttons .btn-apply:active{background:#cc7a00;border-color:#cc7a00}@media (max-width: 768px){.date-picker-content{flex-direction:column}.filter-sidebar{display:none}.calendars-container{padding:.75rem;gap:0;justify-content:center}.calendars-container .calendar:last-child:not(:first-child){display:none}.calendar .calendar-header .month-year-selector{flex:1}.calendar .calendar-header .month-year{min-width:auto;font-size:.875rem;padding:.25rem .375rem}.calendar .calendar-header .nav-button{width:28px;height:28px}.calendar .calendar-header .nav-button svg{width:10px;height:10px}.calendar .calendar-header .nav-button-placeholder{display:none}.calendar .month-year-picker{min-width:240px;padding:.75rem}.calendar .month-year-picker .picker-section .picker-title{font-size:.7rem}.calendar .month-year-picker .months-grid{grid-template-columns:repeat(3,1fr);gap:.25rem}.calendar .month-year-picker .months-grid .month-option{padding:.4rem;font-size:.7rem}.calendar .month-year-picker .years-grid{grid-template-columns:repeat(3,1fr);gap:.25rem;max-height:150px}.calendar .month-year-picker .years-grid .year-option{padding:.4rem;font-size:.7rem}.calendar .calendar-grid{gap:2px 0}.calendar .calendar-grid .calendar-day{width:30px;height:30px;font-size:.75rem}.calendar .calendar-grid .weekday-header{font-size:.65rem}.footer{flex-direction:column;gap:.75rem;padding:.75rem}.footer .selected-dates{width:100%;justify-content:center;flex-wrap:wrap;gap:.5rem}.footer .selected-dates .date-display{font-size:.7rem;padding:.35rem .5rem}.footer .selected-dates .date-display svg{width:12px;height:12px}.footer .selected-dates .date-separator{font-size:.7rem}.footer .action-buttons{width:100%;gap:.5rem}.footer .action-buttons button{flex:1;padding:.625rem .75rem;font-size:.75rem}.date-picker-dropdown{width:280px!important;max-width:calc(100vw - 2rem);max-height:calc(100vh - 4rem);overflow-y:auto}.date-picker-dropdown.range-mode{width:280px!important}}@media (max-width: 480px){.calendars-container{padding:.5rem}.calendar .calendar-header .month-year{font-size:.8125rem;padding:.2rem .3rem}.calendar .calendar-header .nav-button{width:26px;height:26px}.calendar .calendar-header .nav-button svg{width:9px;height:9px}.calendar .month-year-picker{min-width:220px;padding:.625rem}.calendar .month-year-picker .picker-section{margin-bottom:.75rem}.calendar .month-year-picker .picker-section .picker-title{font-size:.65rem;margin-bottom:.375rem}.calendar .month-year-picker .months-grid{gap:.2rem}.calendar .month-year-picker .months-grid .month-option{padding:.35rem;font-size:.65rem}.calendar .month-year-picker .years-grid{gap:.2rem;max-height:120px}.calendar .month-year-picker .years-grid .year-option{padding:.35rem;font-size:.65rem}.calendar .calendar-grid{gap:1px 0}.calendar .calendar-grid .weekday-header{font-size:.6rem;padding:.35rem 0}.calendar .calendar-grid .calendar-day{width:28px;height:28px;font-size:.7rem}.footer{padding:.5rem;gap:.5rem}.footer .selected-dates{gap:.4rem}.footer .selected-dates .date-display{font-size:.65rem;padding:.3rem .4rem}.footer .selected-dates .date-display svg{width:11px;height:11px}.footer .selected-dates .date-separator{font-size:.65rem}.footer .action-buttons{gap:.4rem}.footer .action-buttons button{padding:.5rem .625rem;font-size:.7rem}.date-picker-dropdown{width:260px!important;max-width:calc(100vw - 1rem)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] });
2037
+ }
2038
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DatePickerComponent, decorators: [{
2039
+ type: Component,
2040
+ args: [{ selector: 'app-date-picker', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], providers: [
2041
+ {
2042
+ provide: NG_VALUE_ACCESSOR,
2043
+ useExisting: forwardRef(() => DatePickerComponent),
2044
+ multi: true
2045
+ }
2046
+ ], template: "<div class=\"date-picker-wrapper\">\n <label *ngIf=\"label\" [for]=\"id\">{{ label }}</label>\n\n <div class=\"date-picker-container\">\n <div\n #trigger\n class=\"date-picker-input\"\n [class.error]=\"hasError\"\n [class.disabled]=\"disabled\"\n [class.open]=\"isOpen\"\n [class.icon-right]=\"iconPosition === 'right'\"\n (click)=\"toggleDropdown($event)\">\n\n <svg *ngIf=\"iconPosition === 'left'\" class=\"calendar-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.66667 1.66667V4.16667M13.3333 1.66667V4.16667M2.5 7.5H17.5M4.16667 3.33333H15.8333C16.7538 3.33333 17.5 4.07953 17.5 5V16.6667C17.5 17.5871 16.7538 18.3333 15.8333 18.3333H4.16667C3.24619 18.3333 2.5 17.5871 2.5 16.6667V5C2.5 4.07953 3.24619 3.33333 4.16667 3.33333Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n\n <span class=\"date-picker-placeholder\" *ngIf=\"!getDisplayValue()\">\n {{ placeholder }}\n </span>\n <span class=\"date-picker-value\" *ngIf=\"getDisplayValue()\">\n {{ getDisplayValue() }}\n </span>\n\n <svg *ngIf=\"iconPosition === 'right'\" class=\"calendar-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.66667 1.66667V4.16667M13.3333 1.66667V4.16667M2.5 7.5H17.5M4.16667 3.33333H15.8333C16.7538 3.33333 17.5 4.07953 17.5 5V16.6667C17.5 17.5871 16.7538 18.3333 15.8333 18.3333H4.16667C3.24619 18.3333 2.5 17.5871 2.5 16.6667V5C2.5 4.07953 3.24619 3.33333 4.16667 3.33333Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </div>\n\n <div *ngIf=\"hasError && errorMessage\" class=\"field-error\">\n {{ errorMessage }}\n </div>\n</div>\n\n<!-- Dropdown content (rendered with fixed position) -->\n<div *ngIf=\"isOpen\" class=\"date-picker-overlay\">\n <div #dropdown class=\"date-picker-dropdown\" [class.open]=\"isOpen\" [class.range-mode]=\"rangeMode\" [ngStyle]=\"getDropdownStyle()\">\n <div class=\"date-picker-content\">\n <!-- Sidebar with filters (only for range mode) -->\n <div class=\"filter-sidebar\" *ngIf=\"rangeMode\">\n <div\n *ngFor=\"let option of filterOptions\"\n class=\"filter-option\"\n [class.active]=\"selectedFilter === option.value\"\n (click)=\"selectFilter(option.value)\">\n {{ option.label }}\n </div>\n </div>\n\n <!-- Main content (calendars + footer) -->\n <div class=\"date-picker-main\">\n <!-- Calendars -->\n <div class=\"calendars-container\">\n <!-- Left Calendar (or single calendar in single mode) -->\n <div class=\"calendar\">\n <div class=\"calendar-header\">\n <button\n type=\"button\"\n class=\"nav-button\"\n [disabled]=\"!canNavigatePreviousMonth()\"\n [class.disabled]=\"!canNavigatePreviousMonth()\"\n (click)=\"previousMonth()\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7.5 2L3.5 6L7.5 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <div class=\"month-year-selector\">\n <button type=\"button\" class=\"month-year\" (click)=\"toggleLeftMonthPicker($event)\">\n {{ getMonthYear(leftMonthDate) }}\n </button>\n\n <!-- Month/Year Picker Dropdown -->\n <div class=\"month-year-picker\" *ngIf=\"showLeftMonthPicker\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-section\">\n <div class=\"picker-title\">Mes</div>\n <div class=\"months-grid\">\n <button\n type=\"button\"\n *ngFor=\"let month of months; let i = index\"\n class=\"month-option\"\n [class.active]=\"i === leftMonthDate.getMonth()\"\n [class.disabled]=\"isMonthDisabled(i, leftMonthDate)\"\n [disabled]=\"isMonthDisabled(i, leftMonthDate)\"\n (click)=\"selectLeftMonth(i, $event)\">\n {{ month.substring(0, 3) }}\n </button>\n </div>\n </div>\n <div class=\"picker-section\">\n <div class=\"picker-header\">\n <button\n type=\"button\"\n class=\"year-nav-button\"\n [disabled]=\"!canNavigateLeftYearsPrevious()\"\n [class.disabled]=\"!canNavigateLeftYearsPrevious()\"\n (click)=\"previousLeftYearPage($event)\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.25 2.5L3.75 5L6.25 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <div class=\"picker-title\">{{ getLeftYearRangeLabel() }}</div>\n <button\n type=\"button\"\n class=\"year-nav-button\"\n [disabled]=\"!canNavigateLeftYearsNext()\"\n [class.disabled]=\"!canNavigateLeftYearsNext()\"\n (click)=\"nextLeftYearPage($event)\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3.75 2.5L6.25 5L3.75 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n <div class=\"years-grid\">\n <button\n type=\"button\"\n *ngFor=\"let year of getLeftYears()\"\n class=\"year-option\"\n [class.active]=\"year === leftMonthDate.getFullYear()\"\n [class.disabled]=\"isYearDisabled(year)\"\n [disabled]=\"isYearDisabled(year)\"\n (click)=\"selectLeftYear(year, $event)\">\n {{ year }}\n </button>\n </div>\n </div>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"nav-button\"\n [disabled]=\"!canNavigateNextMonth()\"\n [class.disabled]=\"!canNavigateNextMonth()\"\n (click)=\"nextMonth()\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.5 2L8.5 6L4.5 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"calendar-grid\">\n <div class=\"weekday-header\" *ngFor=\"let day of weekDays\">\n {{ day }}\n </div>\n\n <div\n *ngFor=\"let day of leftCalendarDays; trackBy: trackByDate\"\n class=\"calendar-day\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.in-range]=\"rangeMode && isInRange(day.date)\"\n [class.range-start]=\"day.isRangeStart\"\n [class.range-end]=\"day.isRangeEnd\"\n [class.disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n <span>{{ day.date.getDate() }}</span>\n </div>\n </div>\n </div>\n\n <!-- Right Calendar (only for range mode) -->\n <div class=\"calendar\" *ngIf=\"rangeMode\">\n <div class=\"calendar-header\">\n <div class=\"nav-button-placeholder\"></div>\n <div class=\"month-year-selector\">\n <button type=\"button\" class=\"month-year\" (click)=\"toggleRightMonthPicker($event)\">\n {{ getMonthYear(rightMonthDate) }}\n </button>\n\n <!-- Month/Year Picker Dropdown -->\n <div class=\"month-year-picker\" *ngIf=\"showRightMonthPicker\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-section\">\n <div class=\"picker-title\">Mes</div>\n <div class=\"months-grid\">\n <button\n type=\"button\"\n *ngFor=\"let month of months; let i = index\"\n class=\"month-option\"\n [class.active]=\"i === rightMonthDate.getMonth()\"\n [class.disabled]=\"isMonthDisabled(i, rightMonthDate)\"\n [disabled]=\"isMonthDisabled(i, rightMonthDate)\"\n (click)=\"selectRightMonth(i, $event)\">\n {{ month.substring(0, 3) }}\n </button>\n </div>\n </div>\n <div class=\"picker-section\">\n <div class=\"picker-header\">\n <button\n type=\"button\"\n class=\"year-nav-button\"\n [disabled]=\"!canNavigateRightYearsPrevious()\"\n [class.disabled]=\"!canNavigateRightYearsPrevious()\"\n (click)=\"previousRightYearPage($event)\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.25 2.5L3.75 5L6.25 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <div class=\"picker-title\">{{ getRightYearRangeLabel() }}</div>\n <button\n type=\"button\"\n class=\"year-nav-button\"\n [disabled]=\"!canNavigateRightYearsNext()\"\n [class.disabled]=\"!canNavigateRightYearsNext()\"\n (click)=\"nextRightYearPage($event)\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3.75 2.5L6.25 5L3.75 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n <div class=\"years-grid\">\n <button\n type=\"button\"\n *ngFor=\"let year of getRightYears()\"\n class=\"year-option\"\n [class.active]=\"year === rightMonthDate.getFullYear()\"\n [class.disabled]=\"isYearDisabled(year)\"\n [disabled]=\"isYearDisabled(year)\"\n (click)=\"selectRightYear(year, $event)\">\n {{ year }}\n </button>\n </div>\n </div>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"nav-button\"\n [disabled]=\"!canNavigateNextMonth()\"\n [class.disabled]=\"!canNavigateNextMonth()\"\n (click)=\"nextMonth()\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.5 2L8.5 6L4.5 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"calendar-grid\">\n <div class=\"weekday-header\" *ngFor=\"let day of weekDays\">\n {{ day }}\n </div>\n\n <div\n *ngFor=\"let day of rightCalendarDays; trackBy: trackByDate\"\n class=\"calendar-day\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.in-range]=\"isInRange(day.date)\"\n [class.range-start]=\"day.isRangeStart\"\n [class.range-end]=\"day.isRangeEnd\"\n [class.disabled]=\"day.isDisabled\"\n (click)=\"onDayClick(day)\"\n (mouseenter)=\"onDayHover(day)\"\n (mouseleave)=\"onDayLeave()\">\n <span>{{ day.date.getDate() }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Footer with dates and actions (only for range mode) -->\n <div class=\"footer\" *ngIf=\"rangeMode\">\n <div class=\"selected-dates\">\n <div class=\"date-display\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.33333 1.33333V3.33333M10.6667 1.33333V3.33333M2 6H14M3.33333 2.66667H12.6667C13.403 2.66667 14 3.26362 14 4V13.3333C14 14.0697 13.403 14.6667 12.6667 14.6667H3.33333C2.59695 14.6667 2 14.0697 2 13.3333V4C2 3.26362 2.59695 2.66667 3.33333 2.66667Z\" stroke=\"#6B7280\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"date-text\">{{ getStartDateDisplay() }}</span>\n </div>\n <span class=\"date-separator\">-</span>\n <div class=\"date-display\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.33333 1.33333V3.33333M10.6667 1.33333V3.33333M2 6H14M3.33333 2.66667H12.6667C13.403 2.66667 14 3.26362 14 4V13.3333C14 14.0697 13.403 14.6667 12.6667 14.6667H3.33333C2.59695 14.6667 2 14.0697 2 13.3333V4C2 3.26362 2.59695 2.66667 3.33333 2.66667Z\" stroke=\"#6B7280\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"date-text\">{{ getEndDateDisplay() }}</span>\n </div>\n </div>\n\n <div class=\"action-buttons\">\n <button type=\"button\" class=\"btn-cancel\" (click)=\"cancel()\">\n Cancelar\n </button>\n <button type=\"button\" class=\"btn-apply\" (click)=\"apply()\">\n Aplicar\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".date-picker-wrapper{display:flex;flex-direction:column;width:100%;margin-bottom:6px;padding:0 4px}.date-picker-wrapper label{display:block;margin-bottom:.5rem;font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;color:#585d61}.date-picker-container{position:relative;width:100%}.date-picker-input{display:flex;align-items:center;gap:.5rem;width:100%;min-height:44px;height:44px;padding:0 .75rem;border:1px solid #EAECF5;box-shadow:0 1px 2px #a1afec66;border-radius:8px;background:#fff;cursor:pointer;transition:all .2s ease;font-family:Quicksand,sans-serif}.date-picker-input:hover:not(.disabled){border-color:#fbd399}.date-picker-input.open{border-color:#fbd399;box-shadow:0 0 0 4px #ffe8c8,0 1px 2px #0a0d120d}.date-picker-input.error{border-color:#f04438}.date-picker-input.disabled{background:#f9fafb;cursor:not-allowed;opacity:.6}.date-picker-input .calendar-icon{color:#a4a7ae;flex-shrink:0}.date-picker-input .date-picker-placeholder{color:#a4a7ae;font-size:14px;flex:1}.date-picker-input .date-picker-value{color:#2e353a;font-size:14px;font-weight:500;flex:1}.field-error{color:#f04438;font-size:.875rem;margin-top:.25rem;font-family:Quicksand,sans-serif}.date-picker-overlay{position:fixed;inset:0;z-index:9999;pointer-events:none}.date-picker-dropdown{pointer-events:all;background:#fff;border-radius:12px;box-shadow:0 10px 40px #00000026;opacity:0;transform:translateY(-10px);transition:all .2s ease;overflow:visible}.date-picker-dropdown.open{opacity:1;transform:translateY(0)}.date-picker-content{display:flex;font-family:Quicksand,sans-serif;overflow:visible}.date-picker-main{display:flex;flex-direction:column;flex:1;overflow:visible}.filter-sidebar{padding:.5rem .8rem;min-width:170px;display:flex;flex-direction:column;border-right:1px solid #F3F4F6}.filter-sidebar .filter-option{font-family:Quicksand,sans-serif;padding:.625rem .8rem;color:#6b7280;cursor:pointer;transition:all .15s ease;white-space:nowrap;position:relative;font-weight:400;font-size:14px}.filter-sidebar .filter-option:hover:not(.active){background:#f9fafb}.filter-sidebar .filter-option.active{background:#fef4e6;color:#f7a733;font-weight:500;border-radius:6px}.calendars-container{display:flex;gap:3rem;padding:1rem;overflow:visible}.date-picker-dropdown:not(.range-mode) .calendars-container{gap:0;justify-content:center}.calendar{display:flex;flex-direction:column;gap:1rem;position:relative;overflow:visible}.calendar .calendar-header{display:flex;align-items:center;justify-content:space-between;padding:0 .25rem;margin-bottom:.5rem;position:relative;overflow:visible}.calendar .calendar-header .month-year-selector{position:relative;flex:1;display:flex;justify-content:center}.calendar .calendar-header .month-year{font-size:.9375rem;font-weight:600;color:#1f2937;min-width:160px;text-align:center;background:transparent;border:none;cursor:pointer;padding:.375rem .5rem;border-radius:6px;transition:all .15s ease}.calendar .calendar-header .month-year:hover{background:#f3f4f6}.calendar .calendar-header .nav-button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;cursor:pointer;color:#6b7280;transition:all .15s ease;padding:0}.calendar .calendar-header .nav-button:hover:not(:disabled):not(.disabled){background:#f3f4f6;color:#1f2937}.calendar .calendar-header .nav-button.disabled,.calendar .calendar-header .nav-button:disabled{color:#d1d5db;cursor:not-allowed;opacity:.4}.calendar .calendar-header .nav-button svg{width:10px;height:10px}.calendar .calendar-header .nav-button-placeholder{width:28px;height:28px}.calendar .month-year-picker{position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:.5rem;background:#fff;border-radius:8px;box-shadow:0 10px 30px #0003;z-index:10002;padding:1rem;min-width:280px;border:1px solid #E5E7EB}.calendar .month-year-picker .picker-section{margin-bottom:1rem}.calendar .month-year-picker .picker-section:last-child{margin-bottom:0}.calendar .month-year-picker .picker-section .picker-title{font-size:.75rem;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.5px;margin-bottom:.5rem}.calendar .month-year-picker .picker-section .picker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.5rem}.calendar .month-year-picker .picker-section .picker-header .picker-title{margin-bottom:0;font-size:.75rem;font-weight:600;color:#1f2937;text-transform:none;letter-spacing:0}.calendar .month-year-picker .picker-section .picker-header .year-nav-button{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;cursor:pointer;color:#6b7280;transition:all .15s ease;padding:0}.calendar .month-year-picker .picker-section .picker-header .year-nav-button:hover:not(:disabled):not(.disabled){background:#f3f4f6;color:#1f2937}.calendar .month-year-picker .picker-section .picker-header .year-nav-button.disabled,.calendar .month-year-picker .picker-section .picker-header .year-nav-button:disabled{color:#d1d5db;cursor:not-allowed;opacity:.5}.calendar .month-year-picker .picker-section .picker-header .year-nav-button svg{width:10px;height:10px}.calendar .month-year-picker .months-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.375rem}.calendar .month-year-picker .months-grid .month-option{padding:.5rem;border:1px solid #E5E7EB;background:#fff;border-radius:6px;font-size:.75rem;font-weight:500;color:#6b7280;cursor:pointer;transition:all .15s ease}.calendar .month-year-picker .months-grid .month-option:hover{background:#f9fafb;border-color:#d1d5db}.calendar .month-year-picker .months-grid .month-option.active{background:#f59100;color:#fff;border-color:#f59100}.calendar .month-year-picker .months-grid .month-option.disabled,.calendar .month-year-picker .months-grid .month-option:disabled{background:#f9fafb;color:#d1d5db;border-color:#e5e7eb;cursor:not-allowed;pointer-events:none}.calendar .month-year-picker .years-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.375rem;max-height:200px;overflow-y:auto}.calendar .month-year-picker .years-grid .year-option{padding:.5rem;border:1px solid #E5E7EB;background:#fff;border-radius:6px;font-size:.75rem;font-weight:500;color:#6b7280;cursor:pointer;transition:all .15s ease}.calendar .month-year-picker .years-grid .year-option:hover{background:#f9fafb;border-color:#d1d5db}.calendar .month-year-picker .years-grid .year-option.active{background:#f59100;color:#fff;border-color:#f59100}.calendar .month-year-picker .years-grid .year-option.disabled,.calendar .month-year-picker .years-grid .year-option:disabled{background:#f9fafb;color:#d1d5db;border-color:#e5e7eb;cursor:not-allowed;pointer-events:none}.calendar .calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px 0}.calendar .calendar-grid .weekday-header{display:flex;align-items:center;justify-content:center;font-size:.6875rem;font-weight:500;color:#9ca3af;padding:.5rem 0;text-transform:uppercase;letter-spacing:.5px}.calendar .calendar-grid .calendar-day{display:flex;align-items:center;justify-content:center;width:36px;height:36px;font-size:.8125rem;color:#1f2937;cursor:pointer;transition:all .15s ease;position:relative;font-weight:400;border-radius:0}.calendar .calendar-grid .calendar-day.other-month{color:#d1d5db}.calendar .calendar-grid .calendar-day.today{font-weight:600;color:#f59100;background:transparent}.calendar .calendar-grid .calendar-day.today:after{content:\"\";position:absolute;bottom:4px;left:50%;transform:translate(-50%);width:4px;height:4px;background:#f59100;border-radius:50%}.calendar .calendar-grid .calendar-day:hover:not(.disabled):not(.selected):not(.range-start):not(.range-end):not(.in-range){background:#fef4e6;border-radius:50%}.calendar .calendar-grid .calendar-day.in-range:hover:not(.disabled):not(.range-start):not(.range-end){position:relative;background:transparent}.calendar .calendar-grid .calendar-day.in-range:hover:not(.disabled):not(.range-start):not(.range-end):before{content:\"\";position:absolute;inset:0;background:#fef4e6;z-index:-1;border-radius:0}.calendar .calendar-grid .calendar-day.in-range:hover:not(.disabled):not(.range-start):not(.range-end):after{content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:100%;height:100%;background:#fef4e6;border-radius:50%;z-index:0}.calendar .calendar-grid .calendar-day.in-range:hover:not(.disabled):not(.range-start):not(.range-end) span{position:relative;z-index:1;color:#f59100}.calendar .calendar-grid .calendar-day.in-range:not(.disabled):not(.range-start):not(.range-end){background:#fef4e6;color:#f59100;border-radius:0}.calendar .calendar-grid .calendar-day.in-range:not(.disabled):not(.range-start):not(.range-end):nth-child(7n+8){border-radius:50% 0 0 50%}.calendar .calendar-grid .calendar-day.in-range:not(.disabled):not(.range-start):not(.range-end):nth-child(7n+14){border-radius:0 50% 50% 0}.calendar .calendar-grid .calendar-day.in-range:not(.disabled):not(.range-start):not(.range-end):nth-child(7n+8):nth-child(7n+14){border-radius:50%}.calendar .calendar-grid .calendar-day.range-start:not(.disabled){position:relative;background:transparent;color:#fff;font-weight:600;z-index:2}.calendar .calendar-grid .calendar-day.range-start:not(.disabled):before{content:\"\";position:absolute;inset:0;background:#fef4e6;z-index:-1;border-radius:50% 0 0 50%}.calendar .calendar-grid .calendar-day.range-start:not(.disabled):after{content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:100%;height:100%;background:#f59100;border-radius:50%;z-index:1}.calendar .calendar-grid .calendar-day.range-start:not(.disabled) span{position:relative;z-index:2}.calendar .calendar-grid .calendar-day.range-start:not(.disabled).range-end:before{border-radius:50%}.calendar .calendar-grid .calendar-day.range-end:not(.disabled){position:relative;background:transparent;color:#fff;font-weight:600;z-index:2}.calendar .calendar-grid .calendar-day.range-end:not(.disabled):before{content:\"\";position:absolute;inset:0;background:#fef4e6;z-index:-1;border-radius:0 50% 50% 0}.calendar .calendar-grid .calendar-day.range-end:not(.disabled):after{content:\"\";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:100%;height:100%;background:#f59100;border-radius:50%;z-index:1}.calendar .calendar-grid .calendar-day.range-end:not(.disabled) span{position:relative;z-index:2}.calendar .calendar-grid .calendar-day.range-end:not(.disabled).range-start:before{border-radius:50%}.calendar .calendar-grid .calendar-day.range-start.in-range:not(.disabled){position:relative}.calendar .calendar-grid .calendar-day.range-start.in-range:not(.disabled):before{content:\"\";position:absolute;inset:0 -2px 0 50%;background:#fef4e6;z-index:-1}.calendar .calendar-grid .calendar-day.range-end.in-range:not(.disabled){position:relative}.calendar .calendar-grid .calendar-day.range-end.in-range:not(.disabled):before{content:\"\";position:absolute;inset:0 50% 0 -2px;background:#fef4e6;z-index:-1}.calendar .calendar-grid .calendar-day.selected:not(.range-start):not(.range-end){background:#f59100;color:#fff;font-weight:600;border-radius:50%}.calendar .calendar-grid .calendar-day.disabled{color:#e5e7eb;cursor:not-allowed;pointer-events:none}.footer{display:flex;align-items:center;justify-content:space-between;padding:1rem;border-top:1px solid #E5E7EB}.footer .selected-dates{display:flex;align-items:center;gap:.75rem}.footer .selected-dates .date-display{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:#fff;border:1px solid #E5E7EB;border-radius:6px;font-size:.8125rem;color:#6b7280}.footer .selected-dates .date-display svg{flex-shrink:0;color:#9ca3af}.footer .selected-dates .date-display .date-text{font-weight:400;white-space:nowrap;-webkit-user-select:none;user-select:none}.footer .selected-dates .date-separator{color:#9ca3af;font-weight:400;font-size:.875rem}.footer .action-buttons{display:flex;gap:.75rem}.footer .action-buttons button{padding:.625rem 1.75rem;border-radius:8px;font-size:.875rem;font-weight:500;font-family:Quicksand,sans-serif;cursor:pointer;transition:all .15s ease;border:none;outline:none}.footer .action-buttons button:focus-visible{outline:2px solid rgba(245,145,0,.3);outline-offset:2px}.footer .action-buttons .btn-cancel{background:#fff;color:#6b7280;border:1px solid #D1D5DB}.footer .action-buttons .btn-cancel:hover{background:#f9fafb;border-color:#9ca3af}.footer .action-buttons .btn-apply{background:#f59100;color:#fff;border:1px solid #F59100}.footer .action-buttons .btn-apply:hover{background:#e08500;border-color:#e08500}.footer .action-buttons .btn-apply:active{background:#cc7a00;border-color:#cc7a00}@media (max-width: 768px){.date-picker-content{flex-direction:column}.filter-sidebar{display:none}.calendars-container{padding:.75rem;gap:0;justify-content:center}.calendars-container .calendar:last-child:not(:first-child){display:none}.calendar .calendar-header .month-year-selector{flex:1}.calendar .calendar-header .month-year{min-width:auto;font-size:.875rem;padding:.25rem .375rem}.calendar .calendar-header .nav-button{width:28px;height:28px}.calendar .calendar-header .nav-button svg{width:10px;height:10px}.calendar .calendar-header .nav-button-placeholder{display:none}.calendar .month-year-picker{min-width:240px;padding:.75rem}.calendar .month-year-picker .picker-section .picker-title{font-size:.7rem}.calendar .month-year-picker .months-grid{grid-template-columns:repeat(3,1fr);gap:.25rem}.calendar .month-year-picker .months-grid .month-option{padding:.4rem;font-size:.7rem}.calendar .month-year-picker .years-grid{grid-template-columns:repeat(3,1fr);gap:.25rem;max-height:150px}.calendar .month-year-picker .years-grid .year-option{padding:.4rem;font-size:.7rem}.calendar .calendar-grid{gap:2px 0}.calendar .calendar-grid .calendar-day{width:30px;height:30px;font-size:.75rem}.calendar .calendar-grid .weekday-header{font-size:.65rem}.footer{flex-direction:column;gap:.75rem;padding:.75rem}.footer .selected-dates{width:100%;justify-content:center;flex-wrap:wrap;gap:.5rem}.footer .selected-dates .date-display{font-size:.7rem;padding:.35rem .5rem}.footer .selected-dates .date-display svg{width:12px;height:12px}.footer .selected-dates .date-separator{font-size:.7rem}.footer .action-buttons{width:100%;gap:.5rem}.footer .action-buttons button{flex:1;padding:.625rem .75rem;font-size:.75rem}.date-picker-dropdown{width:280px!important;max-width:calc(100vw - 2rem);max-height:calc(100vh - 4rem);overflow-y:auto}.date-picker-dropdown.range-mode{width:280px!important}}@media (max-width: 480px){.calendars-container{padding:.5rem}.calendar .calendar-header .month-year{font-size:.8125rem;padding:.2rem .3rem}.calendar .calendar-header .nav-button{width:26px;height:26px}.calendar .calendar-header .nav-button svg{width:9px;height:9px}.calendar .month-year-picker{min-width:220px;padding:.625rem}.calendar .month-year-picker .picker-section{margin-bottom:.75rem}.calendar .month-year-picker .picker-section .picker-title{font-size:.65rem;margin-bottom:.375rem}.calendar .month-year-picker .months-grid{gap:.2rem}.calendar .month-year-picker .months-grid .month-option{padding:.35rem;font-size:.65rem}.calendar .month-year-picker .years-grid{gap:.2rem;max-height:120px}.calendar .month-year-picker .years-grid .year-option{padding:.35rem;font-size:.65rem}.calendar .calendar-grid{gap:1px 0}.calendar .calendar-grid .weekday-header{font-size:.6rem;padding:.35rem 0}.calendar .calendar-grid .calendar-day{width:28px;height:28px;font-size:.7rem}.footer{padding:.5rem;gap:.5rem}.footer .selected-dates{gap:.4rem}.footer .selected-dates .date-display{font-size:.65rem;padding:.3rem .4rem}.footer .selected-dates .date-display svg{width:11px;height:11px}.footer .selected-dates .date-separator{font-size:.65rem}.footer .action-buttons{gap:.4rem}.footer .action-buttons button{padding:.5rem .625rem;font-size:.7rem}.date-picker-dropdown{width:260px!important;max-width:calc(100vw - 1rem)}}\n"] }]
2047
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: Document, decorators: [{
2048
+ type: Inject,
2049
+ args: [DOCUMENT]
2050
+ }] }], propDecorators: { label: [{
2051
+ type: Input
2052
+ }], id: [{
2053
+ type: Input
2054
+ }], placeholder: [{
2055
+ type: Input
2056
+ }], hasError: [{
2057
+ type: Input
2058
+ }], errorMessage: [{
2059
+ type: Input
2060
+ }], disabled: [{
2061
+ type: Input
2062
+ }], minDate: [{
2063
+ type: Input
2064
+ }], maxDate: [{
2065
+ type: Input
2066
+ }], rangeMode: [{
2067
+ type: Input
2068
+ }], iconPosition: [{
2069
+ type: Input
2070
+ }], trigger: [{
2071
+ type: ViewChild,
2072
+ args: ['trigger', { read: ElementRef }]
2073
+ }], dropdown: [{
2074
+ type: ViewChild,
2075
+ args: ['dropdown', { read: ElementRef }]
2076
+ }], onDocumentClick: [{
2077
+ type: HostListener,
2078
+ args: ['document:click', ['$event']]
2079
+ }] } });
2080
+
2081
+ class LoaderComponent {
2082
+ show = false;
2083
+ message;
2084
+ logo;
2085
+ image;
2086
+ imageAlt = 'Loading';
2087
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2088
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: LoaderComponent, isStandalone: true, selector: "app-loader", inputs: { show: "show", message: "message", logo: "logo", image: "image", imageAlt: "imageAlt" }, ngImport: i0, template: `
2089
+ <div class="svu-loader-overlay" *ngIf="show">
2090
+ <div class="svu-loader-content">
2091
+ <!-- Logo -->
2092
+ <div class="svu-loader-logo" *ngIf="logo">
2093
+ <img [src]="logo" assetSource="mf" alt="Logo">
2094
+ </div>
2095
+
2096
+ <!-- Image/Icon -->
2097
+ <div class="svu-loader-image" *ngIf="image">
2098
+ <img [src]="image" assetSource="mf" [alt]="imageAlt">
2099
+ </div>
2100
+
2101
+ <!-- Loading Dots Animation -->
2102
+ <div class="svu-loader-dots">
2103
+ <span class="svu-loader-dot"></span>
2104
+ <span class="svu-loader-dot"></span>
2105
+ <span class="svu-loader-dot"></span>
2106
+ </div>
2107
+
2108
+ <!-- Message -->
2109
+ <div class="svu-loader-message" *ngIf="message">
2110
+ <span [innerHTML]="message"></span>
2111
+ </div>
2112
+ </div>
2113
+ </div>
2114
+ `, isInline: true, styles: [".svu-loader-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#f8f9fc;display:flex;align-items:center;justify-content:center;z-index:99999;animation:fadeIn .3s ease-in-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.svu-loader-content{display:flex;flex-direction:column;align-items:center;gap:2rem;min-height:500px;justify-content:center}.svu-loader-logo{margin-bottom:2rem}.svu-loader-logo img{height:60px;width:auto}.svu-loader-image{display:flex;align-items:center;justify-content:center;animation:float 3s ease-in-out infinite}.svu-loader-image img{max-width:300px;height:auto}@keyframes float{0%,to{transform:translateY(0)}50%{transform:translateY(-20px)}}.svu-loader-dots{display:flex;gap:12px;align-items:center;justify-content:center;padding:1rem 0;height:80px}.svu-loader-dot{width:20px;height:20px;border-radius:50%;background:#f59100;position:relative;transform-origin:center}.svu-loader-dot:nth-child(1){animation:bounce 1.4s ease-in-out infinite}.svu-loader-dot:nth-child(2){animation:bounce 1.4s ease-in-out infinite;animation-delay:.2s}.svu-loader-dot:nth-child(3){animation:bounce 1.4s ease-in-out infinite;animation-delay:.4s}@keyframes bounce{0%,80%,to{transform:scale(.6);opacity:.5}40%{transform:scale(1);opacity:1}}.svu-loader-message{font-family:DM Sans,sans-serif;color:#2e353a;text-align:center;font-weight:900;font-size:30px}.svu-loader-message ::ng-deep strong,.svu-loader-message ::ng-deep b{color:#f26d00;font-weight:900}@media (max-width: 768px){.svu-loader-logo img{height:48px}.svu-loader-image img{max-width:200px}.svu-loader-message{font-size:20px;padding:0 1rem}.svu-loader-dots{height:50px;gap:5px}.svu-loader-dot{width:12px;height:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: AssetSourceDirective, selector: "[assetSource]", inputs: ["assetSource", "assetPath"] }] });
2115
+ }
2116
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LoaderComponent, decorators: [{
2117
+ type: Component,
2118
+ args: [{ selector: 'app-loader', standalone: true, imports: [CommonModule, AssetSourceDirective], template: `
2119
+ <div class="svu-loader-overlay" *ngIf="show">
2120
+ <div class="svu-loader-content">
2121
+ <!-- Logo -->
2122
+ <div class="svu-loader-logo" *ngIf="logo">
2123
+ <img [src]="logo" assetSource="mf" alt="Logo">
2124
+ </div>
2125
+
2126
+ <!-- Image/Icon -->
2127
+ <div class="svu-loader-image" *ngIf="image">
2128
+ <img [src]="image" assetSource="mf" [alt]="imageAlt">
2129
+ </div>
2130
+
2131
+ <!-- Loading Dots Animation -->
2132
+ <div class="svu-loader-dots">
2133
+ <span class="svu-loader-dot"></span>
2134
+ <span class="svu-loader-dot"></span>
2135
+ <span class="svu-loader-dot"></span>
2136
+ </div>
2137
+
2138
+ <!-- Message -->
2139
+ <div class="svu-loader-message" *ngIf="message">
2140
+ <span [innerHTML]="message"></span>
2141
+ </div>
2142
+ </div>
2143
+ </div>
2144
+ `, styles: [".svu-loader-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#f8f9fc;display:flex;align-items:center;justify-content:center;z-index:99999;animation:fadeIn .3s ease-in-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.svu-loader-content{display:flex;flex-direction:column;align-items:center;gap:2rem;min-height:500px;justify-content:center}.svu-loader-logo{margin-bottom:2rem}.svu-loader-logo img{height:60px;width:auto}.svu-loader-image{display:flex;align-items:center;justify-content:center;animation:float 3s ease-in-out infinite}.svu-loader-image img{max-width:300px;height:auto}@keyframes float{0%,to{transform:translateY(0)}50%{transform:translateY(-20px)}}.svu-loader-dots{display:flex;gap:12px;align-items:center;justify-content:center;padding:1rem 0;height:80px}.svu-loader-dot{width:20px;height:20px;border-radius:50%;background:#f59100;position:relative;transform-origin:center}.svu-loader-dot:nth-child(1){animation:bounce 1.4s ease-in-out infinite}.svu-loader-dot:nth-child(2){animation:bounce 1.4s ease-in-out infinite;animation-delay:.2s}.svu-loader-dot:nth-child(3){animation:bounce 1.4s ease-in-out infinite;animation-delay:.4s}@keyframes bounce{0%,80%,to{transform:scale(.6);opacity:.5}40%{transform:scale(1);opacity:1}}.svu-loader-message{font-family:DM Sans,sans-serif;color:#2e353a;text-align:center;font-weight:900;font-size:30px}.svu-loader-message ::ng-deep strong,.svu-loader-message ::ng-deep b{color:#f26d00;font-weight:900}@media (max-width: 768px){.svu-loader-logo img{height:48px}.svu-loader-image img{max-width:200px}.svu-loader-message{font-size:20px;padding:0 1rem}.svu-loader-dots{height:50px;gap:5px}.svu-loader-dot{width:12px;height:12px}}\n"] }]
2145
+ }], propDecorators: { show: [{
2146
+ type: Input
2147
+ }], message: [{
2148
+ type: Input
2149
+ }], logo: [{
2150
+ type: Input
2151
+ }], image: [{
2152
+ type: Input
2153
+ }], imageAlt: [{
2154
+ type: Input
2155
+ }] } });
2156
+
2157
+ class OptionComponent {
2158
+ elementRef;
2159
+ value;
2160
+ disabled = false;
2161
+ selected = false;
2162
+ optionClass = true;
2163
+ // Internal property to store text content
2164
+ _viewValue = '';
2165
+ get viewValue() {
2166
+ return this._viewValue || this.getTextContent();
2167
+ }
2168
+ set viewValue(value) {
2169
+ this._viewValue = value;
2170
+ }
2171
+ constructor(elementRef) {
2172
+ this.elementRef = elementRef;
2173
+ }
2174
+ /**
2175
+ * Get the text content from the element
2176
+ */
2177
+ getTextContent() {
2178
+ return this.elementRef.nativeElement.textContent?.trim() || '';
2179
+ }
2180
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OptionComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
2181
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: OptionComponent, isStandalone: true, selector: "app-option", inputs: { value: "value", disabled: "disabled" }, host: { properties: { "class.disabled": "disabled", "class.selected": "this.selected", "class.app-option": "this.optionClass" }, classAttribute: "app-option" }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2182
+ }
2183
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OptionComponent, decorators: [{
2184
+ type: Component,
2185
+ args: [{
2186
+ selector: 'app-option',
2187
+ standalone: true,
2188
+ imports: [CommonModule],
2189
+ template: `<ng-content></ng-content>`,
2190
+ changeDetection: ChangeDetectionStrategy.OnPush,
2191
+ host: {
2192
+ 'class': 'app-option',
2193
+ '[class.disabled]': 'disabled',
2194
+ '[class.selected]': 'selected'
2195
+ }
2196
+ }]
2197
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { value: [{
2198
+ type: Input
2199
+ }], disabled: [{
2200
+ type: Input
2201
+ }], selected: [{
2202
+ type: HostBinding,
2203
+ args: ['class.selected']
2204
+ }], optionClass: [{
2205
+ type: HostBinding,
2206
+ args: ['class.app-option']
2207
+ }] } });
2208
+
2209
+ class SelectPrefixDirective {
2210
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectPrefixDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2211
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: SelectPrefixDirective, isStandalone: true, selector: "[prefix]", ngImport: i0 });
2212
+ }
2213
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectPrefixDirective, decorators: [{
2214
+ type: Directive,
2215
+ args: [{
2216
+ selector: '[prefix]',
2217
+ standalone: true
2218
+ }]
2219
+ }] });
2220
+ class SelectSuffixDirective {
2221
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSuffixDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2222
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: SelectSuffixDirective, isStandalone: true, selector: "[suffix]", ngImport: i0 });
2223
+ }
2224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSuffixDirective, decorators: [{
2225
+ type: Directive,
2226
+ args: [{
2227
+ selector: '[suffix]',
2228
+ standalone: true
2229
+ }]
2230
+ }] });
2231
+ class SelectComponent {
2232
+ renderer;
2233
+ document;
2234
+ label = '';
2235
+ id = '';
2236
+ placeholder = '';
2237
+ options = [];
2238
+ hasError = false;
2239
+ errorMessage = '';
2240
+ disabled = false;
2241
+ unstyled = false;
2242
+ displayKey = 'label'; // Property to display as label
2243
+ valueKey = 'value'; // Property to use as value
2244
+ customClass = ''; // Custom CSS class for styling
2245
+ trigger;
2246
+ contentOptions;
2247
+ prefixDirective;
2248
+ suffixDirective;
2249
+ get hasPrefix() {
2250
+ return !!this.prefixDirective;
2251
+ }
2252
+ get hasSuffix() {
2253
+ return !!this.suffixDirective;
2254
+ }
2255
+ value = '';
2256
+ isOpen = false;
2257
+ onChange = () => { };
2258
+ onTouched = () => { };
2259
+ _usingContentOptions = false;
2260
+ dropdownElement = null;
2261
+ backdropElement = null;
2262
+ scrollHandler = null;
2263
+ resizeHandler = null;
2264
+ constructor(renderer, document) {
2265
+ this.renderer = renderer;
2266
+ this.document = document;
2267
+ }
2268
+ ngAfterContentInit() {
2269
+ // Determine if using content projection or input options
2270
+ this._usingContentOptions = this.contentOptions && this.contentOptions.length > 0;
2271
+ // Subscribe to changes in content options
2272
+ if (this.contentOptions) {
2273
+ this.contentOptions.changes.subscribe(() => {
2274
+ this._usingContentOptions = this.contentOptions.length > 0;
2275
+ });
2276
+ }
2277
+ }
2278
+ ngOnDestroy() {
2279
+ this.destroyDropdown();
2280
+ }
2281
+ onEsc() {
2282
+ this.closeDropdown();
2283
+ this.onTouched();
2284
+ }
2285
+ handleBlur() {
2286
+ this.onTouched();
2287
+ }
2288
+ /**
2289
+ * Get all options (from content or input)
2290
+ */
2291
+ getAllOptions() {
2292
+ if (this._usingContentOptions && this.contentOptions) {
2293
+ return this.contentOptions.toArray();
2294
+ }
2295
+ return this.options || [];
2296
+ }
2297
+ /**
2298
+ * Get display label from option
2299
+ */
2300
+ getOptionLabel(option) {
2301
+ if (option instanceof OptionComponent) {
2302
+ return option.viewValue;
2303
+ }
2304
+ return option?.[this.displayKey] || '';
2305
+ }
2306
+ /**
2307
+ * Get value from option
2308
+ */
2309
+ getOptionValue(option) {
2310
+ if (option instanceof OptionComponent) {
2311
+ return option.value;
2312
+ }
2313
+ return option?.[this.valueKey];
2314
+ }
2315
+ /**
2316
+ * Check if option is disabled
2317
+ */
2318
+ isOptionDisabled(option) {
2319
+ if (option instanceof OptionComponent) {
2320
+ return option.disabled;
2321
+ }
2322
+ return option?.disabled || false;
2323
+ }
2324
+ onDocumentClick(event) {
2325
+ // Close dropdown if click is outside
2326
+ if (this.isOpen && this.dropdownElement && !this.dropdownElement.contains(event.target)) {
2327
+ const triggerElement = this.trigger?.nativeElement;
2328
+ if (triggerElement && !triggerElement.contains(event.target)) {
2329
+ this.closeDropdown();
2330
+ }
2331
+ }
2332
+ }
2333
+ toggleDropdown(event) {
2334
+ event.stopPropagation();
2335
+ if (this.disabled)
2336
+ return;
2337
+ if (this.isOpen) {
2338
+ this.closeDropdown();
2339
+ }
2340
+ else {
2341
+ this.openDropdown();
2342
+ }
2343
+ }
2344
+ openDropdown() {
2345
+ if (!this.trigger)
2346
+ return;
2347
+ // Create backdrop
2348
+ this.backdropElement = this.renderer.createElement('div');
2349
+ this.renderer.addClass(this.backdropElement, 'select-custom-backdrop');
2350
+ this.renderer.listen(this.backdropElement, 'click', () => this.closeDropdown());
2351
+ this.renderer.appendChild(this.document.body, this.backdropElement);
2352
+ // Create dropdown
2353
+ this.dropdownElement = this.renderer.createElement('div');
2354
+ this.renderer.addClass(this.dropdownElement, 'select-custom-dropdown');
2355
+ this.renderer.addClass(this.dropdownElement, 'select-overlay-pane');
2356
+ // Calculate position
2357
+ const position = this.calculatePosition();
2358
+ // Apply positioning styles
2359
+ this.renderer.setStyle(this.dropdownElement, 'position', 'fixed');
2360
+ this.renderer.setStyle(this.dropdownElement, 'left', position.left);
2361
+ this.renderer.setStyle(this.dropdownElement, 'width', position.width);
2362
+ this.renderer.setStyle(this.dropdownElement, 'max-height', position.maxHeight);
2363
+ this.renderer.setStyle(this.dropdownElement, 'z-index', '100000', RendererStyleFlags2.Important);
2364
+ if (position.top) {
2365
+ this.renderer.setStyle(this.dropdownElement, 'top', position.top);
2366
+ }
2367
+ else if (position.bottom) {
2368
+ this.renderer.setStyle(this.dropdownElement, 'bottom', position.bottom);
2369
+ }
2370
+ // Create dropdown content wrapper
2371
+ const dropdownContent = this.renderer.createElement('div');
2372
+ this.renderer.addClass(dropdownContent, 'select-dropdown');
2373
+ // Add options
2374
+ const allOptions = this.getAllOptions();
2375
+ allOptions.forEach(option => {
2376
+ const optionElement = this.createOptionElement(option);
2377
+ this.renderer.appendChild(dropdownContent, optionElement);
2378
+ });
2379
+ this.renderer.appendChild(this.dropdownElement, dropdownContent);
2380
+ this.renderer.appendChild(this.document.body, this.dropdownElement);
2381
+ this.isOpen = true;
2382
+ // Add scroll and resize listeners to reposition dropdown
2383
+ this.addRepositionListeners();
2384
+ // Trigger animation
2385
+ setTimeout(() => {
2386
+ if (this.dropdownElement) {
2387
+ this.renderer.addClass(this.dropdownElement, 'select-dropdown-open');
2388
+ }
2389
+ }, 10);
2390
+ }
2391
+ calculatePosition() {
2392
+ const triggerElement = this.trigger.nativeElement;
2393
+ const rect = triggerElement.getBoundingClientRect();
2394
+ const spaceBelow = window.innerHeight - rect.bottom;
2395
+ const spaceAbove = rect.top;
2396
+ const dropdownMaxHeight = 300;
2397
+ const offsetY = 4;
2398
+ const shouldOpenAbove = spaceBelow < 200 && spaceAbove > spaceBelow;
2399
+ const position = {
2400
+ left: `${rect.left}px`,
2401
+ width: `${rect.width}px`,
2402
+ maxHeight: `${dropdownMaxHeight}px`
2403
+ };
2404
+ if (shouldOpenAbove) {
2405
+ position.bottom = `${window.innerHeight - rect.top + offsetY}px`;
2406
+ }
2407
+ else {
2408
+ position.top = `${rect.bottom + offsetY}px`;
2409
+ }
2410
+ return position;
2411
+ }
2412
+ addRepositionListeners() {
2413
+ // Create handlers
2414
+ const scrollHandler = () => this.updateDropdownPosition();
2415
+ const resizeHandler = () => this.updateDropdownPosition();
2416
+ // Add scroll listener to window with capture phase to catch all scroll events
2417
+ window.addEventListener('scroll', scrollHandler, true);
2418
+ this.scrollHandler = () => window.removeEventListener('scroll', scrollHandler, true);
2419
+ // Add resize listener
2420
+ window.addEventListener('resize', resizeHandler);
2421
+ this.resizeHandler = () => window.removeEventListener('resize', resizeHandler);
2422
+ }
2423
+ updateDropdownPosition() {
2424
+ if (!this.dropdownElement || !this.trigger)
2425
+ return;
2426
+ const position = this.calculatePosition();
2427
+ // Update position styles
2428
+ this.renderer.setStyle(this.dropdownElement, 'left', position.left);
2429
+ this.renderer.setStyle(this.dropdownElement, 'width', position.width);
2430
+ // Remove old top/bottom styles
2431
+ this.renderer.removeStyle(this.dropdownElement, 'top');
2432
+ this.renderer.removeStyle(this.dropdownElement, 'bottom');
2433
+ // Apply new top/bottom position
2434
+ if (position.top) {
2435
+ this.renderer.setStyle(this.dropdownElement, 'top', position.top);
2436
+ }
2437
+ else if (position.bottom) {
2438
+ this.renderer.setStyle(this.dropdownElement, 'bottom', position.bottom);
2439
+ }
2440
+ }
2441
+ createOptionElement(option) {
2442
+ const optionElement = this.renderer.createElement('div');
2443
+ this.renderer.addClass(optionElement, 'select-option');
2444
+ const optionValue = this.getOptionValue(option);
2445
+ const optionLabel = this.getOptionLabel(option);
2446
+ const optionDisabled = this.isOptionDisabled(option);
2447
+ if (this.isEmptyValue(optionValue)) {
2448
+ this.renderer.addClass(optionElement, 'select-option-placeholder');
2449
+ }
2450
+ if (this.isSelected(optionValue)) {
2451
+ this.renderer.addClass(optionElement, 'selected');
2452
+ }
2453
+ if (optionDisabled) {
2454
+ this.renderer.addClass(optionElement, 'disabled');
2455
+ }
2456
+ // Option text
2457
+ const textSpan = this.renderer.createElement('span');
2458
+ this.renderer.addClass(textSpan, 'option-text');
2459
+ const text = this.renderer.createText(optionLabel);
2460
+ this.renderer.appendChild(textSpan, text);
2461
+ this.renderer.appendChild(optionElement, textSpan);
2462
+ // Check icon for selected option
2463
+ if (this.isSelected(optionValue)) {
2464
+ const svg = this.createCheckIcon();
2465
+ this.renderer.appendChild(optionElement, svg);
2466
+ }
2467
+ // Click handler
2468
+ if (!optionDisabled) {
2469
+ this.renderer.listen(optionElement, 'click', (event) => {
2470
+ event.stopPropagation();
2471
+ this.selectOption(option);
2472
+ });
2473
+ }
2474
+ return optionElement;
2475
+ }
2476
+ createCheckIcon() {
2477
+ const svg = this.renderer.createElement('svg', 'svg');
2478
+ this.renderer.addClass(svg, 'check-icon');
2479
+ this.renderer.setAttribute(svg, 'width', '14');
2480
+ this.renderer.setAttribute(svg, 'height', '10');
2481
+ this.renderer.setAttribute(svg, 'viewBox', '0 0 10 8');
2482
+ this.renderer.setAttribute(svg, 'fill', 'none');
2483
+ this.renderer.setAttribute(svg, 'xmlns', 'http://www.w3.org/2000/svg');
2484
+ const path = this.renderer.createElement('path', 'svg');
2485
+ this.renderer.setAttribute(path, 'd', 'M9 1L3.5 6.5L1 4');
2486
+ this.renderer.setAttribute(path, 'stroke', '#F59100');
2487
+ this.renderer.setAttribute(path, 'stroke-width', '1.6666');
2488
+ this.renderer.setAttribute(path, 'stroke-linecap', 'round');
2489
+ this.renderer.setAttribute(path, 'stroke-linejoin', 'round');
2490
+ this.renderer.appendChild(svg, path);
2491
+ return svg;
2492
+ }
2493
+ closeDropdown() {
2494
+ this.destroyDropdown();
2495
+ this.isOpen = false;
2496
+ }
2497
+ destroyDropdown() {
2498
+ // Remove listeners
2499
+ if (this.scrollHandler) {
2500
+ this.scrollHandler();
2501
+ this.scrollHandler = null;
2502
+ }
2503
+ if (this.resizeHandler) {
2504
+ this.resizeHandler();
2505
+ this.resizeHandler = null;
2506
+ }
2507
+ if (this.dropdownElement) {
2508
+ this.renderer.removeChild(this.document.body, this.dropdownElement);
2509
+ this.dropdownElement = null;
2510
+ }
2511
+ if (this.backdropElement) {
2512
+ this.renderer.removeChild(this.document.body, this.backdropElement);
2513
+ this.backdropElement = null;
2514
+ }
2515
+ }
2516
+ selectOption(option) {
2517
+ if (this.isOptionDisabled(option))
2518
+ return;
2519
+ this.value = this.getOptionValue(option);
2520
+ this.onChange(this.value);
2521
+ this.onTouched();
2522
+ this.closeDropdown();
2523
+ }
2524
+ isSelected(value) {
2525
+ return this.value === value;
2526
+ }
2527
+ isEmptyValue(value) {
2528
+ return value === '' || value === null || value === undefined;
2529
+ }
2530
+ getSelectedLabel() {
2531
+ const allOptions = this.getAllOptions();
2532
+ const selectedOption = allOptions.find(opt => this.getOptionValue(opt) === this.value);
2533
+ return selectedOption ? this.getOptionLabel(selectedOption) : '';
2534
+ }
2535
+ writeValue(value) {
2536
+ this.value = value || '';
2537
+ }
2538
+ registerOnChange(fn) {
2539
+ this.onChange = fn;
2540
+ }
2541
+ registerOnTouched(fn) {
2542
+ this.onTouched = fn;
2543
+ }
2544
+ setDisabledState(isDisabled) {
2545
+ this.disabled = isDisabled;
2546
+ }
2547
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectComponent, deps: [{ token: i0.Renderer2 }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component });
2548
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SelectComponent, isStandalone: true, selector: "app-select", inputs: { label: "label", id: "id", placeholder: "placeholder", options: "options", hasError: "hasError", errorMessage: "errorMessage", disabled: "disabled", unstyled: "unstyled", displayKey: "displayKey", valueKey: "valueKey", customClass: "customClass" }, host: { listeners: { "keydown.escape": "onEsc()", "document:click": "onDocumentClick($event)" } }, providers: [
2549
+ {
2550
+ provide: NG_VALUE_ACCESSOR,
2551
+ useExisting: forwardRef(() => SelectComponent),
2552
+ multi: true
2553
+ }
2554
+ ], queries: [{ propertyName: "prefixDirective", first: true, predicate: SelectPrefixDirective, descendants: true }, { propertyName: "suffixDirective", first: true, predicate: SelectSuffixDirective, descendants: true }, { propertyName: "contentOptions", predicate: OptionComponent }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, read: ElementRef }], ngImport: i0, template: `
2555
+ <div class="select-wrapper" [class.select-wrapper--unstyled]="unstyled" [ngClass]="customClass">
2556
+ <label *ngIf="label && !unstyled" [for]="id">{{ label }}</label>
2557
+ <div class="select-container" [class.select-container--unstyled]="unstyled">
2558
+ <div
2559
+ #trigger
2560
+ class="select-header"
2561
+ [attr.tabindex]="disabled ? -1 : 0"
2562
+ [class.error]="hasError && !unstyled"
2563
+ [class.disabled]="disabled"
2564
+ [class.open]="isOpen"
2565
+ [class.select-header--unstyled]="unstyled"
2566
+ [class.select-header--has-prefix]="hasPrefix"
2567
+ (blur)="handleBlur()"
2568
+ (click)="!disabled && toggleDropdown($event)">
2569
+ <span class="select-prefix" *ngIf="hasPrefix">
2570
+ <ng-content select="[prefix]"></ng-content>
2571
+ </span>
2572
+ <span class="select-placeholder" *ngIf="!getSelectedLabel()">
2573
+ {{ placeholder }}
2574
+ </span>
2575
+ <span class="select-selected" *ngIf="getSelectedLabel()">
2576
+ {{ getSelectedLabel() }}
2577
+ </span>
2578
+ <span class="select-suffix" *ngIf="hasSuffix">
2579
+ <ng-content select="[suffix]"></ng-content>
2580
+ </span>
2581
+ <svg class="select-arrow" [class.open]="isOpen" width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
2582
+ <path d="M1 1.5L6 6.5L11 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
2583
+ </svg>
2584
+ </div>
2585
+ </div>
2586
+ <div *ngIf="hasError && errorMessage && !unstyled" class="field-error">
2587
+ {{ errorMessage }}
2588
+ </div>
2589
+
2590
+ <!-- Hidden container for projected options -->
2591
+ <div style="display: none;">
2592
+ <ng-content></ng-content>
2593
+ </div>
2594
+ </div>
2595
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] });
2596
+ }
2597
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectComponent, decorators: [{
2598
+ type: Component,
2599
+ args: [{
2600
+ selector: 'app-select',
2601
+ standalone: true,
2602
+ imports: [CommonModule, ReactiveFormsModule, FormsModule, SelectPrefixDirective, SelectSuffixDirective],
2603
+ template: `
2604
+ <div class="select-wrapper" [class.select-wrapper--unstyled]="unstyled" [ngClass]="customClass">
2605
+ <label *ngIf="label && !unstyled" [for]="id">{{ label }}</label>
2606
+ <div class="select-container" [class.select-container--unstyled]="unstyled">
2607
+ <div
2608
+ #trigger
2609
+ class="select-header"
2610
+ [attr.tabindex]="disabled ? -1 : 0"
2611
+ [class.error]="hasError && !unstyled"
2612
+ [class.disabled]="disabled"
2613
+ [class.open]="isOpen"
2614
+ [class.select-header--unstyled]="unstyled"
2615
+ [class.select-header--has-prefix]="hasPrefix"
2616
+ (blur)="handleBlur()"
2617
+ (click)="!disabled && toggleDropdown($event)">
2618
+ <span class="select-prefix" *ngIf="hasPrefix">
2619
+ <ng-content select="[prefix]"></ng-content>
2620
+ </span>
2621
+ <span class="select-placeholder" *ngIf="!getSelectedLabel()">
2622
+ {{ placeholder }}
2623
+ </span>
2624
+ <span class="select-selected" *ngIf="getSelectedLabel()">
2625
+ {{ getSelectedLabel() }}
2626
+ </span>
2627
+ <span class="select-suffix" *ngIf="hasSuffix">
2628
+ <ng-content select="[suffix]"></ng-content>
2629
+ </span>
2630
+ <svg class="select-arrow" [class.open]="isOpen" width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
2631
+ <path d="M1 1.5L6 6.5L11 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
2632
+ </svg>
2633
+ </div>
2634
+ </div>
2635
+ <div *ngIf="hasError && errorMessage && !unstyled" class="field-error">
2636
+ {{ errorMessage }}
2637
+ </div>
2638
+
2639
+ <!-- Hidden container for projected options -->
2640
+ <div style="display: none;">
2641
+ <ng-content></ng-content>
2642
+ </div>
2643
+ </div>
2644
+ `,
2645
+ providers: [
2646
+ {
2647
+ provide: NG_VALUE_ACCESSOR,
2648
+ useExisting: forwardRef(() => SelectComponent),
2649
+ multi: true
2650
+ }
2651
+ ]
2652
+ }]
2653
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: Document, decorators: [{
2654
+ type: Inject,
2655
+ args: [DOCUMENT]
2656
+ }] }], propDecorators: { label: [{
2657
+ type: Input
2658
+ }], id: [{
2659
+ type: Input
2660
+ }], placeholder: [{
2661
+ type: Input
2662
+ }], options: [{
2663
+ type: Input
2664
+ }], hasError: [{
2665
+ type: Input
2666
+ }], errorMessage: [{
2667
+ type: Input
2668
+ }], disabled: [{
2669
+ type: Input
2670
+ }], unstyled: [{
2671
+ type: Input
2672
+ }], displayKey: [{
2673
+ type: Input
2674
+ }], valueKey: [{
2675
+ type: Input
2676
+ }], customClass: [{
2677
+ type: Input
2678
+ }], trigger: [{
2679
+ type: ViewChild,
2680
+ args: ['trigger', { read: ElementRef }]
2681
+ }], contentOptions: [{
2682
+ type: ContentChildren,
2683
+ args: [OptionComponent]
2684
+ }], prefixDirective: [{
2685
+ type: ContentChild,
2686
+ args: [SelectPrefixDirective]
2687
+ }], suffixDirective: [{
2688
+ type: ContentChild,
2689
+ args: [SelectSuffixDirective]
2690
+ }], onEsc: [{
2691
+ type: HostListener,
2692
+ args: ['keydown.escape']
2693
+ }], onDocumentClick: [{
2694
+ type: HostListener,
2695
+ args: ['document:click', ['$event']]
2696
+ }] } });
2697
+
2698
+ class MultiselectComponent {
2699
+ renderer;
2700
+ document;
2701
+ label = '';
2702
+ id = '';
2703
+ placeholder = '';
2704
+ options = [];
2705
+ hasError = false;
2706
+ errorMessage = '';
2707
+ disabled = false;
2708
+ displayKey = 'label'; // Property to display as label
2709
+ valueKey = 'value'; // Property to use as value
2710
+ customClass = ''; // Custom CSS class for styling
2711
+ trigger;
2712
+ contentOptions;
2713
+ value = [];
2714
+ isOpen = false;
2715
+ onChange = () => { };
2716
+ onTouched = () => { };
2717
+ _usingContentOptions = false;
2718
+ dropdownElement = null;
2719
+ backdropElement = null;
2720
+ scrollHandler = null;
2721
+ resizeHandler = null;
2722
+ constructor(renderer, document) {
2723
+ this.renderer = renderer;
2724
+ this.document = document;
2725
+ }
2726
+ ngAfterContentInit() {
2727
+ // Determine if using content projection or input options
2728
+ this._usingContentOptions = this.contentOptions && this.contentOptions.length > 0;
2729
+ // Subscribe to changes in content options
2730
+ if (this.contentOptions) {
2731
+ this.contentOptions.changes.subscribe(() => {
2732
+ this._usingContentOptions = this.contentOptions.length > 0;
2733
+ });
2734
+ }
2735
+ }
2736
+ ngOnDestroy() {
2737
+ this.destroyDropdown();
2738
+ }
2739
+ /**
2740
+ * Get all options (from content or input)
2741
+ */
2742
+ getAllOptions() {
2743
+ if (this._usingContentOptions && this.contentOptions) {
2744
+ return this.contentOptions.toArray();
2745
+ }
2746
+ return this.options || [];
2747
+ }
2748
+ /**
2749
+ * Get display label from option
2750
+ */
2751
+ getOptionLabel(option) {
2752
+ if (option instanceof OptionComponent) {
2753
+ return option.viewValue;
2754
+ }
2755
+ return option?.[this.displayKey] || '';
2756
+ }
2757
+ /**
2758
+ * Get value from option
2759
+ */
2760
+ getOptionValue(option) {
2761
+ if (option instanceof OptionComponent) {
2762
+ return option.value;
2763
+ }
2764
+ return option?.[this.valueKey];
2765
+ }
2766
+ /**
2767
+ * Check if option is disabled
2768
+ */
2769
+ isOptionDisabled(option) {
2770
+ if (option instanceof OptionComponent) {
2771
+ return option.disabled;
2772
+ }
2773
+ return option?.disabled || false;
2774
+ }
2775
+ onDocumentClick(event) {
2776
+ // Close dropdown if click is outside
2777
+ if (this.isOpen && this.dropdownElement && !this.dropdownElement.contains(event.target)) {
2778
+ const triggerElement = this.trigger?.nativeElement;
2779
+ if (triggerElement && !triggerElement.contains(event.target)) {
2780
+ this.closeDropdown();
2781
+ }
2782
+ }
2783
+ }
2784
+ toggleDropdown(event) {
2785
+ event.stopPropagation();
2786
+ if (this.disabled)
2787
+ return;
2788
+ if (this.isOpen) {
2789
+ this.closeDropdown();
2790
+ }
2791
+ else {
2792
+ this.openDropdown();
2793
+ }
2794
+ }
2795
+ openDropdown() {
2796
+ if (!this.trigger)
2797
+ return;
2798
+ // Create backdrop
2799
+ this.backdropElement = this.renderer.createElement('div');
2800
+ this.renderer.addClass(this.backdropElement, 'multiselect-custom-backdrop');
2801
+ this.renderer.listen(this.backdropElement, 'click', () => this.closeDropdown());
2802
+ this.renderer.appendChild(this.document.body, this.backdropElement);
2803
+ // Create dropdown
2804
+ this.dropdownElement = this.renderer.createElement('div');
2805
+ this.renderer.addClass(this.dropdownElement, 'multiselect-custom-dropdown');
2806
+ this.renderer.addClass(this.dropdownElement, 'multiselect-overlay-pane');
2807
+ // Calculate position
2808
+ const position = this.calculatePosition();
2809
+ // Apply positioning styles
2810
+ this.renderer.setStyle(this.dropdownElement, 'position', 'fixed');
2811
+ this.renderer.setStyle(this.dropdownElement, 'left', position.left);
2812
+ this.renderer.setStyle(this.dropdownElement, 'width', position.width);
2813
+ this.renderer.setStyle(this.dropdownElement, 'max-height', position.maxHeight);
2814
+ this.renderer.setStyle(this.dropdownElement, 'z-index', '100000', RendererStyleFlags2.Important);
2815
+ if (position.top) {
2816
+ this.renderer.setStyle(this.dropdownElement, 'top', position.top);
2817
+ }
2818
+ else if (position.bottom) {
2819
+ this.renderer.setStyle(this.dropdownElement, 'bottom', position.bottom);
2820
+ }
2821
+ // Create dropdown content wrapper
2822
+ const dropdownContent = this.renderer.createElement('div');
2823
+ this.renderer.addClass(dropdownContent, 'multiselect-dropdown');
2824
+ // Add options
2825
+ const allOptions = this.getAllOptions();
2826
+ allOptions.forEach(option => {
2827
+ const optionElement = this.createOptionElement(option);
2828
+ this.renderer.appendChild(dropdownContent, optionElement);
2829
+ });
2830
+ this.renderer.appendChild(this.dropdownElement, dropdownContent);
2831
+ this.renderer.appendChild(this.document.body, this.dropdownElement);
2832
+ this.isOpen = true;
2833
+ // Add scroll and resize listeners to reposition dropdown
2834
+ this.addRepositionListeners();
2835
+ // Trigger animation
2836
+ setTimeout(() => {
2837
+ if (this.dropdownElement) {
2838
+ this.renderer.addClass(this.dropdownElement, 'multiselect-dropdown-open');
2839
+ }
2840
+ }, 10);
2841
+ }
2842
+ calculatePosition() {
2843
+ const triggerElement = this.trigger.nativeElement;
2844
+ const rect = triggerElement.getBoundingClientRect();
2845
+ const spaceBelow = window.innerHeight - rect.bottom;
2846
+ const spaceAbove = rect.top;
2847
+ const dropdownMaxHeight = 300;
2848
+ const offsetY = 4;
2849
+ const shouldOpenAbove = spaceBelow < 200 && spaceAbove > spaceBelow;
2850
+ const position = {
2851
+ left: `${rect.left}px`,
2852
+ width: `${rect.width}px`,
2853
+ maxHeight: `${dropdownMaxHeight}px`
2854
+ };
2855
+ if (shouldOpenAbove) {
2856
+ position.bottom = `${window.innerHeight - rect.top + offsetY}px`;
2857
+ }
2858
+ else {
2859
+ position.top = `${rect.bottom + offsetY}px`;
2860
+ }
2861
+ return position;
2862
+ }
2863
+ addRepositionListeners() {
2864
+ // Create handlers
2865
+ const scrollHandler = () => this.updateDropdownPosition();
2866
+ const resizeHandler = () => this.updateDropdownPosition();
2867
+ // Add scroll listener to window with capture phase to catch all scroll events
2868
+ window.addEventListener('scroll', scrollHandler, true);
2869
+ this.scrollHandler = () => window.removeEventListener('scroll', scrollHandler, true);
2870
+ // Add resize listener
2871
+ window.addEventListener('resize', resizeHandler);
2872
+ this.resizeHandler = () => window.removeEventListener('resize', resizeHandler);
2873
+ }
2874
+ updateDropdownPosition() {
2875
+ if (!this.dropdownElement || !this.trigger)
2876
+ return;
2877
+ const position = this.calculatePosition();
2878
+ // Update position styles
2879
+ this.renderer.setStyle(this.dropdownElement, 'left', position.left);
2880
+ this.renderer.setStyle(this.dropdownElement, 'width', position.width);
2881
+ // Remove old top/bottom styles
2882
+ this.renderer.removeStyle(this.dropdownElement, 'top');
2883
+ this.renderer.removeStyle(this.dropdownElement, 'bottom');
2884
+ // Apply new top/bottom position
2885
+ if (position.top) {
2886
+ this.renderer.setStyle(this.dropdownElement, 'top', position.top);
2887
+ }
2888
+ else if (position.bottom) {
2889
+ this.renderer.setStyle(this.dropdownElement, 'bottom', position.bottom);
2890
+ }
2891
+ }
2892
+ createOptionElement(option) {
2893
+ const labelElement = this.renderer.createElement('label');
2894
+ this.renderer.addClass(labelElement, 'multiselect-option');
2895
+ const optionValue = this.getOptionValue(option);
2896
+ const optionLabel = this.getOptionLabel(option);
2897
+ const optionDisabled = this.isOptionDisabled(option);
2898
+ if (this.isSelected(optionValue)) {
2899
+ this.renderer.addClass(labelElement, 'selected');
2900
+ }
2901
+ if (optionDisabled) {
2902
+ this.renderer.addClass(labelElement, 'disabled');
2903
+ }
2904
+ // Stop propagation on label click
2905
+ this.renderer.listen(labelElement, 'click', (event) => {
2906
+ event.stopPropagation();
2907
+ });
2908
+ // Checkbox container
2909
+ const checkboxDiv = this.renderer.createElement('div');
2910
+ this.renderer.addClass(checkboxDiv, 'option-checkbox');
2911
+ // Hidden native checkbox
2912
+ const checkbox = this.renderer.createElement('input');
2913
+ this.renderer.setAttribute(checkbox, 'type', 'checkbox');
2914
+ this.renderer.setProperty(checkbox, 'checked', this.isSelected(optionValue));
2915
+ if (optionDisabled) {
2916
+ this.renderer.setProperty(checkbox, 'disabled', true);
2917
+ }
2918
+ // Custom checkbox span
2919
+ const customCheckbox = this.renderer.createElement('span');
2920
+ this.renderer.addClass(customCheckbox, 'checkbox-custom');
2921
+ if (this.isSelected(optionValue)) {
2922
+ this.renderer.addClass(customCheckbox, 'checked');
2923
+ }
2924
+ // Check icon
2925
+ if (this.isSelected(optionValue)) {
2926
+ const svg = this.createCheckIcon();
2927
+ this.renderer.appendChild(customCheckbox, svg);
2928
+ }
2929
+ // Listen to change event
2930
+ this.renderer.listen(checkbox, 'change', (event) => {
2931
+ event.stopPropagation();
2932
+ // Toggle the value
2933
+ this.toggleOption(option);
2934
+ // Update visual state
2935
+ const isNowSelected = this.isSelected(optionValue);
2936
+ this.renderer.setProperty(checkbox, 'checked', isNowSelected);
2937
+ if (isNowSelected) {
2938
+ this.renderer.addClass(labelElement, 'selected');
2939
+ this.renderer.addClass(customCheckbox, 'checked');
2940
+ // Add check icon if not present
2941
+ if (!customCheckbox.querySelector('.check-icon')) {
2942
+ const svg = this.createCheckIcon();
2943
+ this.renderer.appendChild(customCheckbox, svg);
2944
+ }
2945
+ }
2946
+ else {
2947
+ this.renderer.removeClass(labelElement, 'selected');
2948
+ this.renderer.removeClass(customCheckbox, 'checked');
2949
+ // Remove check icon
2950
+ const existingIcon = customCheckbox.querySelector('.check-icon');
2951
+ if (existingIcon) {
2952
+ this.renderer.removeChild(customCheckbox, existingIcon);
2953
+ }
2954
+ }
2955
+ });
2956
+ this.renderer.appendChild(checkboxDiv, checkbox);
2957
+ this.renderer.appendChild(checkboxDiv, customCheckbox);
2958
+ this.renderer.appendChild(labelElement, checkboxDiv);
2959
+ // Option text
2960
+ const textSpan = this.renderer.createElement('span');
2961
+ this.renderer.addClass(textSpan, 'option-text');
2962
+ const text = this.renderer.createText(optionLabel);
2963
+ this.renderer.appendChild(textSpan, text);
2964
+ this.renderer.appendChild(labelElement, textSpan);
2965
+ return labelElement;
2966
+ }
2967
+ createCheckIcon() {
2968
+ const svg = this.renderer.createElement('svg', 'svg');
2969
+ this.renderer.addClass(svg, 'check-icon');
2970
+ this.renderer.setAttribute(svg, 'width', '14');
2971
+ this.renderer.setAttribute(svg, 'height', '10');
2972
+ this.renderer.setAttribute(svg, 'viewBox', '0 0 10 8');
2973
+ this.renderer.setAttribute(svg, 'fill', 'none');
2974
+ this.renderer.setAttribute(svg, 'xmlns', 'http://www.w3.org/2000/svg');
2975
+ const path = this.renderer.createElement('path', 'svg');
2976
+ this.renderer.setAttribute(path, 'd', 'M9 1L3.5 6.5L1 4');
2977
+ this.renderer.setAttribute(path, 'stroke', '#F59100');
2978
+ this.renderer.setAttribute(path, 'stroke-width', '1.6666');
2979
+ this.renderer.setAttribute(path, 'stroke-linecap', 'round');
2980
+ this.renderer.setAttribute(path, 'stroke-linejoin', 'round');
2981
+ this.renderer.appendChild(svg, path);
2982
+ return svg;
2983
+ }
2984
+ closeDropdown() {
2985
+ this.destroyDropdown();
2986
+ this.isOpen = false;
2987
+ this.onTouched();
2988
+ }
2989
+ destroyDropdown() {
2990
+ // Remove listeners
2991
+ if (this.scrollHandler) {
2992
+ this.scrollHandler();
2993
+ this.scrollHandler = null;
2994
+ }
2995
+ if (this.resizeHandler) {
2996
+ this.resizeHandler();
2997
+ this.resizeHandler = null;
2998
+ }
2999
+ if (this.dropdownElement) {
3000
+ this.renderer.removeChild(this.document.body, this.dropdownElement);
3001
+ this.dropdownElement = null;
3002
+ }
3003
+ if (this.backdropElement) {
3004
+ this.renderer.removeChild(this.document.body, this.backdropElement);
3005
+ this.backdropElement = null;
3006
+ }
3007
+ }
3008
+ toggleOption(option) {
3009
+ if (this.isOptionDisabled(option))
3010
+ return;
3011
+ const optionValue = this.getOptionValue(option);
3012
+ const index = this.value.indexOf(optionValue);
3013
+ if (index > -1) {
3014
+ this.value = this.value.filter(v => v !== optionValue);
3015
+ }
3016
+ else {
3017
+ this.value = [...this.value, optionValue];
3018
+ }
3019
+ this.onChange(this.value);
3020
+ }
3021
+ isSelected(value) {
3022
+ return this.value.includes(value);
3023
+ }
3024
+ getSelectedCount() {
3025
+ return this.value.length;
3026
+ }
3027
+ getSelectedLabels() {
3028
+ const allOptions = this.getAllOptions();
3029
+ const selectedOptions = allOptions.filter(opt => this.isSelected(this.getOptionValue(opt)));
3030
+ return selectedOptions.map(opt => this.getOptionLabel(opt)).join(', ');
3031
+ }
3032
+ writeValue(value) {
3033
+ this.value = Array.isArray(value) ? value : [];
3034
+ }
3035
+ registerOnChange(fn) {
3036
+ this.onChange = fn;
3037
+ }
3038
+ registerOnTouched(fn) {
3039
+ this.onTouched = fn;
3040
+ }
3041
+ setDisabledState(isDisabled) {
3042
+ this.disabled = isDisabled;
3043
+ }
3044
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiselectComponent, deps: [{ token: i0.Renderer2 }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component });
3045
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: MultiselectComponent, isStandalone: true, selector: "app-multiselect", inputs: { label: "label", id: "id", placeholder: "placeholder", options: "options", hasError: "hasError", errorMessage: "errorMessage", disabled: "disabled", displayKey: "displayKey", valueKey: "valueKey", customClass: "customClass" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
3046
+ {
3047
+ provide: NG_VALUE_ACCESSOR,
3048
+ useExisting: forwardRef(() => MultiselectComponent),
3049
+ multi: true
3050
+ }
3051
+ ], queries: [{ propertyName: "contentOptions", predicate: OptionComponent }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, read: ElementRef }], ngImport: i0, template: `
3052
+ <div class="multiselect-wrapper" [ngClass]="customClass">
3053
+ <label *ngIf="label" [for]="id">{{ label }}</label>
3054
+ <div class="multiselect-container">
3055
+ <div
3056
+ #trigger
3057
+ class="multiselect-header"
3058
+ (click)="toggleDropdown($event)"
3059
+ [class.disabled]="disabled"
3060
+ [class.open]="isOpen"
3061
+ [class.error]="hasError">
3062
+ <span class="multiselect-placeholder" *ngIf="getSelectedCount() === 0">
3063
+ {{ placeholder || 'Selecciona uno o más...' }}
3064
+ </span>
3065
+ <span class="multiselect-selected" *ngIf="getSelectedCount() > 0">
3066
+ {{ getSelectedLabels() }}
3067
+ </span>
3068
+ <svg class="multiselect-arrow" [class.open]="isOpen" width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
3069
+ <path d="M1 1.5L6 6.5L11 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3070
+ </svg>
3071
+ </div>
3072
+ </div>
3073
+ <div *ngIf="hasError && errorMessage" class="field-error">
3074
+ {{ errorMessage }}
3075
+ </div>
3076
+
3077
+ <!-- Hidden container for projected options -->
3078
+ <div style="display: none;">
3079
+ <ng-content></ng-content>
3080
+ </div>
3081
+ </div>
3082
+ `, isInline: true, styles: [".multiselect-wrapper{width:100%;margin-bottom:6px;padding:0 4px}.multiselect-wrapper label{display:block;margin-bottom:.5rem;font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;color:#585d61}.multiselect-container{position:relative;width:100%}.multiselect-header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border:1px solid #EAECF5;box-shadow:0 1px 2px #a1afec66;border-radius:8px;background:#fff;cursor:pointer;transition:all .2s;min-height:44px;height:44px}.multiselect-header:hover:not(.disabled){border-color:#fbd399}.multiselect-header:focus-within{border-color:#fbd399;box-shadow:0 0 0 4px #ffe8c8,0 1px 2px #0a0d120d}.multiselect-header.disabled{background:#f5f5f5;cursor:not-allowed;opacity:.6}.multiselect-header.error{border-color:#dc3545!important}.multiselect-header.error.open{box-shadow:0 0 0 3px #dc35451a!important}.multiselect-header .multiselect-placeholder{font-family:Quicksand,sans-serif;font-size:14px;color:#969a9c}.multiselect-header .multiselect-selected{font-family:Quicksand,sans-serif;font-size:14px;color:#1a1d20;font-weight:500;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.multiselect-header .multiselect-arrow{color:#969a9c;transition:transform .3s ease;margin-left:.5rem;flex-shrink:0;display:flex;align-items:center}.multiselect-header .multiselect-arrow.open{transform:rotate(180deg)}.multiselect-dropdown{margin-top:8px;background:#fff;border:1px solid #EAECF5;border-radius:8px;box-shadow:0 10px 16px -4px #edeffb;max-height:290px!important;width:100%;overflow-x:hidden;overflow-y:auto;animation:dropdownSlide .25s cubic-bezier(.4,0,.2,1)}.multiselect-dropdown::-webkit-scrollbar{width:8px}.multiselect-dropdown::-webkit-scrollbar-track{background:#f1f1f1;border-radius:0 12px 12px 0}.multiselect-dropdown::-webkit-scrollbar-thumb{background:#d5d7d8;border-radius:4px}.multiselect-dropdown::-webkit-scrollbar-thumb:hover{background:#969a9c}@keyframes dropdownSlide{0%{opacity:0;transform:translateY(-8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}.multiselect-option{display:flex!important;align-items:center;padding:.6rem 1.25rem;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);border-bottom:1px solid #F1F2F4;gap:1rem;margin:0!important;position:relative}.multiselect-option:first-child{border-radius:12px 12px 0 0}.multiselect-option:last-child{border-bottom:none;border-radius:0 0 12px 12px}.multiselect-option:hover:not(.disabled){background:linear-gradient(90deg,#fff9f0,#fffef9)}.multiselect-option:hover:not(.disabled):before{opacity:.5}.multiselect-option.disabled{opacity:.5;cursor:not-allowed;background:#f8f9fc}.multiselect-option.disabled:hover{transform:none;background:#f8f9fc}.multiselect-option .option-checkbox{position:relative;display:flex;align-items:center;flex-shrink:0}.multiselect-option .option-checkbox input[type=checkbox]{position:absolute;opacity:0;cursor:pointer;width:22px;height:22px;margin:0}.multiselect-option .option-checkbox .checkbox-custom{width:22px;height:22px;border:2.5px solid #D5D7D8;border-radius:6px;display:flex;align-items:center;justify-content:center;transition:all .25s cubic-bezier(.4,0,.2,1);background:#fff;position:relative}.multiselect-option .option-checkbox .checkbox-custom:after{content:\"\";position:absolute;width:100%;height:100%;border-radius:4px;background:#f59100;opacity:0;transform:scale(.5);transition:all .25s cubic-bezier(.4,0,.2,1)}.multiselect-option .option-checkbox .checkbox-custom.checked{background:#fff;border-color:#f59100;border-width:2.5px;transform:scale(1.05)}.multiselect-option .option-checkbox .checkbox-custom.checked:after{opacity:0}.multiselect-option .option-checkbox .checkbox-custom .check-icon{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;animation:checkPop .3s cubic-bezier(.68,-.55,.265,1.55)}.multiselect-option .option-checkbox input[type=checkbox]:hover~.checkbox-custom:not(.checked){border-color:#f26d00;transform:scale(1.05)}.multiselect-option .option-text{flex:1;font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;color:#1a1d20;line-height:1.5;transition:color .2s ease,font-weight .2s ease}@keyframes checkPop{0%{transform:scale(0);opacity:0}50%{transform:scale(1.2)}to{transform:scale(1);opacity:1}}.field-error{color:#f04438;font-size:.875rem;margin-top:.25rem;font-family:Quicksand,sans-serif}::ng-deep .multiselect-custom-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:99999;pointer-events:auto}::ng-deep .multiselect-custom-dropdown{position:fixed;background:#fff;border-radius:8px;overflow:hidden;z-index:1000;opacity:0;transform:translateY(-8px) scale(.98);transition:opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1)}::ng-deep .multiselect-custom-dropdown.multiselect-dropdown-open{opacity:1;transform:translateY(0) scale(1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] });
3083
+ }
3084
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiselectComponent, decorators: [{
3085
+ type: Component,
3086
+ args: [{ selector: 'app-multiselect', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], template: `
3087
+ <div class="multiselect-wrapper" [ngClass]="customClass">
3088
+ <label *ngIf="label" [for]="id">{{ label }}</label>
3089
+ <div class="multiselect-container">
3090
+ <div
3091
+ #trigger
3092
+ class="multiselect-header"
3093
+ (click)="toggleDropdown($event)"
3094
+ [class.disabled]="disabled"
3095
+ [class.open]="isOpen"
3096
+ [class.error]="hasError">
3097
+ <span class="multiselect-placeholder" *ngIf="getSelectedCount() === 0">
3098
+ {{ placeholder || 'Selecciona uno o más...' }}
3099
+ </span>
3100
+ <span class="multiselect-selected" *ngIf="getSelectedCount() > 0">
3101
+ {{ getSelectedLabels() }}
3102
+ </span>
3103
+ <svg class="multiselect-arrow" [class.open]="isOpen" width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
3104
+ <path d="M1 1.5L6 6.5L11 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
3105
+ </svg>
3106
+ </div>
3107
+ </div>
3108
+ <div *ngIf="hasError && errorMessage" class="field-error">
3109
+ {{ errorMessage }}
3110
+ </div>
3111
+
3112
+ <!-- Hidden container for projected options -->
3113
+ <div style="display: none;">
3114
+ <ng-content></ng-content>
3115
+ </div>
3116
+ </div>
3117
+ `, providers: [
3118
+ {
3119
+ provide: NG_VALUE_ACCESSOR,
3120
+ useExisting: forwardRef(() => MultiselectComponent),
3121
+ multi: true
3122
+ }
3123
+ ], styles: [".multiselect-wrapper{width:100%;margin-bottom:6px;padding:0 4px}.multiselect-wrapper label{display:block;margin-bottom:.5rem;font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;color:#585d61}.multiselect-container{position:relative;width:100%}.multiselect-header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border:1px solid #EAECF5;box-shadow:0 1px 2px #a1afec66;border-radius:8px;background:#fff;cursor:pointer;transition:all .2s;min-height:44px;height:44px}.multiselect-header:hover:not(.disabled){border-color:#fbd399}.multiselect-header:focus-within{border-color:#fbd399;box-shadow:0 0 0 4px #ffe8c8,0 1px 2px #0a0d120d}.multiselect-header.disabled{background:#f5f5f5;cursor:not-allowed;opacity:.6}.multiselect-header.error{border-color:#dc3545!important}.multiselect-header.error.open{box-shadow:0 0 0 3px #dc35451a!important}.multiselect-header .multiselect-placeholder{font-family:Quicksand,sans-serif;font-size:14px;color:#969a9c}.multiselect-header .multiselect-selected{font-family:Quicksand,sans-serif;font-size:14px;color:#1a1d20;font-weight:500;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.multiselect-header .multiselect-arrow{color:#969a9c;transition:transform .3s ease;margin-left:.5rem;flex-shrink:0;display:flex;align-items:center}.multiselect-header .multiselect-arrow.open{transform:rotate(180deg)}.multiselect-dropdown{margin-top:8px;background:#fff;border:1px solid #EAECF5;border-radius:8px;box-shadow:0 10px 16px -4px #edeffb;max-height:290px!important;width:100%;overflow-x:hidden;overflow-y:auto;animation:dropdownSlide .25s cubic-bezier(.4,0,.2,1)}.multiselect-dropdown::-webkit-scrollbar{width:8px}.multiselect-dropdown::-webkit-scrollbar-track{background:#f1f1f1;border-radius:0 12px 12px 0}.multiselect-dropdown::-webkit-scrollbar-thumb{background:#d5d7d8;border-radius:4px}.multiselect-dropdown::-webkit-scrollbar-thumb:hover{background:#969a9c}@keyframes dropdownSlide{0%{opacity:0;transform:translateY(-8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}.multiselect-option{display:flex!important;align-items:center;padding:.6rem 1.25rem;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);border-bottom:1px solid #F1F2F4;gap:1rem;margin:0!important;position:relative}.multiselect-option:first-child{border-radius:12px 12px 0 0}.multiselect-option:last-child{border-bottom:none;border-radius:0 0 12px 12px}.multiselect-option:hover:not(.disabled){background:linear-gradient(90deg,#fff9f0,#fffef9)}.multiselect-option:hover:not(.disabled):before{opacity:.5}.multiselect-option.disabled{opacity:.5;cursor:not-allowed;background:#f8f9fc}.multiselect-option.disabled:hover{transform:none;background:#f8f9fc}.multiselect-option .option-checkbox{position:relative;display:flex;align-items:center;flex-shrink:0}.multiselect-option .option-checkbox input[type=checkbox]{position:absolute;opacity:0;cursor:pointer;width:22px;height:22px;margin:0}.multiselect-option .option-checkbox .checkbox-custom{width:22px;height:22px;border:2.5px solid #D5D7D8;border-radius:6px;display:flex;align-items:center;justify-content:center;transition:all .25s cubic-bezier(.4,0,.2,1);background:#fff;position:relative}.multiselect-option .option-checkbox .checkbox-custom:after{content:\"\";position:absolute;width:100%;height:100%;border-radius:4px;background:#f59100;opacity:0;transform:scale(.5);transition:all .25s cubic-bezier(.4,0,.2,1)}.multiselect-option .option-checkbox .checkbox-custom.checked{background:#fff;border-color:#f59100;border-width:2.5px;transform:scale(1.05)}.multiselect-option .option-checkbox .checkbox-custom.checked:after{opacity:0}.multiselect-option .option-checkbox .checkbox-custom .check-icon{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;animation:checkPop .3s cubic-bezier(.68,-.55,.265,1.55)}.multiselect-option .option-checkbox input[type=checkbox]:hover~.checkbox-custom:not(.checked){border-color:#f26d00;transform:scale(1.05)}.multiselect-option .option-text{flex:1;font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;color:#1a1d20;line-height:1.5;transition:color .2s ease,font-weight .2s ease}@keyframes checkPop{0%{transform:scale(0);opacity:0}50%{transform:scale(1.2)}to{transform:scale(1);opacity:1}}.field-error{color:#f04438;font-size:.875rem;margin-top:.25rem;font-family:Quicksand,sans-serif}::ng-deep .multiselect-custom-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:99999;pointer-events:auto}::ng-deep .multiselect-custom-dropdown{position:fixed;background:#fff;border-radius:8px;overflow:hidden;z-index:1000;opacity:0;transform:translateY(-8px) scale(.98);transition:opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1)}::ng-deep .multiselect-custom-dropdown.multiselect-dropdown-open{opacity:1;transform:translateY(0) scale(1)}\n"] }]
3124
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: Document, decorators: [{
3125
+ type: Inject,
3126
+ args: [DOCUMENT]
3127
+ }] }], propDecorators: { label: [{
3128
+ type: Input
3129
+ }], id: [{
3130
+ type: Input
3131
+ }], placeholder: [{
3132
+ type: Input
3133
+ }], options: [{
3134
+ type: Input
3135
+ }], hasError: [{
3136
+ type: Input
3137
+ }], errorMessage: [{
3138
+ type: Input
3139
+ }], disabled: [{
3140
+ type: Input
3141
+ }], displayKey: [{
3142
+ type: Input
3143
+ }], valueKey: [{
3144
+ type: Input
3145
+ }], customClass: [{
3146
+ type: Input
3147
+ }], trigger: [{
3148
+ type: ViewChild,
3149
+ args: ['trigger', { read: ElementRef }]
3150
+ }], contentOptions: [{
3151
+ type: ContentChildren,
3152
+ args: [OptionComponent]
3153
+ }], onDocumentClick: [{
3154
+ type: HostListener,
3155
+ args: ['document:click', ['$event']]
3156
+ }] } });
3157
+
3158
+ class PhoneInputComponent {
3159
+ label = 'Teléfono';
3160
+ hasError = false;
3161
+ errorMessage = '';
3162
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PhoneInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3163
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PhoneInputComponent, isStandalone: true, selector: "app-phone-input", inputs: { label: "label", hasError: "hasError", errorMessage: "errorMessage" }, ngImport: i0, template: `
3164
+ <div class="svu-phone-input" [class.svu-phone-input--error]="hasError">
3165
+ <label *ngIf="label" class="svu-phone-input__label">
3166
+ {{ label }}
3167
+ </label>
3168
+
3169
+ <div class="svu-phone-input__field">
3170
+ <div class="svu-phone-input__country">
3171
+ <ng-content select="[countrySelect]"></ng-content>
3172
+ </div>
3173
+
3174
+ <div class="svu-phone-input__number">
3175
+ <ng-content select="[phoneInput]"></ng-content>
3176
+ </div>
3177
+ </div>
3178
+
3179
+ <span *ngIf="hasError && errorMessage" class="svu-phone-input__error">
3180
+ {{ errorMessage }}
3181
+ </span>
3182
+ </div>
3183
+ `, isInline: true, styles: [".svu-phone-input{display:flex;flex-direction:column;width:100%;margin-bottom:6px;padding:0 4px}.svu-phone-input__label{display:block;margin-bottom:.5rem;font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;color:#585d61}.svu-phone-input__field{position:relative;display:flex;align-items:stretch;min-height:44px;height:44px;border:1px solid #EAECF5;box-shadow:0 1px 2px #a1afec66;border-radius:8px;transition:all .2s ease;background:#fff}.svu-phone-input__field:hover{border-color:#fbd399}.svu-phone-input__field:focus-within{border-color:#fbd399;box-shadow:0 0 0 4px #ffe8c8,0 1px 2px #0a0d120d}.svu-phone-input__country{flex:0;width:120px;display:flex;align-items:stretch;min-width:64px}.svu-phone-input__number{flex:1;min-width:0;display:flex;align-items:stretch}.svu-phone-input.svu-phone-input--error .svu-phone-input__field{border-color:#dc3545!important}.svu-phone-input.svu-phone-input--error .svu-phone-input__field:focus-within{box-shadow:0 0 0 3px #dc35451a!important}.svu-phone-input__error{color:#f04438;font-size:.875rem;margin-top:.25rem;font-family:Quicksand,sans-serif}@media (max-width: 640px){.svu-phone-input__country{width:100px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
3184
+ }
3185
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PhoneInputComponent, decorators: [{
3186
+ type: Component,
3187
+ args: [{ selector: 'app-phone-input', standalone: true, imports: [CommonModule, InputComponent, SelectComponent], template: `
3188
+ <div class="svu-phone-input" [class.svu-phone-input--error]="hasError">
3189
+ <label *ngIf="label" class="svu-phone-input__label">
3190
+ {{ label }}
3191
+ </label>
3192
+
3193
+ <div class="svu-phone-input__field">
3194
+ <div class="svu-phone-input__country">
3195
+ <ng-content select="[countrySelect]"></ng-content>
3196
+ </div>
3197
+
3198
+ <div class="svu-phone-input__number">
3199
+ <ng-content select="[phoneInput]"></ng-content>
3200
+ </div>
3201
+ </div>
3202
+
3203
+ <span *ngIf="hasError && errorMessage" class="svu-phone-input__error">
3204
+ {{ errorMessage }}
3205
+ </span>
3206
+ </div>
3207
+ `, styles: [".svu-phone-input{display:flex;flex-direction:column;width:100%;margin-bottom:6px;padding:0 4px}.svu-phone-input__label{display:block;margin-bottom:.5rem;font-family:Quicksand,sans-serif;font-weight:500;font-size:14px;color:#585d61}.svu-phone-input__field{position:relative;display:flex;align-items:stretch;min-height:44px;height:44px;border:1px solid #EAECF5;box-shadow:0 1px 2px #a1afec66;border-radius:8px;transition:all .2s ease;background:#fff}.svu-phone-input__field:hover{border-color:#fbd399}.svu-phone-input__field:focus-within{border-color:#fbd399;box-shadow:0 0 0 4px #ffe8c8,0 1px 2px #0a0d120d}.svu-phone-input__country{flex:0;width:120px;display:flex;align-items:stretch;min-width:64px}.svu-phone-input__number{flex:1;min-width:0;display:flex;align-items:stretch}.svu-phone-input.svu-phone-input--error .svu-phone-input__field{border-color:#dc3545!important}.svu-phone-input.svu-phone-input--error .svu-phone-input__field:focus-within{box-shadow:0 0 0 3px #dc35451a!important}.svu-phone-input__error{color:#f04438;font-size:.875rem;margin-top:.25rem;font-family:Quicksand,sans-serif}@media (max-width: 640px){.svu-phone-input__country{width:100px}}\n"] }]
3208
+ }], propDecorators: { label: [{
3209
+ type: Input
3210
+ }], hasError: [{
3211
+ type: Input
3212
+ }], errorMessage: [{
3213
+ type: Input
3214
+ }] } });
3215
+
3216
+ class CopyInputComponent {
3217
+ value = '';
3218
+ icon = 'icon-copy-clipboard';
3219
+ copiedIcon = 'icon-done';
3220
+ ariaLabel = 'Copiar';
3221
+ copied = new EventEmitter();
3222
+ isCopied = false;
3223
+ timeoutRef;
3224
+ async copyToClipboard() {
3225
+ try {
3226
+ await navigator.clipboard.writeText(this.value);
3227
+ this.isCopied = true;
3228
+ this.copied.emit();
3229
+ clearTimeout(this.timeoutRef);
3230
+ this.timeoutRef = setTimeout(() => {
3231
+ this.isCopied = false;
3232
+ }, 1200);
3233
+ }
3234
+ catch (err) {
3235
+ console.error('Error copiando:', err);
3236
+ }
3237
+ }
3238
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CopyInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3239
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CopyInputComponent, isStandalone: true, selector: "copy-input", inputs: { value: "value", icon: "icon", copiedIcon: "copiedIcon", ariaLabel: "ariaLabel" }, outputs: { copied: "copied" }, ngImport: i0, template: "<div class=\"copy-input-wrapper\">\n\n <!-- Tooltip -->\n <div\n class=\"copy-tooltip\"\n *ngIf=\"isCopied\"\n >\n Copiado\n </div>\n\n <!-- Componente -->\n <div\n class=\"copy-input\"\n (click)=\"copyToClipboard()\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"ariaLabel\"\n (keydown.enter)=\"copyToClipboard()\"\n >\n <i\n class=\"copy-input__icon\"\n [ngClass]=\"isCopied ? copiedIcon : icon\">\n </i>\n\n <span class=\"copy-input__text\">\n {{ value }}\n </span>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.copy-input-wrapper{position:relative;display:inline-block;max-width:100%}.copy-tooltip{position:absolute;top:-2rem;left:50%;transform:translate(-50%);padding:.375rem .625rem;background:#2f2f2f;color:#fff;font-size:.75rem;border-radius:.375rem;white-space:nowrap;opacity:0;animation:fadeSlide .25s forwards}.copy-tooltip:after{content:\"\";position:absolute;bottom:-.375rem;left:50%;transform:translate(-50%);border-width:.375rem;border-style:solid;border-color:#2f2f2f transparent transparent transparent}@keyframes fadeSlide{0%{opacity:0;transform:translate(-50%,-5px)}to{opacity:1;transform:translate(-50%)}}.copy-input{display:flex;align-items:center;gap:.5rem;width:100%;box-sizing:border-box;padding:.625rem 1.125rem;border:2px solid #6D7275;border-radius:.5rem;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .2s ease,border-color .2s ease}.copy-input:hover{background:#f9f9f9;border-color:#d8d8d8}.copy-input:active{background:#f0f0f0}.copy-input:focus{outline-offset:2px}.copy-input__icon{font-size:1.1rem;color:#444;transition:transform .2s ease,color .2s ease}.copy-input__icon.icon-done{transform:scale(1.2);color:#27ae60}.copy-input__text{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Quicksand,sans-serif;font-weight:600;font-size:1rem;line-height:1.5rem;color:#2e353a}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
3240
+ }
3241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CopyInputComponent, decorators: [{
3242
+ type: Component,
3243
+ args: [{ selector: 'copy-input', standalone: true, imports: [
3244
+ CommonModule
3245
+ ], template: "<div class=\"copy-input-wrapper\">\n\n <!-- Tooltip -->\n <div\n class=\"copy-tooltip\"\n *ngIf=\"isCopied\"\n >\n Copiado\n </div>\n\n <!-- Componente -->\n <div\n class=\"copy-input\"\n (click)=\"copyToClipboard()\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"ariaLabel\"\n (keydown.enter)=\"copyToClipboard()\"\n >\n <i\n class=\"copy-input__icon\"\n [ngClass]=\"isCopied ? copiedIcon : icon\">\n </i>\n\n <span class=\"copy-input__text\">\n {{ value }}\n </span>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.copy-input-wrapper{position:relative;display:inline-block;max-width:100%}.copy-tooltip{position:absolute;top:-2rem;left:50%;transform:translate(-50%);padding:.375rem .625rem;background:#2f2f2f;color:#fff;font-size:.75rem;border-radius:.375rem;white-space:nowrap;opacity:0;animation:fadeSlide .25s forwards}.copy-tooltip:after{content:\"\";position:absolute;bottom:-.375rem;left:50%;transform:translate(-50%);border-width:.375rem;border-style:solid;border-color:#2f2f2f transparent transparent transparent}@keyframes fadeSlide{0%{opacity:0;transform:translate(-50%,-5px)}to{opacity:1;transform:translate(-50%)}}.copy-input{display:flex;align-items:center;gap:.5rem;width:100%;box-sizing:border-box;padding:.625rem 1.125rem;border:2px solid #6D7275;border-radius:.5rem;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .2s ease,border-color .2s ease}.copy-input:hover{background:#f9f9f9;border-color:#d8d8d8}.copy-input:active{background:#f0f0f0}.copy-input:focus{outline-offset:2px}.copy-input__icon{font-size:1.1rem;color:#444;transition:transform .2s ease,color .2s ease}.copy-input__icon.icon-done{transform:scale(1.2);color:#27ae60}.copy-input__text{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Quicksand,sans-serif;font-weight:600;font-size:1rem;line-height:1.5rem;color:#2e353a}\n"] }]
3246
+ }], propDecorators: { value: [{
3247
+ type: Input
3248
+ }], icon: [{
3249
+ type: Input
3250
+ }], copiedIcon: [{
3251
+ type: Input
3252
+ }], ariaLabel: [{
3253
+ type: Input
3254
+ }], copied: [{
3255
+ type: Output
3256
+ }] } });
3257
+
3258
+ class SnackbarComponent {
3259
+ snackbarService;
3260
+ snackbars = [];
3261
+ subscriptions = [];
3262
+ constructor(snackbarService) {
3263
+ this.snackbarService = snackbarService;
3264
+ }
3265
+ ngOnInit() {
3266
+ // Subscribe to new snackbars
3267
+ const snackbarSub = this.snackbarService.snackbar$.subscribe((snackbar) => {
3268
+ this.snackbars.push(snackbar);
3269
+ });
3270
+ this.subscriptions.push(snackbarSub);
3271
+ // Subscribe to dismiss events
3272
+ const dismissSub = this.snackbarService.dismiss$.subscribe((id) => {
3273
+ if (id === 'all') {
3274
+ this.snackbars = [];
3275
+ }
3276
+ else {
3277
+ this.snackbars = this.snackbars.filter(s => s.id !== id);
3278
+ }
3279
+ });
3280
+ this.subscriptions.push(dismissSub);
3281
+ }
3282
+ ngOnDestroy() {
3283
+ this.subscriptions.forEach(sub => sub.unsubscribe());
3284
+ }
3285
+ getSnackbarsByPosition(position) {
3286
+ return this.snackbars.filter(s => s.position === position);
3287
+ }
3288
+ dismiss(id) {
3289
+ this.snackbars = this.snackbars.filter(s => s.id !== id);
3290
+ this.snackbarService.dismiss(id);
3291
+ }
3292
+ handleAction(snackbar) {
3293
+ if (snackbar.actionCallback) {
3294
+ snackbar.actionCallback();
3295
+ }
3296
+ this.dismiss(snackbar.id);
3297
+ }
3298
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SnackbarComponent, deps: [{ token: SnackbarService }], target: i0.ɵɵFactoryTarget.Component });
3299
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SnackbarComponent, isStandalone: true, selector: "app-snackbar", ngImport: i0, template: `
3300
+ <!-- Top Right -->
3301
+ <div class="snackbar-container snackbar-container--top-right" *ngIf="getSnackbarsByPosition('top-right').length > 0">
3302
+ <div
3303
+ *ngFor="let snackbar of getSnackbarsByPosition('top-right')"
3304
+ class="snackbar"
3305
+ [class.snackbar--success]="snackbar.type === 'success'"
3306
+ [class.snackbar--error]="snackbar.type === 'error'"
3307
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3308
+ [class.snackbar--info]="snackbar.type === 'info'"
3309
+ >
3310
+ <div class="snackbar__icon">
3311
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3312
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3313
+ </svg>
3314
+ <svg *ngIf="snackbar.type === 'error'" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3315
+ <path d="M11.96 2.37695C13.2212 2.38797 14.4681 2.65061 15.627 3.14844C16.7858 3.64631 17.8337 4.37013 18.71 5.27734L18.7158 5.2832L18.7227 5.28906C19.63 6.1654 20.3537 7.21402 20.8516 8.37305C21.3494 9.53204 21.6111 10.7787 21.6221 12.04C21.633 13.3014 21.3927 14.5523 20.915 15.7197C20.4374 16.8872 19.7318 17.9479 18.8398 18.8398C17.9479 19.7318 16.8872 20.4374 15.7197 20.915C14.5523 21.3927 13.3014 21.633 12.04 21.6221C10.7787 21.6111 9.53204 21.3494 8.37305 20.8516C7.21402 20.3537 6.1654 19.63 5.28906 18.7227L5.2832 18.7158L5.27734 18.71L4.94531 18.374C4.19221 17.5705 3.58408 16.641 3.14844 15.627C2.65061 14.4681 2.38797 13.2212 2.37695 11.96C2.36599 10.6986 2.60632 9.44681 3.08398 8.2793C3.56165 7.11184 4.26724 6.05112 5.15918 5.15918C6.05112 4.26724 7.11184 3.56165 8.2793 3.08398C9.44681 2.60632 10.6986 2.36599 11.96 2.37695ZM13.6523 3.66797C11.7234 3.28574 9.7209 3.58451 7.9873 4.5127C6.25388 5.4409 4.89578 6.94166 4.14453 8.75879C3.39335 10.5759 3.29528 12.5973 3.86719 14.4785C4.43922 16.3599 5.64653 17.9847 7.28223 19.0762C8.91789 20.1676 10.8811 20.6587 12.8379 20.4648C14.7947 20.271 16.623 19.4038 18.0127 18.0127C18.8041 17.2243 19.4316 16.2872 19.8584 15.2549C20.2319 14.3515 20.4462 13.3914 20.4912 12.417L20.5 11.998C20.4981 10.0321 19.8148 8.12717 18.5664 6.6084C17.3178 5.08945 15.5811 4.05022 13.6523 3.66797ZM15 8.49414C15.0659 8.49416 15.1315 8.50686 15.1924 8.53223C15.2531 8.55755 15.3081 8.59493 15.3545 8.6416L15.3574 8.64453C15.4043 8.69099 15.4414 8.74672 15.4668 8.80762C15.4922 8.86855 15.5059 8.93399 15.5059 9C15.5058 9.06595 15.4922 9.1315 15.4668 9.19238C15.4414 9.25316 15.4042 9.3081 15.3574 9.35449V9.35547L13.0566 11.6455L12.7012 12L13.0566 12.3545L15.3574 14.6445C15.4043 14.691 15.4414 14.7467 15.4668 14.8076C15.4922 14.8685 15.5059 14.934 15.5059 15C15.5058 15.0659 15.4922 15.1315 15.4668 15.1924C15.4414 15.2532 15.4042 15.3081 15.3574 15.3545L15.3545 15.3574C15.3081 15.4042 15.2532 15.4414 15.1924 15.4668C15.1315 15.4922 15.0659 15.5058 15 15.5059C14.934 15.5059 14.8685 15.4922 14.8076 15.4668C14.7467 15.4414 14.691 15.4043 14.6445 15.3574L12.3545 13.0566L12 12.7012L11.6455 13.0566L9.35547 15.3574H9.35449C9.3081 15.4042 9.25316 15.4414 9.19238 15.4668C9.1315 15.4922 9.06595 15.5058 9 15.5059C8.93399 15.5059 8.86855 15.4922 8.80762 15.4668C8.74672 15.4414 8.69099 15.4043 8.64453 15.3574L8.6416 15.3545C8.59493 15.3081 8.55755 15.2531 8.53223 15.1924C8.50686 15.1315 8.49416 15.0659 8.49414 15C8.49414 14.9341 8.50688 14.8685 8.53223 14.8076C8.55761 14.7467 8.59475 14.691 8.6416 14.6445H8.64258L10.9424 12.3545L11.2988 12L10.9424 11.6455L8.64258 9.35547C8.54859 9.26105 8.49614 9.13325 8.49609 9C8.49609 8.86631 8.54902 8.73809 8.64355 8.64355C8.73809 8.54902 8.86631 8.49609 9 8.49609C9.10009 8.49613 9.1972 8.52542 9.2793 8.58008L9.35645 8.64355L11.6455 10.9424L12 11.2988L12.3545 10.9424L14.6445 8.64258V8.6416C14.691 8.59475 14.7467 8.55761 14.8076 8.53223C14.8685 8.50688 14.9341 8.49414 15 8.49414Z" stroke="#F04438"/>
3316
+ </svg>
3317
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3318
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3319
+ </svg>
3320
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3321
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3322
+ </svg>
3323
+ </div>
3324
+ <div class="snackbar__content">
3325
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3326
+ </div>
3327
+ <button
3328
+ *ngIf="snackbar.action"
3329
+ class="snackbar__action"
3330
+ (click)="handleAction(snackbar)">
3331
+ {{ snackbar.action }}
3332
+ </button>
3333
+ <button
3334
+ class="snackbar__close"
3335
+ (click)="dismiss(snackbar.id)"
3336
+ aria-label="Cerrar">
3337
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3338
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3339
+ </svg>
3340
+ </button>
3341
+ </div>
3342
+ </div>
3343
+
3344
+ <!-- Top Left -->
3345
+ <div class="snackbar-container snackbar-container--top-left" *ngIf="getSnackbarsByPosition('top-left').length > 0">
3346
+ <div
3347
+ *ngFor="let snackbar of getSnackbarsByPosition('top-left')"
3348
+ class="snackbar"
3349
+ [class.snackbar--success]="snackbar.type === 'success'"
3350
+ [class.snackbar--error]="snackbar.type === 'error'"
3351
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3352
+ [class.snackbar--info]="snackbar.type === 'info'"
3353
+ >
3354
+ <div class="snackbar__icon">
3355
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3356
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3357
+ </svg>
3358
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3359
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3360
+ </svg>
3361
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3362
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3363
+ </svg>
3364
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3365
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3366
+ </svg>
3367
+ </div>
3368
+ <div class="snackbar__content">
3369
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3370
+ </div>
3371
+ <button
3372
+ *ngIf="snackbar.action"
3373
+ class="snackbar__action"
3374
+ (click)="handleAction(snackbar)">
3375
+ {{ snackbar.action }}
3376
+ </button>
3377
+ <button
3378
+ class="snackbar__close"
3379
+ (click)="dismiss(snackbar.id)"
3380
+ aria-label="Cerrar">
3381
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3382
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3383
+ </svg>
3384
+ </button>
3385
+ </div>
3386
+ </div>
3387
+
3388
+ <!-- Top Center -->
3389
+ <div class="snackbar-container snackbar-container--top-center" *ngIf="getSnackbarsByPosition('top-center').length > 0">
3390
+ <div
3391
+ *ngFor="let snackbar of getSnackbarsByPosition('top-center')"
3392
+ class="snackbar"
3393
+ [class.snackbar--success]="snackbar.type === 'success'"
3394
+ [class.snackbar--error]="snackbar.type === 'error'"
3395
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3396
+ [class.snackbar--info]="snackbar.type === 'info'"
3397
+ >
3398
+ <div class="snackbar__icon">
3399
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3400
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3401
+ </svg>
3402
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3403
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3404
+ </svg>
3405
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3406
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3407
+ </svg>
3408
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3409
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3410
+ </svg>
3411
+ </div>
3412
+ <div class="snackbar__content">
3413
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3414
+ </div>
3415
+ <button
3416
+ *ngIf="snackbar.action"
3417
+ class="snackbar__action"
3418
+ (click)="handleAction(snackbar)">
3419
+ {{ snackbar.action }}
3420
+ </button>
3421
+ <button
3422
+ class="snackbar__close"
3423
+ (click)="dismiss(snackbar.id)"
3424
+ aria-label="Cerrar">
3425
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3426
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3427
+ </svg>
3428
+ </button>
3429
+ </div>
3430
+ </div>
3431
+
3432
+ <!-- Bottom Right -->
3433
+ <div class="snackbar-container snackbar-container--bottom-right" *ngIf="getSnackbarsByPosition('bottom-right').length > 0">
3434
+ <div
3435
+ *ngFor="let snackbar of getSnackbarsByPosition('bottom-right')"
3436
+ class="snackbar"
3437
+ [class.snackbar--success]="snackbar.type === 'success'"
3438
+ [class.snackbar--error]="snackbar.type === 'error'"
3439
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3440
+ [class.snackbar--info]="snackbar.type === 'info'"
3441
+ >
3442
+ <div class="snackbar__icon">
3443
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3444
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3445
+ </svg>
3446
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3447
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3448
+ </svg>
3449
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3450
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3451
+ </svg>
3452
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3453
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3454
+ </svg>
3455
+ </div>
3456
+ <div class="snackbar__content">
3457
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3458
+ </div>
3459
+ <button
3460
+ *ngIf="snackbar.action"
3461
+ class="snackbar__action"
3462
+ (click)="handleAction(snackbar)">
3463
+ {{ snackbar.action }}
3464
+ </button>
3465
+ <button
3466
+ class="snackbar__close"
3467
+ (click)="dismiss(snackbar.id)"
3468
+ aria-label="Cerrar">
3469
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3470
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3471
+ </svg>
3472
+ </button>
3473
+ </div>
3474
+ </div>
3475
+
3476
+ <!-- Bottom Left -->
3477
+ <div class="snackbar-container snackbar-container--bottom-left" *ngIf="getSnackbarsByPosition('bottom-left').length > 0">
3478
+ <div
3479
+ *ngFor="let snackbar of getSnackbarsByPosition('bottom-left')"
3480
+ class="snackbar"
3481
+ [class.snackbar--success]="snackbar.type === 'success'"
3482
+ [class.snackbar--error]="snackbar.type === 'error'"
3483
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3484
+ [class.snackbar--info]="snackbar.type === 'info'"
3485
+ >
3486
+ <div class="snackbar__icon">
3487
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3488
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3489
+ </svg>
3490
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3491
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3492
+ </svg>
3493
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3494
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3495
+ </svg>
3496
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3497
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3498
+ </svg>
3499
+ </div>
3500
+ <div class="snackbar__content">
3501
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3502
+ </div>
3503
+ <button
3504
+ *ngIf="snackbar.action"
3505
+ class="snackbar__action"
3506
+ (click)="handleAction(snackbar)">
3507
+ {{ snackbar.action }}
3508
+ </button>
3509
+ <button
3510
+ class="snackbar__close"
3511
+ (click)="dismiss(snackbar.id)"
3512
+ aria-label="Cerrar">
3513
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3514
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3515
+ </svg>
3516
+ </button>
3517
+ </div>
3518
+ </div>
3519
+
3520
+ <!-- Bottom Center -->
3521
+ <div class="snackbar-container snackbar-container--bottom-center" *ngIf="getSnackbarsByPosition('bottom-center').length > 0">
3522
+ <div
3523
+ *ngFor="let snackbar of getSnackbarsByPosition('bottom-center')"
3524
+ class="snackbar"
3525
+ [class.snackbar--success]="snackbar.type === 'success'"
3526
+ [class.snackbar--error]="snackbar.type === 'error'"
3527
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3528
+ [class.snackbar--info]="snackbar.type === 'info'"
3529
+ >
3530
+ <div class="snackbar__icon">
3531
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3532
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3533
+ </svg>
3534
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3535
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3536
+ </svg>
3537
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3538
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3539
+ </svg>
3540
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3541
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3542
+ </svg>
3543
+ </div>
3544
+ <div class="snackbar__content">
3545
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3546
+ </div>
3547
+ <button
3548
+ *ngIf="snackbar.action"
3549
+ class="snackbar__action"
3550
+ (click)="handleAction(snackbar)">
3551
+ {{ snackbar.action }}
3552
+ </button>
3553
+ <button
3554
+ class="snackbar__close"
3555
+ (click)="dismiss(snackbar.id)"
3556
+ aria-label="Cerrar">
3557
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3558
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3559
+ </svg>
3560
+ </button>
3561
+ </div>
3562
+ </div>
3563
+ `, isInline: true, styles: [".snackbar-container{position:fixed;z-index:999999;display:flex;flex-direction:column;gap:12px;max-width:644px;pointer-events:none}.snackbar-container--top-right{top:24px;right:24px}.snackbar-container--top-left{top:24px;left:24px}.snackbar-container--top-center{top:24px;left:50%;transform:translate(-50%)}.snackbar-container--bottom-right{bottom:24px;right:24px}.snackbar-container--bottom-left{bottom:24px;left:24px}.snackbar-container--bottom-center{bottom:24px;left:50%;transform:translate(-50%)}@media (max-width: 640px){.snackbar-container{left:16px!important;right:16px!important;max-width:none;transform:none!important}.snackbar-container--top-right,.snackbar-container--top-left,.snackbar-container--top-center{top:16px}.snackbar-container--bottom-right,.snackbar-container--bottom-left,.snackbar-container--bottom-center{bottom:16px}}.snackbar{display:flex;align-items:center;gap:12px;padding:16px;border-radius:8px;box-shadow:0 4px 12px #00000026;background:#fff;pointer-events:auto;min-width:300px;max-width:644px;animation:slideIn .3s ease-out}@keyframes slideIn{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@media (max-width: 640px){.snackbar{min-width:auto;max-width:none}}.snackbar--success{background:#f0fdf4;border:1px solid #22c55e}.snackbar--success .snackbar__icon{color:#22c55e}.snackbar--error{background:#fef3f2;border:1px solid #F04438}.snackbar--error .snackbar__icon{color:#f04438}.snackbar--warning{background:#fffbeb;border:1px solid #f59e0b}.snackbar--warning .snackbar__icon{color:#f59e0b}.snackbar--info{background:#eff6ff;border:1px solid #3b82f6}.snackbar--info .snackbar__icon{color:#3b82f6}.snackbar__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px}.snackbar__content{flex:1;min-width:0}.snackbar__message{margin:0;line-height:20px;word-wrap:break-word;font-family:Quicksand,sans-serif;font-weight:600;font-size:14px;color:#2e353a}.snackbar__action{flex-shrink:0;padding:6px 12px;border:none;border-radius:4px;background:transparent;color:inherit;font-size:14px;font-weight:600;cursor:pointer;transition:background-color .2s}.snackbar__action:hover{background:#0000000d}.snackbar__action:active{background:#0000001a}.snackbar__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:4px;background:transparent;color:#2e353a;cursor:pointer;transition:all .2s}.snackbar__close:hover{background:#0000000d;color:#1f2937}.snackbar__close:active{background:#0000001a}.snackbar__close svg{width:14px;height:14px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
3564
+ }
3565
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SnackbarComponent, decorators: [{
3566
+ type: Component,
3567
+ args: [{ selector: 'app-snackbar', standalone: true, imports: [CommonModule], template: `
3568
+ <!-- Top Right -->
3569
+ <div class="snackbar-container snackbar-container--top-right" *ngIf="getSnackbarsByPosition('top-right').length > 0">
3570
+ <div
3571
+ *ngFor="let snackbar of getSnackbarsByPosition('top-right')"
3572
+ class="snackbar"
3573
+ [class.snackbar--success]="snackbar.type === 'success'"
3574
+ [class.snackbar--error]="snackbar.type === 'error'"
3575
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3576
+ [class.snackbar--info]="snackbar.type === 'info'"
3577
+ >
3578
+ <div class="snackbar__icon">
3579
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3580
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3581
+ </svg>
3582
+ <svg *ngIf="snackbar.type === 'error'" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3583
+ <path d="M11.96 2.37695C13.2212 2.38797 14.4681 2.65061 15.627 3.14844C16.7858 3.64631 17.8337 4.37013 18.71 5.27734L18.7158 5.2832L18.7227 5.28906C19.63 6.1654 20.3537 7.21402 20.8516 8.37305C21.3494 9.53204 21.6111 10.7787 21.6221 12.04C21.633 13.3014 21.3927 14.5523 20.915 15.7197C20.4374 16.8872 19.7318 17.9479 18.8398 18.8398C17.9479 19.7318 16.8872 20.4374 15.7197 20.915C14.5523 21.3927 13.3014 21.633 12.04 21.6221C10.7787 21.6111 9.53204 21.3494 8.37305 20.8516C7.21402 20.3537 6.1654 19.63 5.28906 18.7227L5.2832 18.7158L5.27734 18.71L4.94531 18.374C4.19221 17.5705 3.58408 16.641 3.14844 15.627C2.65061 14.4681 2.38797 13.2212 2.37695 11.96C2.36599 10.6986 2.60632 9.44681 3.08398 8.2793C3.56165 7.11184 4.26724 6.05112 5.15918 5.15918C6.05112 4.26724 7.11184 3.56165 8.2793 3.08398C9.44681 2.60632 10.6986 2.36599 11.96 2.37695ZM13.6523 3.66797C11.7234 3.28574 9.7209 3.58451 7.9873 4.5127C6.25388 5.4409 4.89578 6.94166 4.14453 8.75879C3.39335 10.5759 3.29528 12.5973 3.86719 14.4785C4.43922 16.3599 5.64653 17.9847 7.28223 19.0762C8.91789 20.1676 10.8811 20.6587 12.8379 20.4648C14.7947 20.271 16.623 19.4038 18.0127 18.0127C18.8041 17.2243 19.4316 16.2872 19.8584 15.2549C20.2319 14.3515 20.4462 13.3914 20.4912 12.417L20.5 11.998C20.4981 10.0321 19.8148 8.12717 18.5664 6.6084C17.3178 5.08945 15.5811 4.05022 13.6523 3.66797ZM15 8.49414C15.0659 8.49416 15.1315 8.50686 15.1924 8.53223C15.2531 8.55755 15.3081 8.59493 15.3545 8.6416L15.3574 8.64453C15.4043 8.69099 15.4414 8.74672 15.4668 8.80762C15.4922 8.86855 15.5059 8.93399 15.5059 9C15.5058 9.06595 15.4922 9.1315 15.4668 9.19238C15.4414 9.25316 15.4042 9.3081 15.3574 9.35449V9.35547L13.0566 11.6455L12.7012 12L13.0566 12.3545L15.3574 14.6445C15.4043 14.691 15.4414 14.7467 15.4668 14.8076C15.4922 14.8685 15.5059 14.934 15.5059 15C15.5058 15.0659 15.4922 15.1315 15.4668 15.1924C15.4414 15.2532 15.4042 15.3081 15.3574 15.3545L15.3545 15.3574C15.3081 15.4042 15.2532 15.4414 15.1924 15.4668C15.1315 15.4922 15.0659 15.5058 15 15.5059C14.934 15.5059 14.8685 15.4922 14.8076 15.4668C14.7467 15.4414 14.691 15.4043 14.6445 15.3574L12.3545 13.0566L12 12.7012L11.6455 13.0566L9.35547 15.3574H9.35449C9.3081 15.4042 9.25316 15.4414 9.19238 15.4668C9.1315 15.4922 9.06595 15.5058 9 15.5059C8.93399 15.5059 8.86855 15.4922 8.80762 15.4668C8.74672 15.4414 8.69099 15.4043 8.64453 15.3574L8.6416 15.3545C8.59493 15.3081 8.55755 15.2531 8.53223 15.1924C8.50686 15.1315 8.49416 15.0659 8.49414 15C8.49414 14.9341 8.50688 14.8685 8.53223 14.8076C8.55761 14.7467 8.59475 14.691 8.6416 14.6445H8.64258L10.9424 12.3545L11.2988 12L10.9424 11.6455L8.64258 9.35547C8.54859 9.26105 8.49614 9.13325 8.49609 9C8.49609 8.86631 8.54902 8.73809 8.64355 8.64355C8.73809 8.54902 8.86631 8.49609 9 8.49609C9.10009 8.49613 9.1972 8.52542 9.2793 8.58008L9.35645 8.64355L11.6455 10.9424L12 11.2988L12.3545 10.9424L14.6445 8.64258V8.6416C14.691 8.59475 14.7467 8.55761 14.8076 8.53223C14.8685 8.50688 14.9341 8.49414 15 8.49414Z" stroke="#F04438"/>
3584
+ </svg>
3585
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3586
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3587
+ </svg>
3588
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3589
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3590
+ </svg>
3591
+ </div>
3592
+ <div class="snackbar__content">
3593
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3594
+ </div>
3595
+ <button
3596
+ *ngIf="snackbar.action"
3597
+ class="snackbar__action"
3598
+ (click)="handleAction(snackbar)">
3599
+ {{ snackbar.action }}
3600
+ </button>
3601
+ <button
3602
+ class="snackbar__close"
3603
+ (click)="dismiss(snackbar.id)"
3604
+ aria-label="Cerrar">
3605
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3606
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3607
+ </svg>
3608
+ </button>
3609
+ </div>
3610
+ </div>
3611
+
3612
+ <!-- Top Left -->
3613
+ <div class="snackbar-container snackbar-container--top-left" *ngIf="getSnackbarsByPosition('top-left').length > 0">
3614
+ <div
3615
+ *ngFor="let snackbar of getSnackbarsByPosition('top-left')"
3616
+ class="snackbar"
3617
+ [class.snackbar--success]="snackbar.type === 'success'"
3618
+ [class.snackbar--error]="snackbar.type === 'error'"
3619
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3620
+ [class.snackbar--info]="snackbar.type === 'info'"
3621
+ >
3622
+ <div class="snackbar__icon">
3623
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3624
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3625
+ </svg>
3626
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3627
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3628
+ </svg>
3629
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3630
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3631
+ </svg>
3632
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3633
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3634
+ </svg>
3635
+ </div>
3636
+ <div class="snackbar__content">
3637
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3638
+ </div>
3639
+ <button
3640
+ *ngIf="snackbar.action"
3641
+ class="snackbar__action"
3642
+ (click)="handleAction(snackbar)">
3643
+ {{ snackbar.action }}
3644
+ </button>
3645
+ <button
3646
+ class="snackbar__close"
3647
+ (click)="dismiss(snackbar.id)"
3648
+ aria-label="Cerrar">
3649
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3650
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3651
+ </svg>
3652
+ </button>
3653
+ </div>
3654
+ </div>
3655
+
3656
+ <!-- Top Center -->
3657
+ <div class="snackbar-container snackbar-container--top-center" *ngIf="getSnackbarsByPosition('top-center').length > 0">
3658
+ <div
3659
+ *ngFor="let snackbar of getSnackbarsByPosition('top-center')"
3660
+ class="snackbar"
3661
+ [class.snackbar--success]="snackbar.type === 'success'"
3662
+ [class.snackbar--error]="snackbar.type === 'error'"
3663
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3664
+ [class.snackbar--info]="snackbar.type === 'info'"
3665
+ >
3666
+ <div class="snackbar__icon">
3667
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3668
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3669
+ </svg>
3670
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3671
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3672
+ </svg>
3673
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3674
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3675
+ </svg>
3676
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3677
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3678
+ </svg>
3679
+ </div>
3680
+ <div class="snackbar__content">
3681
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3682
+ </div>
3683
+ <button
3684
+ *ngIf="snackbar.action"
3685
+ class="snackbar__action"
3686
+ (click)="handleAction(snackbar)">
3687
+ {{ snackbar.action }}
3688
+ </button>
3689
+ <button
3690
+ class="snackbar__close"
3691
+ (click)="dismiss(snackbar.id)"
3692
+ aria-label="Cerrar">
3693
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3694
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3695
+ </svg>
3696
+ </button>
3697
+ </div>
3698
+ </div>
3699
+
3700
+ <!-- Bottom Right -->
3701
+ <div class="snackbar-container snackbar-container--bottom-right" *ngIf="getSnackbarsByPosition('bottom-right').length > 0">
3702
+ <div
3703
+ *ngFor="let snackbar of getSnackbarsByPosition('bottom-right')"
3704
+ class="snackbar"
3705
+ [class.snackbar--success]="snackbar.type === 'success'"
3706
+ [class.snackbar--error]="snackbar.type === 'error'"
3707
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3708
+ [class.snackbar--info]="snackbar.type === 'info'"
3709
+ >
3710
+ <div class="snackbar__icon">
3711
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3712
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3713
+ </svg>
3714
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3715
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3716
+ </svg>
3717
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3718
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3719
+ </svg>
3720
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3721
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3722
+ </svg>
3723
+ </div>
3724
+ <div class="snackbar__content">
3725
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3726
+ </div>
3727
+ <button
3728
+ *ngIf="snackbar.action"
3729
+ class="snackbar__action"
3730
+ (click)="handleAction(snackbar)">
3731
+ {{ snackbar.action }}
3732
+ </button>
3733
+ <button
3734
+ class="snackbar__close"
3735
+ (click)="dismiss(snackbar.id)"
3736
+ aria-label="Cerrar">
3737
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3738
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3739
+ </svg>
3740
+ </button>
3741
+ </div>
3742
+ </div>
3743
+
3744
+ <!-- Bottom Left -->
3745
+ <div class="snackbar-container snackbar-container--bottom-left" *ngIf="getSnackbarsByPosition('bottom-left').length > 0">
3746
+ <div
3747
+ *ngFor="let snackbar of getSnackbarsByPosition('bottom-left')"
3748
+ class="snackbar"
3749
+ [class.snackbar--success]="snackbar.type === 'success'"
3750
+ [class.snackbar--error]="snackbar.type === 'error'"
3751
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3752
+ [class.snackbar--info]="snackbar.type === 'info'"
3753
+ >
3754
+ <div class="snackbar__icon">
3755
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3756
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3757
+ </svg>
3758
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3759
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3760
+ </svg>
3761
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3762
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3763
+ </svg>
3764
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3765
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3766
+ </svg>
3767
+ </div>
3768
+ <div class="snackbar__content">
3769
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3770
+ </div>
3771
+ <button
3772
+ *ngIf="snackbar.action"
3773
+ class="snackbar__action"
3774
+ (click)="handleAction(snackbar)">
3775
+ {{ snackbar.action }}
3776
+ </button>
3777
+ <button
3778
+ class="snackbar__close"
3779
+ (click)="dismiss(snackbar.id)"
3780
+ aria-label="Cerrar">
3781
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3782
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3783
+ </svg>
3784
+ </button>
3785
+ </div>
3786
+ </div>
3787
+
3788
+ <!-- Bottom Center -->
3789
+ <div class="snackbar-container snackbar-container--bottom-center" *ngIf="getSnackbarsByPosition('bottom-center').length > 0">
3790
+ <div
3791
+ *ngFor="let snackbar of getSnackbarsByPosition('bottom-center')"
3792
+ class="snackbar"
3793
+ [class.snackbar--success]="snackbar.type === 'success'"
3794
+ [class.snackbar--error]="snackbar.type === 'error'"
3795
+ [class.snackbar--warning]="snackbar.type === 'warning'"
3796
+ [class.snackbar--info]="snackbar.type === 'info'"
3797
+ >
3798
+ <div class="snackbar__icon">
3799
+ <svg *ngIf="snackbar.type === 'success'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3800
+ <path d="M16.6667 5L7.50004 14.1667L3.33337 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3801
+ </svg>
3802
+ <svg *ngIf="snackbar.type === 'error'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3803
+ <path d="M10 6V10M10 14H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3804
+ </svg>
3805
+ <svg *ngIf="snackbar.type === 'warning'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3806
+ <path d="M10 7V11M10 15H10.01M8.60001 3.5L1.95001 15C1.69137 15.4584 1.55396 15.9753 1.55189 16.5015C1.54982 17.0277 1.68317 17.5456 1.93827 18.006C2.19337 18.4663 2.56117 18.8535 3.00616 19.1305C3.45115 19.4075 3.95928 19.5648 4.48001 19.5882H17.52C18.0407 19.5648 18.5489 19.4075 18.9939 19.1305C19.4388 18.8535 19.8066 18.4663 20.0617 18.006C20.3168 17.5456 20.4502 17.0277 20.4481 16.5015C20.446 15.9753 20.3086 15.4584 20.05 15L13.4 3.5C13.1332 3.05942 12.7619 2.69355 12.3198 2.43406C11.8777 2.17458 11.3783 2.02954 10.87 2.00967C10.3617 1.98981 9.85362 2.09565 9.39278 2.31848C8.93194 2.5413 8.53223 2.87461 8.23001 3.29L8.60001 3.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3807
+ </svg>
3808
+ <svg *ngIf="snackbar.type === 'info'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3809
+ <path d="M10 14V10M10 6H10.01M18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3810
+ </svg>
3811
+ </div>
3812
+ <div class="snackbar__content">
3813
+ <p class="snackbar__message">{{ snackbar.message }}</p>
3814
+ </div>
3815
+ <button
3816
+ *ngIf="snackbar.action"
3817
+ class="snackbar__action"
3818
+ (click)="handleAction(snackbar)">
3819
+ {{ snackbar.action }}
3820
+ </button>
3821
+ <button
3822
+ class="snackbar__close"
3823
+ (click)="dismiss(snackbar.id)"
3824
+ aria-label="Cerrar">
3825
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
3826
+ <path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3827
+ </svg>
3828
+ </button>
3829
+ </div>
3830
+ </div>
3831
+ `, styles: [".snackbar-container{position:fixed;z-index:999999;display:flex;flex-direction:column;gap:12px;max-width:644px;pointer-events:none}.snackbar-container--top-right{top:24px;right:24px}.snackbar-container--top-left{top:24px;left:24px}.snackbar-container--top-center{top:24px;left:50%;transform:translate(-50%)}.snackbar-container--bottom-right{bottom:24px;right:24px}.snackbar-container--bottom-left{bottom:24px;left:24px}.snackbar-container--bottom-center{bottom:24px;left:50%;transform:translate(-50%)}@media (max-width: 640px){.snackbar-container{left:16px!important;right:16px!important;max-width:none;transform:none!important}.snackbar-container--top-right,.snackbar-container--top-left,.snackbar-container--top-center{top:16px}.snackbar-container--bottom-right,.snackbar-container--bottom-left,.snackbar-container--bottom-center{bottom:16px}}.snackbar{display:flex;align-items:center;gap:12px;padding:16px;border-radius:8px;box-shadow:0 4px 12px #00000026;background:#fff;pointer-events:auto;min-width:300px;max-width:644px;animation:slideIn .3s ease-out}@keyframes slideIn{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@media (max-width: 640px){.snackbar{min-width:auto;max-width:none}}.snackbar--success{background:#f0fdf4;border:1px solid #22c55e}.snackbar--success .snackbar__icon{color:#22c55e}.snackbar--error{background:#fef3f2;border:1px solid #F04438}.snackbar--error .snackbar__icon{color:#f04438}.snackbar--warning{background:#fffbeb;border:1px solid #f59e0b}.snackbar--warning .snackbar__icon{color:#f59e0b}.snackbar--info{background:#eff6ff;border:1px solid #3b82f6}.snackbar--info .snackbar__icon{color:#3b82f6}.snackbar__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px}.snackbar__content{flex:1;min-width:0}.snackbar__message{margin:0;line-height:20px;word-wrap:break-word;font-family:Quicksand,sans-serif;font-weight:600;font-size:14px;color:#2e353a}.snackbar__action{flex-shrink:0;padding:6px 12px;border:none;border-radius:4px;background:transparent;color:inherit;font-size:14px;font-weight:600;cursor:pointer;transition:background-color .2s}.snackbar__action:hover{background:#0000000d}.snackbar__action:active{background:#0000001a}.snackbar__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:4px;background:transparent;color:#2e353a;cursor:pointer;transition:all .2s}.snackbar__close:hover{background:#0000000d;color:#1f2937}.snackbar__close:active{background:#0000001a}.snackbar__close svg{width:14px;height:14px}\n"] }]
3832
+ }], ctorParameters: () => [{ type: SnackbarService }] });
3833
+
3834
+ /*
3835
+ * Public API Surface of @up_si_vale/sivale-componentes-angular
3836
+ */
3837
+ // Tokens
3838
+
3839
+ /**
3840
+ * Generated bundle index. Do not edit.
3841
+ */
3842
+
3843
+ export { ASSET_BASE_URL, AssetSourceDirective, ButtonComponent, CheckboxComponent, CopyInputComponent, DatePickerComponent, IconSourceDirective, InputComponent, LoaderComponent, MultiselectComponent, NoLeadingSpaceDirective, OnlyLettersDirective, OnlyNumberDirective, OptionComponent, PhoneInputComponent, RadioComponent, RfcDirective, SelectComponent, SelectPrefixDirective, SelectSuffixDirective, SnackbarComponent, SnackbarService, TextareaComponent, TooltipDirective };
3844
+ //# sourceMappingURL=up_si_vale-sivale-componentes-angular.mjs.map