@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.
- package/esm2022/lib/atoms/button/button.component.mjs +55 -0
- package/esm2022/lib/atoms/checkbox/checkbox.component.mjs +174 -0
- package/esm2022/lib/atoms/date-picker/date-picker.component.mjs +835 -0
- package/esm2022/lib/atoms/input/input.component.mjs +218 -0
- package/esm2022/lib/atoms/loader/loader.component.mjs +81 -0
- package/esm2022/lib/atoms/radio/radio.component.mjs +142 -0
- package/esm2022/lib/atoms/textarea/textarea.component.mjs +126 -0
- package/esm2022/lib/directives/asset-source.directive.mjs +68 -0
- package/esm2022/lib/directives/icon-source.directive.mjs +65 -0
- package/esm2022/lib/directives/no-leading-space.directive.mjs +24 -0
- package/esm2022/lib/directives/only-letters.directive.mjs +25 -0
- package/esm2022/lib/directives/only-number.directive.mjs +21 -0
- package/esm2022/lib/directives/rfc.directive.mjs +67 -0
- package/esm2022/lib/directives/tooltip.directive.mjs +199 -0
- package/esm2022/lib/models/snackbar.models.mjs +2 -0
- package/esm2022/lib/molecules/copy-input/copy-input.component.mjs +46 -0
- package/esm2022/lib/molecules/multiselect/multiselect.component.mjs +466 -0
- package/esm2022/lib/molecules/option/option.component.mjs +55 -0
- package/esm2022/lib/molecules/phone-input/phone-input.component.mjs +64 -0
- package/esm2022/lib/molecules/select/select.component.mjs +498 -0
- package/esm2022/lib/molecules/snackbar/snackbar.component.mjs +581 -0
- package/esm2022/lib/services/snackbar.service.mjs +96 -0
- package/esm2022/lib/tokens/asset-base-url.token.mjs +10 -0
- package/esm2022/public-api.mjs +33 -0
- package/esm2022/up_si_vale-sivale-componentes-angular.mjs +5 -0
- package/fesm2022/up_si_vale-sivale-componentes-angular.mjs +3844 -0
- package/fesm2022/up_si_vale-sivale-componentes-angular.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/atoms/button/button.component.d.ts +20 -0
- package/lib/atoms/checkbox/checkbox.component.d.ts +31 -0
- package/lib/atoms/date-picker/date-picker.component.d.ts +134 -0
- package/lib/atoms/input/input.component.d.ts +35 -0
- package/lib/atoms/loader/loader.component.d.ts +10 -0
- package/lib/atoms/radio/radio.component.d.ts +25 -0
- package/lib/atoms/textarea/textarea.component.d.ts +27 -0
- package/lib/directives/asset-source.directive.d.ts +19 -0
- package/lib/directives/icon-source.directive.d.ts +18 -0
- package/lib/directives/no-leading-space.directive.d.ts +6 -0
- package/lib/directives/only-letters.directive.d.ts +7 -0
- package/lib/directives/only-number.directive.d.ts +6 -0
- package/lib/directives/rfc.directive.d.ts +12 -0
- package/lib/directives/tooltip.directive.d.ts +27 -0
- package/{src/lib/models/snackbar.models.ts → lib/models/snackbar.models.d.ts} +8 -10
- package/lib/molecules/copy-input/copy-input.component.d.ts +14 -0
- package/lib/molecules/multiselect/multiselect.component.d.ts +74 -0
- package/lib/molecules/option/option.component.d.ts +19 -0
- package/lib/molecules/phone-input/phone-input.component.d.ts +12 -0
- package/lib/molecules/select/select.component.d.ts +88 -0
- package/lib/molecules/snackbar/snackbar.component.d.ts +17 -0
- package/lib/services/snackbar.service.d.ts +40 -0
- package/{src/lib/tokens/asset-base-url.token.ts → lib/tokens/asset-base-url.token.d.ts} +1 -5
- package/package.json +30 -24
- package/{src/public-api.ts → public-api.d.ts} +0 -15
- package/ng-package.json +0 -9
- package/src/lib/atoms/button/button.component.html +0 -21
- package/src/lib/atoms/button/button.component.scss +0 -242
- package/src/lib/atoms/button/button.component.ts +0 -43
- package/src/lib/atoms/checkbox/checkbox.component.scss +0 -131
- package/src/lib/atoms/checkbox/checkbox.component.ts +0 -130
- package/src/lib/atoms/date-picker/date-picker.component.html +0 -295
- package/src/lib/atoms/date-picker/date-picker.component.scss +0 -1002
- package/src/lib/atoms/date-picker/date-picker.component.ts +0 -942
- package/src/lib/atoms/input/input.component.ts +0 -239
- package/src/lib/atoms/loader/loader.component.scss +0 -144
- package/src/lib/atoms/loader/loader.component.ts +0 -44
- package/src/lib/atoms/radio/radio.component.scss +0 -115
- package/src/lib/atoms/radio/radio.component.ts +0 -103
- package/src/lib/atoms/textarea/textarea.component.ts +0 -155
- package/src/lib/directives/asset-source.directive.ts +0 -64
- package/src/lib/directives/icon-source.directive.ts +0 -74
- package/src/lib/directives/no-leading-space.directive.ts +0 -18
- package/src/lib/directives/only-letters.directive.ts +0 -21
- package/src/lib/directives/only-number.directive.ts +0 -15
- package/src/lib/directives/rfc.directive.ts +0 -60
- package/src/lib/directives/tooltip.directive.ts +0 -211
- package/src/lib/molecules/copy-input/copy-input.component.html +0 -29
- package/src/lib/molecules/copy-input/copy-input.component.scss +0 -101
- package/src/lib/molecules/copy-input/copy-input.component.ts +0 -41
- package/src/lib/molecules/multiselect/multiselect.component.scss +0 -298
- package/src/lib/molecules/multiselect/multiselect.component.ts +0 -487
- package/src/lib/molecules/option/option.component.ts +0 -45
- package/src/lib/molecules/phone-input/phone-input.component.scss +0 -78
- package/src/lib/molecules/phone-input/phone-input.component.ts +0 -43
- package/src/lib/molecules/select/select.component.ts +0 -482
- package/src/lib/molecules/snackbar/snackbar.component.scss +0 -201
- package/src/lib/molecules/snackbar/snackbar.component.ts +0 -321
- package/src/lib/services/snackbar.service.ts +0 -103
- 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
|