@lesterarte/sefin-ui 0.0.9 → 0.0.10

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.
@@ -3099,6 +3099,461 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
3099
3099
  args: ['document:click', ['$event']]
3100
3100
  }] } });
3101
3101
 
3102
+ class DatepickerComponent {
3103
+ cdr;
3104
+ ngZone;
3105
+ containerRef;
3106
+ calendarRef;
3107
+ textfieldRef;
3108
+ value = null;
3109
+ placeholder = 'Selecciona una fecha';
3110
+ disabled = false;
3111
+ size = 'md';
3112
+ class = '';
3113
+ format = 'DD/MM/YYYY';
3114
+ mode = 'single';
3115
+ minDate;
3116
+ maxDate;
3117
+ showTodayButton = true;
3118
+ showClearButton = true;
3119
+ locale = 'es-ES';
3120
+ firstDayOfWeek = 1; // 0 = Sunday, 1 = Monday
3121
+ valueChange = new EventEmitter();
3122
+ dateSelected = new EventEmitter();
3123
+ isOpen = false;
3124
+ currentMonth = new Date();
3125
+ selectedDate = null;
3126
+ rangeStart = null;
3127
+ rangeEnd = null;
3128
+ displayValue = '';
3129
+ hoveredDate = null;
3130
+ monthsES = [
3131
+ 'Enero',
3132
+ 'Febrero',
3133
+ 'Marzo',
3134
+ 'Abril',
3135
+ 'Mayo',
3136
+ 'Junio',
3137
+ 'Julio',
3138
+ 'Agosto',
3139
+ 'Septiembre',
3140
+ 'Octubre',
3141
+ 'Noviembre',
3142
+ 'Diciembre',
3143
+ ];
3144
+ daysES = ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'];
3145
+ daysESFull = [
3146
+ 'Domingo',
3147
+ 'Lunes',
3148
+ 'Martes',
3149
+ 'Miércoles',
3150
+ 'Jueves',
3151
+ 'Viernes',
3152
+ 'Sábado',
3153
+ ];
3154
+ constructor(cdr, ngZone) {
3155
+ this.cdr = cdr;
3156
+ this.ngZone = ngZone;
3157
+ }
3158
+ ngOnInit() {
3159
+ this.initializeDates();
3160
+ this.updateDisplayValue();
3161
+ }
3162
+ ngOnChanges(changes) {
3163
+ if (changes['value']) {
3164
+ this.initializeDates();
3165
+ this.updateDisplayValue();
3166
+ }
3167
+ if (changes['mode']) {
3168
+ this.initializeDates();
3169
+ this.updateDisplayValue();
3170
+ }
3171
+ }
3172
+ ngOnDestroy() { }
3173
+ onClickOutside(event) {
3174
+ if (this.containerRef?.nativeElement && this.isOpen) {
3175
+ const clickedInside = this.containerRef.nativeElement.contains(event.target);
3176
+ if (!clickedInside) {
3177
+ this.closeCalendar();
3178
+ }
3179
+ }
3180
+ }
3181
+ onKeyDown(event) {
3182
+ if (event.key === 'Escape' && this.isOpen) {
3183
+ this.closeCalendar();
3184
+ }
3185
+ }
3186
+ initializeDates() {
3187
+ if (this.mode === 'single') {
3188
+ this.selectedDate = this.value instanceof Date ? new Date(this.value) : null;
3189
+ this.rangeStart = null;
3190
+ this.rangeEnd = null;
3191
+ if (this.selectedDate) {
3192
+ this.currentMonth = new Date(this.selectedDate);
3193
+ }
3194
+ }
3195
+ else {
3196
+ const range = this.value;
3197
+ this.selectedDate = null;
3198
+ this.rangeStart = range?.start ? new Date(range.start) : null;
3199
+ this.rangeEnd = range?.end ? new Date(range.end) : null;
3200
+ if (this.rangeStart) {
3201
+ this.currentMonth = new Date(this.rangeStart);
3202
+ }
3203
+ else if (this.rangeEnd) {
3204
+ this.currentMonth = new Date(this.rangeEnd);
3205
+ }
3206
+ }
3207
+ }
3208
+ toggleCalendar() {
3209
+ if (this.disabled)
3210
+ return;
3211
+ this.isOpen = !this.isOpen;
3212
+ if (this.isOpen && !this.currentMonth) {
3213
+ this.currentMonth = new Date();
3214
+ }
3215
+ }
3216
+ closeCalendar() {
3217
+ this.isOpen = false;
3218
+ this.hoveredDate = null;
3219
+ }
3220
+ onInputClick() {
3221
+ if (!this.disabled) {
3222
+ this.toggleCalendar();
3223
+ }
3224
+ }
3225
+ onInputFocus() {
3226
+ if (!this.disabled) {
3227
+ this.toggleCalendar();
3228
+ }
3229
+ }
3230
+ getDaysInMonth(date) {
3231
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
3232
+ }
3233
+ getFirstDayOfMonth(date) {
3234
+ const firstDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay();
3235
+ return this.firstDayOfWeek === 1 ? (firstDay === 0 ? 6 : firstDay - 1) : firstDay;
3236
+ }
3237
+ getCalendarDays() {
3238
+ const days = [];
3239
+ const daysInMonth = this.getDaysInMonth(this.currentMonth);
3240
+ const firstDay = this.getFirstDayOfMonth(this.currentMonth);
3241
+ // Add empty cells for days before the first day of the month
3242
+ for (let i = 0; i < firstDay; i++) {
3243
+ days.push(null);
3244
+ }
3245
+ // Add days of the month
3246
+ for (let day = 1; day <= daysInMonth; day++) {
3247
+ days.push(new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth(), day));
3248
+ }
3249
+ return days;
3250
+ }
3251
+ isToday(date) {
3252
+ const today = new Date();
3253
+ return (date.getDate() === today.getDate() &&
3254
+ date.getMonth() === today.getMonth() &&
3255
+ date.getFullYear() === today.getFullYear());
3256
+ }
3257
+ isSelected(date) {
3258
+ if (this.mode === 'single') {
3259
+ if (!this.selectedDate)
3260
+ return false;
3261
+ return (date.getDate() === this.selectedDate.getDate() &&
3262
+ date.getMonth() === this.selectedDate.getMonth() &&
3263
+ date.getFullYear() === this.selectedDate.getFullYear());
3264
+ }
3265
+ else {
3266
+ if (!this.rangeStart && !this.rangeEnd)
3267
+ return false;
3268
+ if (this.rangeStart && this.rangeEnd) {
3269
+ return ((date >= this.rangeStart && date <= this.rangeEnd) ||
3270
+ (date >= this.rangeEnd && date <= this.rangeStart));
3271
+ }
3272
+ if (this.rangeStart) {
3273
+ return (date.getDate() === this.rangeStart.getDate() &&
3274
+ date.getMonth() === this.rangeStart.getMonth() &&
3275
+ date.getFullYear() === this.rangeStart.getFullYear());
3276
+ }
3277
+ return false;
3278
+ }
3279
+ }
3280
+ isInRange(date) {
3281
+ if (this.mode !== 'range')
3282
+ return false;
3283
+ if (!this.rangeStart || !this.rangeEnd) {
3284
+ if (this.rangeStart && this.hoveredDate) {
3285
+ const start = this.rangeStart < this.hoveredDate ? this.rangeStart : this.hoveredDate;
3286
+ const end = this.rangeStart < this.hoveredDate ? this.hoveredDate : this.rangeStart;
3287
+ return date >= start && date <= end;
3288
+ }
3289
+ return false;
3290
+ }
3291
+ const start = this.rangeStart < this.rangeEnd ? this.rangeStart : this.rangeEnd;
3292
+ const end = this.rangeStart < this.rangeEnd ? this.rangeEnd : this.rangeStart;
3293
+ return date >= start && date <= end;
3294
+ }
3295
+ isDisabled(date) {
3296
+ if (this.minDate) {
3297
+ const min = new Date(this.minDate);
3298
+ min.setHours(0, 0, 0, 0);
3299
+ const dateCompare = new Date(date);
3300
+ dateCompare.setHours(0, 0, 0, 0);
3301
+ if (dateCompare < min)
3302
+ return true;
3303
+ }
3304
+ if (this.maxDate) {
3305
+ const max = new Date(this.maxDate);
3306
+ max.setHours(23, 59, 59, 999);
3307
+ const dateCompare = new Date(date);
3308
+ dateCompare.setHours(23, 59, 59, 999);
3309
+ if (dateCompare > max)
3310
+ return true;
3311
+ }
3312
+ return false;
3313
+ }
3314
+ onDayClick(date, event) {
3315
+ if (!date)
3316
+ return;
3317
+ event.preventDefault();
3318
+ event.stopPropagation();
3319
+ if (!this.isDisabled(date)) {
3320
+ this.selectDate(date);
3321
+ }
3322
+ }
3323
+ selectDate(date) {
3324
+ if (this.isDisabled(date))
3325
+ return;
3326
+ if (this.mode === 'single') {
3327
+ this.selectedDate = new Date(date);
3328
+ this.value = new Date(date);
3329
+ // Calculate and set display value
3330
+ const formattedDate = this.formatDate(this.selectedDate);
3331
+ // Update displayValue
3332
+ this.displayValue = formattedDate;
3333
+ // Update textfield using writeValue (ControlValueAccessor method)
3334
+ if (this.textfieldRef) {
3335
+ this.textfieldRef.writeValue(formattedDate);
3336
+ }
3337
+ // Force change detection
3338
+ this.cdr.detectChanges();
3339
+ // One more update after Angular processes the change
3340
+ setTimeout(() => {
3341
+ if (this.textfieldRef) {
3342
+ this.textfieldRef.writeValue(formattedDate);
3343
+ }
3344
+ this.cdr.detectChanges();
3345
+ }, 10);
3346
+ // Emit events
3347
+ this.valueChange.emit(this.value);
3348
+ this.dateSelected.emit(this.value);
3349
+ // Close calendar after a delay to ensure value is updated and visible
3350
+ setTimeout(() => {
3351
+ this.closeCalendar();
3352
+ }, 100);
3353
+ }
3354
+ else {
3355
+ if (!this.rangeStart || (this.rangeStart && this.rangeEnd)) {
3356
+ // Start new range
3357
+ this.rangeStart = new Date(date);
3358
+ this.rangeEnd = null;
3359
+ this.hoveredDate = null;
3360
+ const formattedDate = this.formatDate(this.rangeStart);
3361
+ const displayText = `${formattedDate} - ...`;
3362
+ this.displayValue = displayText;
3363
+ this.updateTextField(displayText);
3364
+ }
3365
+ else {
3366
+ // Complete range
3367
+ this.rangeEnd = new Date(date);
3368
+ const range = {
3369
+ start: this.rangeStart,
3370
+ end: this.rangeEnd,
3371
+ };
3372
+ this.value = range;
3373
+ const formattedValue = `${this.formatDate(range.start)} - ${this.formatDate(range.end)}`;
3374
+ this.displayValue = formattedValue;
3375
+ this.updateTextField(formattedValue);
3376
+ this.valueChange.emit(this.value);
3377
+ this.dateSelected.emit(this.value);
3378
+ // Close calendar after a delay to ensure value is updated
3379
+ setTimeout(() => {
3380
+ this.closeCalendar();
3381
+ }, 100);
3382
+ }
3383
+ }
3384
+ }
3385
+ updateTextField(value) {
3386
+ // This method is kept for compatibility but the main update is done in selectDate
3387
+ // Update displayValue
3388
+ this.displayValue = value;
3389
+ // Update via writeValue
3390
+ if (this.textfieldRef) {
3391
+ this.textfieldRef.writeValue(value);
3392
+ }
3393
+ // Force change detection
3394
+ this.cdr.detectChanges();
3395
+ }
3396
+ onDateHover(date) {
3397
+ if (this.mode === 'range' && this.rangeStart && !this.rangeEnd) {
3398
+ this.hoveredDate = new Date(date);
3399
+ }
3400
+ }
3401
+ previousMonth() {
3402
+ this.currentMonth = new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth() - 1, 1);
3403
+ }
3404
+ nextMonth() {
3405
+ this.currentMonth = new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth() + 1, 1);
3406
+ }
3407
+ goToToday() {
3408
+ const today = new Date();
3409
+ if (!this.isDisabled(today)) {
3410
+ this.selectDate(today);
3411
+ }
3412
+ }
3413
+ clearValue() {
3414
+ if (this.mode === 'single') {
3415
+ this.selectedDate = null;
3416
+ this.value = null;
3417
+ }
3418
+ else {
3419
+ this.rangeStart = null;
3420
+ this.rangeEnd = null;
3421
+ this.value = null;
3422
+ }
3423
+ this.updateDisplayValue();
3424
+ this.valueChange.emit(null);
3425
+ this.dateSelected.emit(null);
3426
+ this.closeCalendar();
3427
+ }
3428
+ formatDate(date) {
3429
+ if (!date)
3430
+ return '';
3431
+ const day = String(date.getDate()).padStart(2, '0');
3432
+ const month = String(date.getMonth() + 1).padStart(2, '0');
3433
+ const year = date.getFullYear();
3434
+ switch (this.format) {
3435
+ case 'DD/MM/YYYY':
3436
+ return `${day}/${month}/${year}`;
3437
+ case 'MM/DD/YYYY':
3438
+ return `${month}/${day}/${year}`;
3439
+ case 'YYYY-MM-DD':
3440
+ return `${year}-${month}-${day}`;
3441
+ case 'DD-MM-YYYY':
3442
+ return `${day}-${month}-${year}`;
3443
+ default:
3444
+ return `${day}/${month}/${year}`;
3445
+ }
3446
+ }
3447
+ updateDisplayValue() {
3448
+ const newValue = this.mode === 'single'
3449
+ ? (this.selectedDate ? this.formatDate(this.selectedDate) : '')
3450
+ : (() => {
3451
+ const range = this.value;
3452
+ if (range?.start && range?.end) {
3453
+ return `${this.formatDate(range.start)} - ${this.formatDate(range.end)}`;
3454
+ }
3455
+ else if (range?.start) {
3456
+ return `${this.formatDate(range.start)} - ...`;
3457
+ }
3458
+ else {
3459
+ return '';
3460
+ }
3461
+ })();
3462
+ // Update displayValue (for internal use)
3463
+ this.displayValue = newValue;
3464
+ // Update textfield using writeValue (ControlValueAccessor method)
3465
+ // Use setTimeout to ensure ViewChild is available
3466
+ setTimeout(() => {
3467
+ if (this.textfieldRef) {
3468
+ this.textfieldRef.writeValue(newValue);
3469
+ }
3470
+ this.cdr.detectChanges();
3471
+ }, 0);
3472
+ }
3473
+ getMonthName() {
3474
+ return this.monthsES[this.currentMonth.getMonth()];
3475
+ }
3476
+ getYear() {
3477
+ return this.currentMonth.getFullYear();
3478
+ }
3479
+ getDayNames() {
3480
+ const days = [...this.daysES];
3481
+ if (this.firstDayOfWeek === 1) {
3482
+ // Move Sunday to the end
3483
+ const sunday = days.shift();
3484
+ if (sunday)
3485
+ days.push(sunday);
3486
+ }
3487
+ return days;
3488
+ }
3489
+ get containerClasses() {
3490
+ return [
3491
+ 'sefin-datepicker',
3492
+ this.isOpen ? 'sefin-datepicker--open' : '',
3493
+ this.class,
3494
+ ]
3495
+ .filter(Boolean)
3496
+ .join(' ');
3497
+ }
3498
+ get todayDate() {
3499
+ return new Date();
3500
+ }
3501
+ isTodayDisabled() {
3502
+ return this.isDisabled(this.todayDate);
3503
+ }
3504
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatepickerComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
3505
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: DatepickerComponent, isStandalone: true, selector: "sefin-datepicker", inputs: { value: "value", placeholder: "placeholder", disabled: "disabled", size: "size", class: "class", format: "format", mode: "mode", minDate: "minDate", maxDate: "maxDate", showTodayButton: "showTodayButton", showClearButton: "showClearButton", locale: "locale", firstDayOfWeek: "firstDayOfWeek" }, outputs: { valueChange: "valueChange", dateSelected: "dateSelected" }, host: { listeners: { "document:click": "onClickOutside($event)", "document:keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["containerRef"], descendants: true }, { propertyName: "calendarRef", first: true, predicate: ["calendarRef"], descendants: true }, { propertyName: "textfieldRef", first: true, predicate: ["textfieldRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div [class]=\"containerClasses\" #containerRef>\n <div class=\"sefin-datepicker__wrapper\">\n <sefin-textfield\n #textfieldRef\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [size]=\"size\"\n [readonly]=\"true\"\n [trailingIcon]=\"'calendar'\"\n (click)=\"onInputClick()\"\n (focus)=\"onInputFocus()\"\n class=\"sefin-datepicker__input\"\n ></sefin-textfield>\n <div class=\"sefin-datepicker__actions\">\n <button\n *ngIf=\"displayValue && showClearButton && !disabled\"\n type=\"button\"\n class=\"sefin-datepicker__clear\"\n (click)=\"clearValue()\"\n aria-label=\"Limpiar fecha\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12 4L4 12M4 4L12 12\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n </div>\n\n <div\n *ngIf=\"isOpen\"\n #calendarRef\n class=\"sefin-datepicker__calendar\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"sefin-datepicker__calendar-header\">\n <button\n type=\"button\"\n class=\"sefin-datepicker__nav-button\"\n (click)=\"previousMonth()\"\n aria-label=\"Mes anterior\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M10 12L6 8L10 4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n <div class=\"sefin-datepicker__month-year\">\n <span class=\"sefin-datepicker__month\">{{ getMonthName() }}</span>\n <span class=\"sefin-datepicker__year\">{{ getYear() }}</span>\n </div>\n <button\n type=\"button\"\n class=\"sefin-datepicker__nav-button\"\n (click)=\"nextMonth()\"\n aria-label=\"Mes siguiente\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6 4L10 8L6 12\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n\n <div class=\"sefin-datepicker__calendar-body\">\n <div class=\"sefin-datepicker__weekdays\">\n <div\n *ngFor=\"let dayName of getDayNames()\"\n class=\"sefin-datepicker__weekday\"\n >\n {{ dayName }}\n </div>\n </div>\n <div class=\"sefin-datepicker__days\">\n <button\n *ngFor=\"let day of getCalendarDays(); let i = index\"\n type=\"button\"\n class=\"sefin-datepicker__day\"\n [class.sefin-datepicker__day--today]=\"day && isToday(day)\"\n [class.sefin-datepicker__day--selected]=\"day && isSelected(day)\"\n [class.sefin-datepicker__day--in-range]=\"day && isInRange(day)\"\n [class.sefin-datepicker__day--disabled]=\"day && isDisabled(day)\"\n [class.sefin-datepicker__day--empty]=\"!day\"\n [disabled]=\"!day || (day && isDisabled(day))\"\n (click)=\"day && !isDisabled(day) && selectDate(day); $event.stopPropagation(); $event.preventDefault()\"\n (mouseenter)=\"day && onDateHover(day)\"\n [attr.aria-label]=\"day ? formatDate(day) : ''\"\n >\n <span *ngIf=\"day\">{{ day.getDate() }}</span>\n </button>\n </div>\n </div>\n\n <div *ngIf=\"showTodayButton\" class=\"sefin-datepicker__calendar-footer\">\n <button\n type=\"button\"\n class=\"sefin-datepicker__today-button\"\n (click)=\"goToToday()\"\n [disabled]=\"isTodayDisabled()\"\n >\n Hoy\n </button>\n </div>\n </div>\n</div>\n\n", styles: [".sefin-datepicker{position:relative;width:100%}.sefin-datepicker__wrapper{position:relative;display:flex;align-items:center;width:100%}.sefin-datepicker__input{width:100%;cursor:pointer}.sefin-datepicker__input ::ng-deep .sefin-textfield__input{cursor:pointer}.sefin-datepicker__actions{position:absolute;right:var(--sefin-spacing-sm);display:flex;align-items:center;gap:var(--sefin-spacing-xs);z-index:1;pointer-events:none}.sefin-datepicker__clear{display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;background:transparent;border:none;border-radius:var(--sefin-radius-sm);color:var(--sefin-color-text-secondary);cursor:pointer;transition:all .2s ease-in-out;pointer-events:all}.sefin-datepicker__clear:hover{background-color:var(--sefin-color-surface-hover);color:var(--sefin-color-text)}.sefin-datepicker__clear:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-datepicker__clear svg{width:16px;height:16px}.sefin-datepicker__calendar{position:absolute;top:calc(100% + var(--sefin-spacing-xs));left:0;z-index:9999;background-color:var(--sefin-color-surface);border:1px solid var(--sefin-color-border);border-radius:var(--sefin-radius-md);box-shadow:var(--sefin-shadow-lg);padding:var(--sefin-spacing-md);min-width:300px;max-width:320px}.sefin-datepicker__calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--sefin-spacing-md)}.sefin-datepicker__nav-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:transparent;border:none;border-radius:var(--sefin-radius-sm);color:var(--sefin-color-text);cursor:pointer;transition:all .2s ease-in-out}.sefin-datepicker__nav-button:hover{background-color:var(--sefin-color-surface-hover)}.sefin-datepicker__nav-button:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-datepicker__nav-button svg{width:16px;height:16px}.sefin-datepicker__month-year{display:flex;align-items:center;gap:var(--sefin-spacing-xs);font-family:var(--sefin-font-family-base);font-size:var(--sefin-font-size-base);font-weight:var(--sefin-font-weight-semibold);line-height:var(--sefin-line-height-normal);color:var(--sefin-color-text)}.sefin-datepicker__month{text-transform:capitalize}.sefin-datepicker__year{color:var(--sefin-color-text-secondary)}.sefin-datepicker__calendar-body{margin-bottom:var(--sefin-spacing-sm)}.sefin-datepicker__weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--sefin-spacing-xs);margin-bottom:var(--sefin-spacing-xs)}.sefin-datepicker__weekday{display:flex;align-items:center;justify-content:center;height:32px;font-family:var(--sefin-font-family-base);font-size:var(--sefin-font-size-xs);font-weight:var(--sefin-font-weight-medium);line-height:var(--sefin-line-height-normal);color:var(--sefin-color-text-secondary);text-transform:uppercase;letter-spacing:.5px}.sefin-datepicker__days{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--sefin-spacing-xs)}.sefin-datepicker__day{display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;background:transparent;border:none;border-radius:var(--sefin-radius-sm);font-family:var(--sefin-font-family-base);font-size:var(--sefin-font-size-sm);font-weight:var(--sefin-font-weight-normal);line-height:var(--sefin-line-height-normal);color:var(--sefin-color-text);cursor:pointer;transition:all .15s ease-in-out;position:relative}.sefin-datepicker__day:hover:not(.sefin-datepicker__day--disabled):not(.sefin-datepicker__day--empty){background-color:var(--sefin-color-surface-hover)}.sefin-datepicker__day--today{font-weight:var(--sefin-font-weight-semibold);color:var(--sefin-color-primary)}.sefin-datepicker__day--today:before{content:\"\";position:absolute;bottom:4px;left:50%;transform:translate(-50%);width:4px;height:4px;background-color:var(--sefin-color-primary);border-radius:50%}.sefin-datepicker__day--selected{background-color:var(--sefin-color-primary);color:var(--sefin-color-surface);font-weight:var(--sefin-font-weight-semibold)}.sefin-datepicker__day--selected:before{display:none}.sefin-datepicker__day--in-range{background-color:var(--sefin-color-primary-light);color:var(--sefin-color-primary)}.sefin-datepicker__day--disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.sefin-datepicker__day--empty{cursor:default;pointer-events:none}.sefin-datepicker__day:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-datepicker__calendar-footer{display:flex;align-items:center;justify-content:center;padding-top:var(--sefin-spacing-sm);border-top:1px solid var(--sefin-color-border)}.sefin-datepicker__today-button{padding:var(--sefin-spacing-xs) var(--sefin-spacing-md);background:transparent;border:1px solid var(--sefin-color-border);border-radius:var(--sefin-radius-sm);font-family:var(--sefin-font-family-base);font-size:var(--sefin-font-size-sm);font-weight:var(--sefin-font-weight-medium);line-height:var(--sefin-line-height-normal);color:var(--sefin-color-text);cursor:pointer;transition:all .2s ease-in-out}.sefin-datepicker__today-button:hover:not(:disabled){background-color:var(--sefin-color-surface-hover);border-color:var(--sefin-color-border-focus)}.sefin-datepicker__today-button:disabled{opacity:.5;cursor:not-allowed}.sefin-datepicker__today-button:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-datepicker--open .sefin-datepicker__input ::ng-deep .sefin-textfield__input{border-color:var(--sefin-color-border-focus)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: TextFieldComponent, selector: "sefin-textfield", inputs: ["variant", "size", "type", "placeholder", "hint", "errorMessage", "required", "disabled", "readonly", "maxLength", "minLength", "pattern", "leadingIcon", "trailingIcon", "showCounter", "autocomplete", "name", "id", "class", "customValidator"], outputs: ["valueChange", "focused", "blurred", "trailingIconClick"] }], changeDetection: i0.ChangeDetectionStrategy.Default });
3506
+ }
3507
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatepickerComponent, decorators: [{
3508
+ type: Component,
3509
+ args: [{ selector: 'sefin-datepicker', standalone: true, imports: [CommonModule, FormsModule, TextFieldComponent, IconComponent], changeDetection: ChangeDetectionStrategy.Default, template: "<div [class]=\"containerClasses\" #containerRef>\n <div class=\"sefin-datepicker__wrapper\">\n <sefin-textfield\n #textfieldRef\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [size]=\"size\"\n [readonly]=\"true\"\n [trailingIcon]=\"'calendar'\"\n (click)=\"onInputClick()\"\n (focus)=\"onInputFocus()\"\n class=\"sefin-datepicker__input\"\n ></sefin-textfield>\n <div class=\"sefin-datepicker__actions\">\n <button\n *ngIf=\"displayValue && showClearButton && !disabled\"\n type=\"button\"\n class=\"sefin-datepicker__clear\"\n (click)=\"clearValue()\"\n aria-label=\"Limpiar fecha\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12 4L4 12M4 4L12 12\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n </div>\n\n <div\n *ngIf=\"isOpen\"\n #calendarRef\n class=\"sefin-datepicker__calendar\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"sefin-datepicker__calendar-header\">\n <button\n type=\"button\"\n class=\"sefin-datepicker__nav-button\"\n (click)=\"previousMonth()\"\n aria-label=\"Mes anterior\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M10 12L6 8L10 4\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n <div class=\"sefin-datepicker__month-year\">\n <span class=\"sefin-datepicker__month\">{{ getMonthName() }}</span>\n <span class=\"sefin-datepicker__year\">{{ getYear() }}</span>\n </div>\n <button\n type=\"button\"\n class=\"sefin-datepicker__nav-button\"\n (click)=\"nextMonth()\"\n aria-label=\"Mes siguiente\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6 4L10 8L6 12\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n\n <div class=\"sefin-datepicker__calendar-body\">\n <div class=\"sefin-datepicker__weekdays\">\n <div\n *ngFor=\"let dayName of getDayNames()\"\n class=\"sefin-datepicker__weekday\"\n >\n {{ dayName }}\n </div>\n </div>\n <div class=\"sefin-datepicker__days\">\n <button\n *ngFor=\"let day of getCalendarDays(); let i = index\"\n type=\"button\"\n class=\"sefin-datepicker__day\"\n [class.sefin-datepicker__day--today]=\"day && isToday(day)\"\n [class.sefin-datepicker__day--selected]=\"day && isSelected(day)\"\n [class.sefin-datepicker__day--in-range]=\"day && isInRange(day)\"\n [class.sefin-datepicker__day--disabled]=\"day && isDisabled(day)\"\n [class.sefin-datepicker__day--empty]=\"!day\"\n [disabled]=\"!day || (day && isDisabled(day))\"\n (click)=\"day && !isDisabled(day) && selectDate(day); $event.stopPropagation(); $event.preventDefault()\"\n (mouseenter)=\"day && onDateHover(day)\"\n [attr.aria-label]=\"day ? formatDate(day) : ''\"\n >\n <span *ngIf=\"day\">{{ day.getDate() }}</span>\n </button>\n </div>\n </div>\n\n <div *ngIf=\"showTodayButton\" class=\"sefin-datepicker__calendar-footer\">\n <button\n type=\"button\"\n class=\"sefin-datepicker__today-button\"\n (click)=\"goToToday()\"\n [disabled]=\"isTodayDisabled()\"\n >\n Hoy\n </button>\n </div>\n </div>\n</div>\n\n", styles: [".sefin-datepicker{position:relative;width:100%}.sefin-datepicker__wrapper{position:relative;display:flex;align-items:center;width:100%}.sefin-datepicker__input{width:100%;cursor:pointer}.sefin-datepicker__input ::ng-deep .sefin-textfield__input{cursor:pointer}.sefin-datepicker__actions{position:absolute;right:var(--sefin-spacing-sm);display:flex;align-items:center;gap:var(--sefin-spacing-xs);z-index:1;pointer-events:none}.sefin-datepicker__clear{display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;background:transparent;border:none;border-radius:var(--sefin-radius-sm);color:var(--sefin-color-text-secondary);cursor:pointer;transition:all .2s ease-in-out;pointer-events:all}.sefin-datepicker__clear:hover{background-color:var(--sefin-color-surface-hover);color:var(--sefin-color-text)}.sefin-datepicker__clear:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-datepicker__clear svg{width:16px;height:16px}.sefin-datepicker__calendar{position:absolute;top:calc(100% + var(--sefin-spacing-xs));left:0;z-index:9999;background-color:var(--sefin-color-surface);border:1px solid var(--sefin-color-border);border-radius:var(--sefin-radius-md);box-shadow:var(--sefin-shadow-lg);padding:var(--sefin-spacing-md);min-width:300px;max-width:320px}.sefin-datepicker__calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--sefin-spacing-md)}.sefin-datepicker__nav-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:transparent;border:none;border-radius:var(--sefin-radius-sm);color:var(--sefin-color-text);cursor:pointer;transition:all .2s ease-in-out}.sefin-datepicker__nav-button:hover{background-color:var(--sefin-color-surface-hover)}.sefin-datepicker__nav-button:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-datepicker__nav-button svg{width:16px;height:16px}.sefin-datepicker__month-year{display:flex;align-items:center;gap:var(--sefin-spacing-xs);font-family:var(--sefin-font-family-base);font-size:var(--sefin-font-size-base);font-weight:var(--sefin-font-weight-semibold);line-height:var(--sefin-line-height-normal);color:var(--sefin-color-text)}.sefin-datepicker__month{text-transform:capitalize}.sefin-datepicker__year{color:var(--sefin-color-text-secondary)}.sefin-datepicker__calendar-body{margin-bottom:var(--sefin-spacing-sm)}.sefin-datepicker__weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--sefin-spacing-xs);margin-bottom:var(--sefin-spacing-xs)}.sefin-datepicker__weekday{display:flex;align-items:center;justify-content:center;height:32px;font-family:var(--sefin-font-family-base);font-size:var(--sefin-font-size-xs);font-weight:var(--sefin-font-weight-medium);line-height:var(--sefin-line-height-normal);color:var(--sefin-color-text-secondary);text-transform:uppercase;letter-spacing:.5px}.sefin-datepicker__days{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--sefin-spacing-xs)}.sefin-datepicker__day{display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;background:transparent;border:none;border-radius:var(--sefin-radius-sm);font-family:var(--sefin-font-family-base);font-size:var(--sefin-font-size-sm);font-weight:var(--sefin-font-weight-normal);line-height:var(--sefin-line-height-normal);color:var(--sefin-color-text);cursor:pointer;transition:all .15s ease-in-out;position:relative}.sefin-datepicker__day:hover:not(.sefin-datepicker__day--disabled):not(.sefin-datepicker__day--empty){background-color:var(--sefin-color-surface-hover)}.sefin-datepicker__day--today{font-weight:var(--sefin-font-weight-semibold);color:var(--sefin-color-primary)}.sefin-datepicker__day--today:before{content:\"\";position:absolute;bottom:4px;left:50%;transform:translate(-50%);width:4px;height:4px;background-color:var(--sefin-color-primary);border-radius:50%}.sefin-datepicker__day--selected{background-color:var(--sefin-color-primary);color:var(--sefin-color-surface);font-weight:var(--sefin-font-weight-semibold)}.sefin-datepicker__day--selected:before{display:none}.sefin-datepicker__day--in-range{background-color:var(--sefin-color-primary-light);color:var(--sefin-color-primary)}.sefin-datepicker__day--disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.sefin-datepicker__day--empty{cursor:default;pointer-events:none}.sefin-datepicker__day:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-datepicker__calendar-footer{display:flex;align-items:center;justify-content:center;padding-top:var(--sefin-spacing-sm);border-top:1px solid var(--sefin-color-border)}.sefin-datepicker__today-button{padding:var(--sefin-spacing-xs) var(--sefin-spacing-md);background:transparent;border:1px solid var(--sefin-color-border);border-radius:var(--sefin-radius-sm);font-family:var(--sefin-font-family-base);font-size:var(--sefin-font-size-sm);font-weight:var(--sefin-font-weight-medium);line-height:var(--sefin-line-height-normal);color:var(--sefin-color-text);cursor:pointer;transition:all .2s ease-in-out}.sefin-datepicker__today-button:hover:not(:disabled){background-color:var(--sefin-color-surface-hover);border-color:var(--sefin-color-border-focus)}.sefin-datepicker__today-button:disabled{opacity:.5;cursor:not-allowed}.sefin-datepicker__today-button:focus-visible{outline:2px solid var(--sefin-color-border-focus);outline-offset:2px}.sefin-datepicker--open .sefin-datepicker__input ::ng-deep .sefin-textfield__input{border-color:var(--sefin-color-border-focus)}\n"] }]
3510
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }], propDecorators: { containerRef: [{
3511
+ type: ViewChild,
3512
+ args: ['containerRef', { static: false }]
3513
+ }], calendarRef: [{
3514
+ type: ViewChild,
3515
+ args: ['calendarRef', { static: false }]
3516
+ }], textfieldRef: [{
3517
+ type: ViewChild,
3518
+ args: ['textfieldRef', { static: false }]
3519
+ }], value: [{
3520
+ type: Input
3521
+ }], placeholder: [{
3522
+ type: Input
3523
+ }], disabled: [{
3524
+ type: Input
3525
+ }], size: [{
3526
+ type: Input
3527
+ }], class: [{
3528
+ type: Input
3529
+ }], format: [{
3530
+ type: Input
3531
+ }], mode: [{
3532
+ type: Input
3533
+ }], minDate: [{
3534
+ type: Input
3535
+ }], maxDate: [{
3536
+ type: Input
3537
+ }], showTodayButton: [{
3538
+ type: Input
3539
+ }], showClearButton: [{
3540
+ type: Input
3541
+ }], locale: [{
3542
+ type: Input
3543
+ }], firstDayOfWeek: [{
3544
+ type: Input
3545
+ }], valueChange: [{
3546
+ type: Output
3547
+ }], dateSelected: [{
3548
+ type: Output
3549
+ }], onClickOutside: [{
3550
+ type: HostListener,
3551
+ args: ['document:click', ['$event']]
3552
+ }], onKeyDown: [{
3553
+ type: HostListener,
3554
+ args: ['document:keydown', ['$event']]
3555
+ }] } });
3556
+
3102
3557
  /**
3103
3558
  * Molecules index
3104
3559
  */
@@ -3114,5 +3569,5 @@ const STYLES_PATH = './styles/index.scss';
3114
3569
  * Generated bundle index. Do not edit.
3115
3570
  */
3116
3571
 
3117
- export { AlertComponent, AutocompleteComponent, AvatarComponent, BORDER_RADIUS_TOKENS, BRAND_THEME, BadgeComponent, ButtonComponent, COLOR_TOKENS, CheckboxComponent, ChipComponent, ContainerComponent, DARK_THEME, DESIGN_TOKENS, DividerComponent, FabButtonComponent, IconButtonComponent, IconComponent, LIGHT_THEME, LinkComponent, ProgressBarComponent, RadioComponent, SHADOW_TOKENS, SPACING_TOKENS, STYLES_PATH, SelectComponent, SpinnerComponent, StackComponent, SwitchComponent, TYPOGRAPHY_TOKENS, TagComponent, TextFieldComponent, ThemeLoader, ToastComponent, TooltipComponent, TypographyComponent };
3572
+ export { AlertComponent, AutocompleteComponent, AvatarComponent, BORDER_RADIUS_TOKENS, BRAND_THEME, BadgeComponent, ButtonComponent, COLOR_TOKENS, CheckboxComponent, ChipComponent, ContainerComponent, DARK_THEME, DESIGN_TOKENS, DatepickerComponent, DividerComponent, FabButtonComponent, IconButtonComponent, IconComponent, LIGHT_THEME, LinkComponent, ProgressBarComponent, RadioComponent, SHADOW_TOKENS, SPACING_TOKENS, STYLES_PATH, SelectComponent, SpinnerComponent, StackComponent, SwitchComponent, TYPOGRAPHY_TOKENS, TagComponent, TextFieldComponent, ThemeLoader, ToastComponent, TooltipComponent, TypographyComponent };
3118
3573
  //# sourceMappingURL=lesterarte-sefin-ui.mjs.map