@oneluiz/dual-datepicker 2.4.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +481 -101
- package/date-adapter.d.ts +116 -0
- package/dual-datepicker.component.d.ts +10 -3
- package/esm2022/date-adapter.mjs +12 -0
- package/esm2022/dual-datepicker.component.mjs +64 -26
- package/esm2022/native-date-adapter.mjs +112 -0
- package/esm2022/preset-utils.mjs +276 -0
- package/esm2022/public-api.mjs +6 -1
- package/fesm2022/oneluiz-dual-datepicker.mjs +458 -26
- package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -1
- package/native-date-adapter.d.ts +26 -0
- package/package.json +1 -1
- package/preset-utils.d.ts +91 -0
- package/public-api.d.ts +4 -1
|
@@ -1,9 +1,129 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, signal, computed, effect, forwardRef, HostListener, Output, Input, Component } from '@angular/core';
|
|
2
|
+
import { InjectionToken, Injectable, EventEmitter, inject, signal, computed, effect, forwardRef, HostListener, Output, Input, Component } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
5
|
import { FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Abstract class for date adapters.
|
|
9
|
+
* Allows the component to work with different date libraries (Date, DayJS, date-fns, Luxon, etc.)
|
|
10
|
+
*/
|
|
11
|
+
class DateAdapter {
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Injection token for DateAdapter
|
|
15
|
+
*/
|
|
16
|
+
const DATE_ADAPTER = new InjectionToken('DATE_ADAPTER');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Date adapter implementation for native JavaScript Date objects
|
|
20
|
+
* This is the default adapter used by the component
|
|
21
|
+
*/
|
|
22
|
+
class NativeDateAdapter extends DateAdapter {
|
|
23
|
+
parse(value) {
|
|
24
|
+
if (!value)
|
|
25
|
+
return null;
|
|
26
|
+
if (value instanceof Date) {
|
|
27
|
+
return new Date(value);
|
|
28
|
+
}
|
|
29
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
30
|
+
const date = new Date(value);
|
|
31
|
+
return this.isValid(date) ? date : null;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
format(date, format = 'YYYY-MM-DD') {
|
|
36
|
+
if (!this.isValid(date))
|
|
37
|
+
return '';
|
|
38
|
+
const year = date.getFullYear();
|
|
39
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
40
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
41
|
+
// Simple format implementation
|
|
42
|
+
switch (format) {
|
|
43
|
+
case 'YYYY-MM-DD':
|
|
44
|
+
return `${year}-${month}-${day}`;
|
|
45
|
+
case 'MM/DD/YYYY':
|
|
46
|
+
return `${month}/${day}/${year}`;
|
|
47
|
+
case 'DD/MM/YYYY':
|
|
48
|
+
return `${day}/${month}/${year}`;
|
|
49
|
+
default:
|
|
50
|
+
return `${year}-${month}-${day}`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
addDays(date, days) {
|
|
54
|
+
const result = this.clone(date);
|
|
55
|
+
result.setDate(result.getDate() + days);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
addMonths(date, months) {
|
|
59
|
+
const result = this.clone(date);
|
|
60
|
+
result.setMonth(result.getMonth() + months);
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
getYear(date) {
|
|
64
|
+
return date.getFullYear();
|
|
65
|
+
}
|
|
66
|
+
getMonth(date) {
|
|
67
|
+
return date.getMonth();
|
|
68
|
+
}
|
|
69
|
+
getDate(date) {
|
|
70
|
+
return date.getDate();
|
|
71
|
+
}
|
|
72
|
+
getDay(date) {
|
|
73
|
+
return date.getDay();
|
|
74
|
+
}
|
|
75
|
+
createDate(year, month, date) {
|
|
76
|
+
return new Date(year, month, date);
|
|
77
|
+
}
|
|
78
|
+
today() {
|
|
79
|
+
return new Date();
|
|
80
|
+
}
|
|
81
|
+
isSameDay(a, b) {
|
|
82
|
+
if (!a || !b)
|
|
83
|
+
return false;
|
|
84
|
+
if (!this.isValid(a) || !this.isValid(b))
|
|
85
|
+
return false;
|
|
86
|
+
return (a.getFullYear() === b.getFullYear() &&
|
|
87
|
+
a.getMonth() === b.getMonth() &&
|
|
88
|
+
a.getDate() === b.getDate());
|
|
89
|
+
}
|
|
90
|
+
isBefore(a, b) {
|
|
91
|
+
if (!a || !b)
|
|
92
|
+
return false;
|
|
93
|
+
if (!this.isValid(a) || !this.isValid(b))
|
|
94
|
+
return false;
|
|
95
|
+
return a.getTime() < b.getTime();
|
|
96
|
+
}
|
|
97
|
+
isAfter(a, b) {
|
|
98
|
+
if (!a || !b)
|
|
99
|
+
return false;
|
|
100
|
+
if (!this.isValid(a) || !this.isValid(b))
|
|
101
|
+
return false;
|
|
102
|
+
return a.getTime() > b.getTime();
|
|
103
|
+
}
|
|
104
|
+
isBetween(date, start, end) {
|
|
105
|
+
if (!date || !start || !end)
|
|
106
|
+
return false;
|
|
107
|
+
if (!this.isValid(date) || !this.isValid(start) || !this.isValid(end))
|
|
108
|
+
return false;
|
|
109
|
+
const dateTime = date.getTime();
|
|
110
|
+
const startTime = start.getTime();
|
|
111
|
+
const endTime = end.getTime();
|
|
112
|
+
return dateTime >= startTime && dateTime <= endTime;
|
|
113
|
+
}
|
|
114
|
+
clone(date) {
|
|
115
|
+
return new Date(date.getTime());
|
|
116
|
+
}
|
|
117
|
+
isValid(date) {
|
|
118
|
+
return date instanceof Date && !isNaN(date.getTime());
|
|
119
|
+
}
|
|
120
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NativeDateAdapter, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
121
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NativeDateAdapter });
|
|
122
|
+
}
|
|
123
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NativeDateAdapter, decorators: [{
|
|
124
|
+
type: Injectable
|
|
125
|
+
}] });
|
|
126
|
+
|
|
7
127
|
class DualDatepickerComponent {
|
|
8
128
|
elementRef;
|
|
9
129
|
placeholder = 'Select date range';
|
|
@@ -28,12 +148,14 @@ class DualDatepickerComponent {
|
|
|
28
148
|
locale = {};
|
|
29
149
|
dateRangeChange = new EventEmitter();
|
|
30
150
|
dateRangeSelected = new EventEmitter();
|
|
151
|
+
// Date adapter injection
|
|
152
|
+
dateAdapter = inject(DATE_ADAPTER);
|
|
31
153
|
// Signals for reactive state
|
|
32
154
|
mostrarDatePicker = signal(false);
|
|
33
155
|
rangoFechas = signal('');
|
|
34
156
|
fechaSeleccionandoInicio = signal(true);
|
|
35
|
-
mesActual = signal(
|
|
36
|
-
mesAnterior = signal(
|
|
157
|
+
mesActual = signal(this.dateAdapter.today());
|
|
158
|
+
mesAnterior = signal(this.dateAdapter.today());
|
|
37
159
|
diasMesActual = signal([]);
|
|
38
160
|
diasMesAnterior = signal([]);
|
|
39
161
|
isDisabled = signal(false);
|
|
@@ -84,17 +206,19 @@ class DualDatepickerComponent {
|
|
|
84
206
|
}
|
|
85
207
|
}
|
|
86
208
|
formatearFecha(fecha) {
|
|
87
|
-
const year =
|
|
88
|
-
const month = String(
|
|
89
|
-
const day = String(
|
|
209
|
+
const year = this.dateAdapter.getYear(fecha);
|
|
210
|
+
const month = String(this.dateAdapter.getMonth(fecha) + 1).padStart(2, '0');
|
|
211
|
+
const day = String(this.dateAdapter.getDate(fecha)).padStart(2, '0');
|
|
90
212
|
return `${year}-${month}-${day}`;
|
|
91
213
|
}
|
|
92
214
|
formatearFechaDisplay(fechaStr) {
|
|
93
215
|
if (!fechaStr)
|
|
94
216
|
return '';
|
|
95
|
-
const fecha =
|
|
217
|
+
const fecha = this.dateAdapter.parse(fechaStr);
|
|
218
|
+
if (!fecha)
|
|
219
|
+
return '';
|
|
96
220
|
const monthNames = this.locale.monthNamesShort || this.defaultMonthNamesShort;
|
|
97
|
-
return `${
|
|
221
|
+
return `${this.dateAdapter.getDate(fecha)} ${monthNames[this.dateAdapter.getMonth(fecha)]}`;
|
|
98
222
|
}
|
|
99
223
|
actualizarRangoFechasTexto() {
|
|
100
224
|
if (this.fechaInicio && this.fechaFin) {
|
|
@@ -111,7 +235,10 @@ class DualDatepickerComponent {
|
|
|
111
235
|
if (this.mostrarDatePicker()) {
|
|
112
236
|
this.fechaSeleccionandoInicio.set(true);
|
|
113
237
|
const mesActualValue = this.mesActual();
|
|
114
|
-
this.
|
|
238
|
+
const año = this.dateAdapter.getYear(mesActualValue);
|
|
239
|
+
const mes = this.dateAdapter.getMonth(mesActualValue);
|
|
240
|
+
const mesAnteriorDate = this.dateAdapter.createDate(año, mes - 1, 1);
|
|
241
|
+
this.mesAnterior.set(mesAnteriorDate);
|
|
115
242
|
this.generarCalendarios();
|
|
116
243
|
}
|
|
117
244
|
this.onTouched();
|
|
@@ -125,18 +252,18 @@ class DualDatepickerComponent {
|
|
|
125
252
|
this.diasMesActual.set(this.generarCalendarioMes(this.mesActual()));
|
|
126
253
|
}
|
|
127
254
|
generarCalendarioMes(fecha) {
|
|
128
|
-
const año =
|
|
129
|
-
const mes =
|
|
130
|
-
const primerDia =
|
|
131
|
-
const ultimoDia =
|
|
132
|
-
const diasEnMes =
|
|
133
|
-
const primerDiaSemana =
|
|
255
|
+
const año = this.dateAdapter.getYear(fecha);
|
|
256
|
+
const mes = this.dateAdapter.getMonth(fecha);
|
|
257
|
+
const primerDia = this.dateAdapter.createDate(año, mes, 1);
|
|
258
|
+
const ultimoDia = this.dateAdapter.createDate(año, mes + 1, 0);
|
|
259
|
+
const diasEnMes = this.dateAdapter.getDate(ultimoDia);
|
|
260
|
+
const primerDiaSemana = this.dateAdapter.getDay(primerDia);
|
|
134
261
|
const diasMes = [];
|
|
135
262
|
for (let i = 0; i < primerDiaSemana; i++) {
|
|
136
263
|
diasMes.push({ dia: null, esMesActual: false });
|
|
137
264
|
}
|
|
138
265
|
for (let dia = 1; dia <= diasEnMes; dia++) {
|
|
139
|
-
const fechaDia =
|
|
266
|
+
const fechaDia = this.dateAdapter.createDate(año, mes, dia);
|
|
140
267
|
const fechaStr = this.formatearFecha(fechaDia);
|
|
141
268
|
diasMes.push({
|
|
142
269
|
dia: dia,
|
|
@@ -184,24 +311,45 @@ class DualDatepickerComponent {
|
|
|
184
311
|
}
|
|
185
312
|
cambiarMes(direccion) {
|
|
186
313
|
const mesActualValue = this.mesActual();
|
|
187
|
-
this.
|
|
188
|
-
const
|
|
189
|
-
this.
|
|
314
|
+
const año = this.dateAdapter.getYear(mesActualValue);
|
|
315
|
+
const mes = this.dateAdapter.getMonth(mesActualValue);
|
|
316
|
+
const nuevoMesActual = this.dateAdapter.createDate(año, mes + direccion, 1);
|
|
317
|
+
this.mesActual.set(nuevoMesActual);
|
|
318
|
+
const añoNuevo = this.dateAdapter.getYear(nuevoMesActual);
|
|
319
|
+
const mesNuevo = this.dateAdapter.getMonth(nuevoMesActual);
|
|
320
|
+
const mesAnteriorNuevo = this.dateAdapter.createDate(añoNuevo, mesNuevo - 1, 1);
|
|
321
|
+
this.mesAnterior.set(mesAnteriorNuevo);
|
|
190
322
|
this.generarCalendarios();
|
|
191
323
|
}
|
|
192
324
|
getNombreMes(fecha) {
|
|
193
325
|
const monthNames = this.locale.monthNames || this.defaultMonthNames;
|
|
194
|
-
return `${monthNames[
|
|
326
|
+
return `${monthNames[this.dateAdapter.getMonth(fecha)]} ${this.dateAdapter.getYear(fecha)}`;
|
|
195
327
|
}
|
|
196
328
|
getDayNames() {
|
|
197
329
|
return this.locale.dayNamesShort || this.defaultDayNamesShort;
|
|
198
330
|
}
|
|
199
331
|
seleccionarRangoPredefinido(preset) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
332
|
+
let start;
|
|
333
|
+
let end;
|
|
334
|
+
// New flexible pattern with getValue()
|
|
335
|
+
if (preset.getValue) {
|
|
336
|
+
const range = preset.getValue();
|
|
337
|
+
start = range.start;
|
|
338
|
+
end = range.end;
|
|
339
|
+
}
|
|
340
|
+
// Backward compatibility with daysAgo pattern
|
|
341
|
+
else if (preset.daysAgo !== undefined) {
|
|
342
|
+
const hoy = this.dateAdapter.today();
|
|
343
|
+
const fechaInicio = this.dateAdapter.addDays(hoy, -preset.daysAgo);
|
|
344
|
+
start = this.formatearFecha(fechaInicio);
|
|
345
|
+
end = this.formatearFecha(hoy);
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
console.error('PresetConfig must have either getValue() or daysAgo');
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
this.fechaInicio = start;
|
|
352
|
+
this.fechaFin = end;
|
|
205
353
|
this.actualizarRangoFechasTexto();
|
|
206
354
|
this.generarCalendarios();
|
|
207
355
|
if (this.closeOnPresetSelection) {
|
|
@@ -270,6 +418,10 @@ class DualDatepickerComponent {
|
|
|
270
418
|
provide: NG_VALUE_ACCESSOR,
|
|
271
419
|
useExisting: forwardRef(() => DualDatepickerComponent),
|
|
272
420
|
multi: true
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
provide: DATE_ADAPTER,
|
|
424
|
+
useClass: NativeDateAdapter
|
|
273
425
|
}
|
|
274
426
|
], usesOnChanges: true, ngImport: i0, template: "<div class=\"datepicker-wrapper\" \n [style.--input-border-hover]=\"inputBorderColorHover\"\n [style.--input-border-focus]=\"inputBorderColorFocus\">\n <input \n type=\"text\" \n class=\"datepicker-input\" \n [value]=\"rangoFechas()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (mostrarDatePicker()) {\n <div class=\"date-picker-dropdown\">\n @if (showPresets) {\n <div class=\"date-picker-presets\">\n @for (preset of presets; track preset.label) {\n <button type=\"button\" (click)=\"seleccionarRangoPredefinido(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"cerrarDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n @if (!showPresets) {\n <div class=\"date-picker-header-only-close\">\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"cerrarDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n <!-- Calendars -->\n <div class=\"date-picker-calendars\">\n <!-- Previous month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" (click)=\"cambiarMes(-1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ nombreMesAnterior() }}</span>\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of diasSemana(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (diaObj of diasMesAnterior(); track diaObj.fecha || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!diaObj.esMesActual\"\n [class.selected]=\"diaObj.esInicio || diaObj.esFin\"\n [class.in-range]=\"diaObj.enRango && !diaObj.esInicio && !diaObj.esFin\"\n (click)=\"seleccionarDia(diaObj)\"\n [disabled]=\"!diaObj.esMesActual\">\n {{ diaObj.dia }}\n </button>\n }\n </div>\n </div>\n\n <!-- Current month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ nombreMesActual() }}</span>\n <button type=\"button\" (click)=\"cambiarMes(1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of diasSemana(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (diaObj of diasMesActual(); track diaObj.fecha || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!diaObj.esMesActual\"\n [class.selected]=\"diaObj.esInicio || diaObj.esFin\"\n [class.in-range]=\"diaObj.enRango && !diaObj.esInicio && !diaObj.esFin\"\n (click)=\"seleccionarDia(diaObj)\"\n [disabled]=\"!diaObj.esMesActual\">\n {{ diaObj.dia }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Footer with clear button -->\n @if (showClearButton) {\n <div class=\"date-picker-footer\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"limpiar()\" title=\"Clear selection\">\n Clear\n </button>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media (max-width: 768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media (max-width: 768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media (max-width: 768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
275
427
|
}
|
|
@@ -280,6 +432,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
280
432
|
provide: NG_VALUE_ACCESSOR,
|
|
281
433
|
useExisting: forwardRef(() => DualDatepickerComponent),
|
|
282
434
|
multi: true
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
provide: DATE_ADAPTER,
|
|
438
|
+
useClass: NativeDateAdapter
|
|
283
439
|
}
|
|
284
440
|
], template: "<div class=\"datepicker-wrapper\" \n [style.--input-border-hover]=\"inputBorderColorHover\"\n [style.--input-border-focus]=\"inputBorderColorFocus\">\n <input \n type=\"text\" \n class=\"datepicker-input\" \n [value]=\"rangoFechas()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (mostrarDatePicker()) {\n <div class=\"date-picker-dropdown\">\n @if (showPresets) {\n <div class=\"date-picker-presets\">\n @for (preset of presets; track preset.label) {\n <button type=\"button\" (click)=\"seleccionarRangoPredefinido(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"cerrarDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n @if (!showPresets) {\n <div class=\"date-picker-header-only-close\">\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"cerrarDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n <!-- Calendars -->\n <div class=\"date-picker-calendars\">\n <!-- Previous month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" (click)=\"cambiarMes(-1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ nombreMesAnterior() }}</span>\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of diasSemana(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (diaObj of diasMesAnterior(); track diaObj.fecha || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!diaObj.esMesActual\"\n [class.selected]=\"diaObj.esInicio || diaObj.esFin\"\n [class.in-range]=\"diaObj.enRango && !diaObj.esInicio && !diaObj.esFin\"\n (click)=\"seleccionarDia(diaObj)\"\n [disabled]=\"!diaObj.esMesActual\">\n {{ diaObj.dia }}\n </button>\n }\n </div>\n </div>\n\n <!-- Current month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ nombreMesActual() }}</span>\n <button type=\"button\" (click)=\"cambiarMes(1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of diasSemana(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (diaObj of diasMesActual(); track diaObj.fecha || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!diaObj.esMesActual\"\n [class.selected]=\"diaObj.esInicio || diaObj.esFin\"\n [class.in-range]=\"diaObj.enRango && !diaObj.esInicio && !diaObj.esFin\"\n (click)=\"seleccionarDia(diaObj)\"\n [disabled]=\"!diaObj.esMesActual\">\n {{ diaObj.dia }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Footer with clear button -->\n @if (showClearButton) {\n <div class=\"date-picker-footer\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"limpiar()\" title=\"Clear selection\">\n Clear\n </button>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media (max-width: 768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media (max-width: 768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media (max-width: 768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}\n"] }]
|
|
285
441
|
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { placeholder: [{
|
|
@@ -323,6 +479,282 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
323
479
|
args: ['document:click', ['$event']]
|
|
324
480
|
}] } });
|
|
325
481
|
|
|
482
|
+
/**
|
|
483
|
+
* Utility functions for creating common date range presets
|
|
484
|
+
* Perfect for dashboards, reporting, POS, BI apps, and ERP systems
|
|
485
|
+
*/
|
|
486
|
+
/**
|
|
487
|
+
* Format a date as YYYY-MM-DD string
|
|
488
|
+
*/
|
|
489
|
+
function formatDate(date) {
|
|
490
|
+
const year = date.getFullYear();
|
|
491
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
492
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
493
|
+
return `${year}-${month}-${day}`;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Get the start of today
|
|
497
|
+
*/
|
|
498
|
+
function getToday() {
|
|
499
|
+
const today = new Date();
|
|
500
|
+
return {
|
|
501
|
+
start: formatDate(today),
|
|
502
|
+
end: formatDate(today)
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Get yesterday's date range
|
|
507
|
+
*/
|
|
508
|
+
function getYesterday() {
|
|
509
|
+
const yesterday = new Date();
|
|
510
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
511
|
+
return {
|
|
512
|
+
start: formatDate(yesterday),
|
|
513
|
+
end: formatDate(yesterday)
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Get last N days (including today)
|
|
518
|
+
*/
|
|
519
|
+
function getLastNDays(days) {
|
|
520
|
+
const end = new Date();
|
|
521
|
+
const start = new Date();
|
|
522
|
+
start.setDate(start.getDate() - days + 1);
|
|
523
|
+
return {
|
|
524
|
+
start: formatDate(start),
|
|
525
|
+
end: formatDate(end)
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Get this week (Monday to Sunday)
|
|
530
|
+
*/
|
|
531
|
+
function getThisWeek() {
|
|
532
|
+
const today = new Date();
|
|
533
|
+
const dayOfWeek = today.getDay();
|
|
534
|
+
const start = new Date(today);
|
|
535
|
+
// Adjust to Monday (1) as first day of week
|
|
536
|
+
const daysToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
|
|
537
|
+
start.setDate(start.getDate() - daysToMonday);
|
|
538
|
+
const end = new Date(start);
|
|
539
|
+
end.setDate(end.getDate() + 6);
|
|
540
|
+
return {
|
|
541
|
+
start: formatDate(start),
|
|
542
|
+
end: formatDate(end)
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Get last week (Monday to Sunday)
|
|
547
|
+
*/
|
|
548
|
+
function getLastWeek() {
|
|
549
|
+
const today = new Date();
|
|
550
|
+
const dayOfWeek = today.getDay();
|
|
551
|
+
const daysToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
|
|
552
|
+
const lastMonday = new Date(today);
|
|
553
|
+
lastMonday.setDate(lastMonday.getDate() - daysToMonday - 7);
|
|
554
|
+
const lastSunday = new Date(lastMonday);
|
|
555
|
+
lastSunday.setDate(lastSunday.getDate() + 6);
|
|
556
|
+
return {
|
|
557
|
+
start: formatDate(lastMonday),
|
|
558
|
+
end: formatDate(lastSunday)
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Get this month (1st to last day)
|
|
563
|
+
*/
|
|
564
|
+
function getThisMonth() {
|
|
565
|
+
const today = new Date();
|
|
566
|
+
const start = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
567
|
+
const end = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
|
568
|
+
return {
|
|
569
|
+
start: formatDate(start),
|
|
570
|
+
end: formatDate(end)
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Get last month (1st to last day)
|
|
575
|
+
*/
|
|
576
|
+
function getLastMonth() {
|
|
577
|
+
const today = new Date();
|
|
578
|
+
const start = new Date(today.getFullYear(), today.getMonth() - 1, 1);
|
|
579
|
+
const end = new Date(today.getFullYear(), today.getMonth(), 0);
|
|
580
|
+
return {
|
|
581
|
+
start: formatDate(start),
|
|
582
|
+
end: formatDate(end)
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Get month to date (1st of current month to today)
|
|
587
|
+
*/
|
|
588
|
+
function getMonthToDate() {
|
|
589
|
+
const today = new Date();
|
|
590
|
+
const start = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
591
|
+
return {
|
|
592
|
+
start: formatDate(start),
|
|
593
|
+
end: formatDate(today)
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Get this quarter (Q1, Q2, Q3, or Q4)
|
|
598
|
+
*/
|
|
599
|
+
function getThisQuarter() {
|
|
600
|
+
const today = new Date();
|
|
601
|
+
const currentMonth = today.getMonth();
|
|
602
|
+
const quarterStartMonth = Math.floor(currentMonth / 3) * 3;
|
|
603
|
+
const start = new Date(today.getFullYear(), quarterStartMonth, 1);
|
|
604
|
+
const end = new Date(today.getFullYear(), quarterStartMonth + 3, 0);
|
|
605
|
+
return {
|
|
606
|
+
start: formatDate(start),
|
|
607
|
+
end: formatDate(end)
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Get last quarter
|
|
612
|
+
*/
|
|
613
|
+
function getLastQuarter() {
|
|
614
|
+
const today = new Date();
|
|
615
|
+
const currentMonth = today.getMonth();
|
|
616
|
+
const lastQuarterStartMonth = Math.floor(currentMonth / 3) * 3 - 3;
|
|
617
|
+
const start = new Date(today.getFullYear(), lastQuarterStartMonth, 1);
|
|
618
|
+
const end = new Date(today.getFullYear(), lastQuarterStartMonth + 3, 0);
|
|
619
|
+
return {
|
|
620
|
+
start: formatDate(start),
|
|
621
|
+
end: formatDate(end)
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Get quarter to date (start of current quarter to today)
|
|
626
|
+
*/
|
|
627
|
+
function getQuarterToDate() {
|
|
628
|
+
const today = new Date();
|
|
629
|
+
const currentMonth = today.getMonth();
|
|
630
|
+
const quarterStartMonth = Math.floor(currentMonth / 3) * 3;
|
|
631
|
+
const start = new Date(today.getFullYear(), quarterStartMonth, 1);
|
|
632
|
+
return {
|
|
633
|
+
start: formatDate(start),
|
|
634
|
+
end: formatDate(today)
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Get this year (January 1 to December 31)
|
|
639
|
+
*/
|
|
640
|
+
function getThisYear() {
|
|
641
|
+
const today = new Date();
|
|
642
|
+
const start = new Date(today.getFullYear(), 0, 1);
|
|
643
|
+
const end = new Date(today.getFullYear(), 11, 31);
|
|
644
|
+
return {
|
|
645
|
+
start: formatDate(start),
|
|
646
|
+
end: formatDate(end)
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Get last year
|
|
651
|
+
*/
|
|
652
|
+
function getLastYear() {
|
|
653
|
+
const today = new Date();
|
|
654
|
+
const start = new Date(today.getFullYear() - 1, 0, 1);
|
|
655
|
+
const end = new Date(today.getFullYear() - 1, 11, 31);
|
|
656
|
+
return {
|
|
657
|
+
start: formatDate(start),
|
|
658
|
+
end: formatDate(end)
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Get year to date (January 1 to today)
|
|
663
|
+
*/
|
|
664
|
+
function getYearToDate() {
|
|
665
|
+
const today = new Date();
|
|
666
|
+
const start = new Date(today.getFullYear(), 0, 1);
|
|
667
|
+
return {
|
|
668
|
+
start: formatDate(start),
|
|
669
|
+
end: formatDate(today)
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Get last N months (including current partial month)
|
|
674
|
+
*/
|
|
675
|
+
function getLastNMonths(months) {
|
|
676
|
+
const today = new Date();
|
|
677
|
+
const start = new Date(today);
|
|
678
|
+
start.setMonth(start.getMonth() - months);
|
|
679
|
+
return {
|
|
680
|
+
start: formatDate(start),
|
|
681
|
+
end: formatDate(today)
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Get last N years
|
|
686
|
+
*/
|
|
687
|
+
function getLastNYears(years) {
|
|
688
|
+
const today = new Date();
|
|
689
|
+
const start = new Date(today);
|
|
690
|
+
start.setFullYear(start.getFullYear() - years);
|
|
691
|
+
return {
|
|
692
|
+
start: formatDate(start),
|
|
693
|
+
end: formatDate(today)
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Pre-built preset configurations for common use cases
|
|
698
|
+
* Import and use these directly in your component
|
|
699
|
+
*/
|
|
700
|
+
const CommonPresets = {
|
|
701
|
+
/**
|
|
702
|
+
* Dashboard presets - Perfect for analytics dashboards
|
|
703
|
+
*/
|
|
704
|
+
dashboard: [
|
|
705
|
+
{ label: 'Today', getValue: getToday },
|
|
706
|
+
{ label: 'Yesterday', getValue: getYesterday },
|
|
707
|
+
{ label: 'Last 7 days', getValue: () => getLastNDays(7) },
|
|
708
|
+
{ label: 'Last 30 days', getValue: () => getLastNDays(30) },
|
|
709
|
+
{ label: 'This month', getValue: getThisMonth },
|
|
710
|
+
{ label: 'Last month', getValue: getLastMonth }
|
|
711
|
+
],
|
|
712
|
+
/**
|
|
713
|
+
* Reporting presets - Perfect for business reporting
|
|
714
|
+
*/
|
|
715
|
+
reporting: [
|
|
716
|
+
{ label: 'Today', getValue: getToday },
|
|
717
|
+
{ label: 'This week', getValue: getThisWeek },
|
|
718
|
+
{ label: 'Last week', getValue: getLastWeek },
|
|
719
|
+
{ label: 'This month', getValue: getThisMonth },
|
|
720
|
+
{ label: 'Last month', getValue: getLastMonth },
|
|
721
|
+
{ label: 'This quarter', getValue: getThisQuarter },
|
|
722
|
+
{ label: 'Last quarter', getValue: getLastQuarter }
|
|
723
|
+
],
|
|
724
|
+
/**
|
|
725
|
+
* Financial presets - Perfect for ERP and accounting systems
|
|
726
|
+
*/
|
|
727
|
+
financial: [
|
|
728
|
+
{ label: 'Month to date', getValue: getMonthToDate },
|
|
729
|
+
{ label: 'Quarter to date', getValue: getQuarterToDate },
|
|
730
|
+
{ label: 'Year to date', getValue: getYearToDate },
|
|
731
|
+
{ label: 'Last month', getValue: getLastMonth },
|
|
732
|
+
{ label: 'Last quarter', getValue: getLastQuarter },
|
|
733
|
+
{ label: 'Last year', getValue: getLastYear }
|
|
734
|
+
],
|
|
735
|
+
/**
|
|
736
|
+
* Analytics presets - Perfect for BI and data analysis
|
|
737
|
+
*/
|
|
738
|
+
analytics: [
|
|
739
|
+
{ label: 'Last 7 days', getValue: () => getLastNDays(7) },
|
|
740
|
+
{ label: 'Last 14 days', getValue: () => getLastNDays(14) },
|
|
741
|
+
{ label: 'Last 30 days', getValue: () => getLastNDays(30) },
|
|
742
|
+
{ label: 'Last 60 days', getValue: () => getLastNDays(60) },
|
|
743
|
+
{ label: 'Last 90 days', getValue: () => getLastNDays(90) },
|
|
744
|
+
{ label: 'Last 180 days', getValue: () => getLastNDays(180) },
|
|
745
|
+
{ label: 'Last 365 days', getValue: () => getLastNDays(365) }
|
|
746
|
+
],
|
|
747
|
+
/**
|
|
748
|
+
* Simple presets - Basic common ranges
|
|
749
|
+
*/
|
|
750
|
+
simple: [
|
|
751
|
+
{ label: 'Today', getValue: getToday },
|
|
752
|
+
{ label: 'Last 7 days', getValue: () => getLastNDays(7) },
|
|
753
|
+
{ label: 'Last 30 days', getValue: () => getLastNDays(30) },
|
|
754
|
+
{ label: 'This year', getValue: getThisYear }
|
|
755
|
+
]
|
|
756
|
+
};
|
|
757
|
+
|
|
326
758
|
/**
|
|
327
759
|
* Public API Surface of @oneluiz/dual-datepicker
|
|
328
760
|
*/
|
|
@@ -331,5 +763,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
331
763
|
* Generated bundle index. Do not edit.
|
|
332
764
|
*/
|
|
333
765
|
|
|
334
|
-
export { DualDatepickerComponent };
|
|
766
|
+
export { CommonPresets, DATE_ADAPTER, DateAdapter, DualDatepickerComponent, NativeDateAdapter, getLastMonth, getLastNDays, getLastNMonths, getLastNYears, getLastQuarter, getLastWeek, getLastYear, getMonthToDate, getQuarterToDate, getThisMonth, getThisQuarter, getThisWeek, getThisYear, getToday, getYearToDate, getYesterday };
|
|
335
767
|
//# sourceMappingURL=oneluiz-dual-datepicker.mjs.map
|