@oneluiz/dual-datepicker 2.7.0 → 3.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/README.md CHANGED
@@ -10,6 +10,16 @@ A lightweight, zero-dependency date range picker for Angular 17+. Built with sta
10
10
  npm install @oneluiz/dual-datepicker
11
11
  ```
12
12
 
13
+ > ## ⚠️ **BREAKING CHANGES in v3.0.0**
14
+ >
15
+ > - **All DateRange properties renamed to English**: `fechaInicio` → `startDate`, `fechaFin` → `endDate`, `rangoTexto` → `rangeText`
16
+ > - **Deprecated `daysAgo` removed**: Use `getValue: () => PresetRange` pattern or `CommonPresets` instead
17
+ > - **All component methods renamed to English**: `limpiar()` → `clear()`, etc.
18
+ >
19
+ > **📖 See [MIGRATION_V3.md](MIGRATION_V3.md) for complete migration guide**
20
+ >
21
+ > To stay on v2.x: `npm install @oneluiz/dual-datepicker@2.7.0`
22
+
13
23
  ## 🎯 [Live Demo](https://oneluiz.github.io/ng-dual-datepicker/)
14
24
 
15
25
  **[Check out the interactive examples →](https://oneluiz.github.io/ng-dual-datepicker/)**
@@ -108,8 +118,8 @@ import { DualDatepickerComponent, DateRange } from '@oneluiz/dual-datepicker';
108
118
  })
109
119
  export class AppComponent {
110
120
  onRangeChange(range: DateRange) {
111
- console.log('Start:', range.fechaInicio);
112
- console.log('End:', range.fechaFin);
121
+ console.log('Start:', range.startDate);
122
+ console.log('End:', range.endDate);
113
123
  }
114
124
  }
115
125
  ```
@@ -154,8 +164,6 @@ dateRange = signal<DateRange | null>(null);
154
164
  ```
155
165
 
156
166
  ## 📚 Advanced Usage
157
- }
158
- ```
159
167
 
160
168
  ### 4. Use with Angular Signals ⚡ New!
161
169
 
@@ -171,8 +179,8 @@ import { DualDatepickerComponent, DateRange } from '@oneluiz/dual-datepicker';
171
179
  imports: [DualDatepickerComponent],
172
180
  template: `
173
181
  <ngx-dual-datepicker
174
- [fechaInicio]="fechaInicio()"
175
- [fechaFin]="fechaFin()"
182
+ [startDate]="startDate()"
183
+ [endDate]="endDate()"
176
184
  (dateRangeChange)="onDateChange($event)">
177
185
  </ngx-dual-datepicker>
178
186
 
@@ -185,30 +193,30 @@ import { DualDatepickerComponent, DateRange } from '@oneluiz/dual-datepicker';
185
193
  `
186
194
  })
187
195
  export class SignalsExampleComponent {
188
- fechaInicio = signal('');
189
- fechaFin = signal('');
196
+ startDate = signal('');
197
+ endDate = signal('');
190
198
 
191
199
  // Computed values
192
200
  isRangeSelected = computed(() =>
193
- this.fechaInicio() !== '' && this.fechaFin() !== ''
201
+ this.startDate() !== '' && this.endDate() !== ''
194
202
  );
195
203
 
196
204
  rangeText = computed(() =>
197
205
  this.isRangeSelected()
198
- ? `${this.fechaInicio()} to ${this.fechaFin()}`
206
+ ? `${this.startDate()} to ${this.endDate()}`
199
207
  : 'No range selected'
200
208
  );
201
209
 
202
210
  daysDifference = computed(() => {
203
211
  if (!this.isRangeSelected()) return 0;
204
- const start = new Date(this.fechaInicio());
205
- const end = new Date(this.fechaFin());
212
+ const start = new Date(this.startDate());
213
+ const end = new Date(this.endDate());
206
214
  return Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
207
215
  });
208
216
 
209
217
  onDateChange(range: DateRange) {
210
- this.fechaInicio.set(range.fechaInicio);
211
- this.fechaFin.set(range.fechaFin);
218
+ this.startDate.set(range.startDate);
219
+ this.endDate.set(range.endDate);
212
220
  }
213
221
  }
214
222
  ```
@@ -237,9 +245,9 @@ import { DualDatepickerComponent, MultiDateRange } from '@oneluiz/dual-datepicke
237
245
  <h3>Selected Ranges ({{ selectedRanges.ranges.length }})</h3>
238
246
  @for (range of selectedRanges.ranges; track $index) {
239
247
  <div class="range-item">
240
- <strong>Range {{ $index + 1 }}:</strong> {{ range.rangoTexto }}
241
- <br>
242
- <span>{{ range.fechaInicio }} → {{ range.fechaFin }}</span>
248
+ <strong>Range {{ $index + 1 }}:</strong> {{ range.rangeText }}
249
+ <br />
250
+ <span>{{ range.startDate }} → {{ range.endDate }}</span>
243
251
  </div>
244
252
  }
245
253
  </div>
@@ -254,9 +262,9 @@ export class MultiRangeExample {
254
262
  console.log('Selected ranges:', ranges.ranges);
255
263
  // Output example:
256
264
  // [
257
- // { fechaInicio: '2026-01-01', fechaFin: '2026-01-05', rangoTexto: 'Jan 1 – Jan 5' },
258
- // { fechaInicio: '2026-01-10', fechaFin: '2026-01-15', rangoTexto: 'Jan 10 – Jan 15' },
259
- // { fechaInicio: '2026-02-01', fechaFin: '2026-02-07', rangoTexto: 'Feb 1 – Feb 7' }
265
+ // { startDate: '2026-01-01', endDate: '2026-01-05', rangeText: 'Jan 1 – Jan 5' },
266
+ // { startDate: '2026-01-10', endDate: '2026-01-15', rangeText: 'Jan 10 – Jan 15' },
267
+ // { startDate: '2026-02-01', endDate: '2026-02-07', rangeText: 'Feb 1 – Feb 7' }
260
268
  // ]
261
269
  }
262
270
  }
@@ -721,22 +729,22 @@ export class MyComponent {
721
729
  @ViewChild('datepicker') datepicker!: DualDatepickerComponent;
722
730
 
723
731
  clearSelection() {
724
- this.datepicker.limpiar(); // Clears the date selection
732
+ this.datepicker.clear(); // v3.0.0: method renamed from limpiar() to clear()
725
733
  }
726
734
  }
727
735
  ```
728
736
 
729
737
  | Method | Description |
730
- |--------|-------------|
731
- | `limpiar()` | Clears the current date selection and resets the component |
738
+ |--------|----------|
739
+ | `clear()` | Clears the current date selection and resets the component (v3.0.0: renamed from `limpiar()`) |
732
740
 
733
741
  ### Types
734
742
 
735
743
  ```typescript
736
744
  interface DateRange {
737
- fechaInicio: string; // ISO date format: 'YYYY-MM-DD'
738
- fechaFin: string; // ISO date format: 'YYYY-MM-DD'
739
- rangoTexto: string; // Display text: 'DD Mon - DD Mon'
745
+ startDate: string; // v3.0.0: renamed from 'fechaInicio' - ISO format: 'YYYY-MM-DD'
746
+ endDate: string; // v3.0.0: renamed from 'fechaFin' - ISO format: 'YYYY-MM-DD'
747
+ rangeText: string; // v3.0.0: renamed from 'rangoTexto' - Display text: 'DD Mon - DD Mon'
740
748
  }
741
749
 
742
750
  interface PresetRange {
@@ -746,10 +754,7 @@ interface PresetRange {
746
754
 
747
755
  interface PresetConfig {
748
756
  label: string;
749
- /** @deprecated Use getValue() instead for more flexibility */
750
- daysAgo?: number;
751
- /** NEW v2.6.0 - Function that returns date range with custom logic */
752
- getValue?: () => PresetRange;
757
+ getValue: () => PresetRange; // v3.0.0: NOW REQUIRED (daysAgo removed)
753
758
  }
754
759
 
755
760
  interface LocaleConfig {
@@ -761,48 +766,37 @@ interface LocaleConfig {
761
766
  }
762
767
  ```
763
768
 
764
- ### Default Presets
769
+ ### CommonPresets
770
+
771
+ v3.0.0: No default presets shipped with component. Use `CommonPresets` utility or create custom:
765
772
 
766
773
  ```typescript
767
- [
768
- { label: 'Last month', daysAgo: 30 },
769
- { label: 'Last 6 months', daysAgo: 180 },
770
- { label: 'Last yea
771
- [fechaInicio]="startDate"
772
- [fechaFin]="endDate"
773
- (dateRangeSelected)="onDateRangeSelected($event)">
774
- </ngx-dual-datepicker>
775
- ```
774
+ import { CommonPresets, getLastNDays } from '@oneluiz/dual-datepicker';
776
775
 
777
- ###fechaInicio]="startDate"
778
- [fechaFin]="endDate"
779
- [closeOnSelection]="true"
780
- [closeOnPresetSelection]="true"
781
- (dateRangeSelected)="onDateRangeSelected($event)
782
- spanishLocale: LocaleConfig = {
783
- monthNames: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
784
- 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
785
- monthNamesShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun',
786
- 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
787
- dayNames: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
788
- dayNamesShort: ['D', 'L', 'M', 'X', 'J', 'V', 'S']
789
- };
776
+ // Use pre-built collections
777
+ presets = CommonPresets.dashboard; // Last 7, 15, 30, 60, 90 days + last 6 months
778
+
779
+ // Or create custom presets
780
+ presets: PresetConfig[] = [
781
+ { label: 'Last 15 days', getValue: () => getLastNDays(15) },
782
+ { label: 'Last 3 months', getValue: () => getLastNDays(90) },
783
+ { label: 'Last 6 months', getValue: () => getLastNDays(180) },
784
+ { label: 'Last year', getValue: () => getLastNDays(365) }
785
+ ];
790
786
  ```
791
787
 
792
- ```html
793
- <ngx-dual-datepicker
794
- [fechaInicio]="startDate"
795
- [fechaFin]="endDate"
796
- [fechaInicio]="startDate"
797
- [fechaFin]="endDate"
798
- placeholder="Pick your dates"
799
- inputBackgroundColor="#fef3c7"
800
- inputTextColor="#92400e"
801
- inputBorderColor="#fbbf24"
802
- inputBorderColorHover="#f59e0b"
803
- inputBorderColorFocus="#d97706"
804
- inputPadding="8px 12px"
805
- (dateRangeSelected)="onDateRangeSelected($event)
788
+ Available `CommonPresets` collections:
789
+ - `CommonPresets.simple` - Last 7, 30, 60, 90 days
790
+ - `CommonPresets.dashboard` - Last 7, 15, 30, 60, 90 days + last 6 months
791
+ - `CommonPresets.analytics` - Last 30, 60, 90, 180, 365 days + YTD
792
+
793
+ Helper functions:
794
+ - `getLastNDays(n)` - Returns range for last N days
795
+ - `getThisMonth()` - Returns range for current month
796
+ - `getLastMonth()` - Returns range for previous month
797
+ - `getYearToDate()` - Returns range from Jan 1 to today
798
+
799
+ ## Usage Examples
806
800
 
807
801
  ### Minimal Usage
808
802
 
@@ -810,15 +804,31 @@ spanishLocale: LocaleConfig = {
810
804
  <ngx-dual-datepicker [(ngModel)]="dateRange"></ngx-dual-datepicker>
811
805
  ```
812
806
 
813
- ### With Auto-close
814
- fechaInicio]="startDate"
815
- [fechaFin]="endDate"
807
+ ### With Initial Dates
808
+
809
+ ```html
810
+ <ngx-dual-datepicker
811
+ [startDate]="'2024-01-15'"
812
+ [endDate]="'2024-01-30'"
813
+ (dateRangeSelected)="onDateRangeSelected($event)">
814
+ </ngx-dual-datepicker>
815
+ ```
816
+
817
+ ### With Events
818
+
819
+ ```typescript
820
+ @Component({
821
+ selector: 'app-example',
822
+ template: `
823
+ <ngx-dual-datepicker
824
+ [startDate]="startDate"
825
+ [endDate]="endDate"
816
826
  (dateRangeSelected)="onDateRangeSelected($event)"
817
827
  (dateRangeChange)="onDateRangeChange($event)">
818
828
  </ngx-dual-datepicker>
819
829
 
820
830
  <div *ngIf="selectedRange">
821
- Selected: {{ selectedRange.rangoTexto }}
831
+ Selected: {{ selectedRange.rangeText }}
822
832
  </div>
823
833
  `
824
834
  })
@@ -828,7 +838,7 @@ export class ExampleComponent {
828
838
  selectedRange: DateRange | null = null;
829
839
 
830
840
  onDateRangeChange(range: DateRange) {
831
- console.log('Date changed:', range.fechaInicio);
841
+ console.log('Date changed:', range.startDate);
832
842
  // Emitted when user selects first date (before completing range)
833
843
  }
834
844
 
@@ -837,53 +847,65 @@ export class ExampleComponent {
837
847
  this.selectedRange = range;
838
848
 
839
849
  // Both dates selected - do something
840
- this.fetchData(range.fechaInicio, range.fechaFin);
850
+ this.fetchData(range.startDate, range.endDate);
841
851
  }
842
852
 
843
853
  fetchData(startDate: string, endDate: string) {
844
854
  // Your API call here
845
- // Dates are in 'YYYY-MM-DD' format,
855
+ // Dates are in 'YYYY-MM-DD' format
856
+ }
857
+ }
858
+ ```
859
+
860
+ ### With ngModel
861
+
862
+ ```typescript
863
+ @Component({
864
+ selector: 'app-example',
846
865
  template: `
847
866
  <ngx-dual-datepicker
848
867
  [(ngModel)]="dateRange"
849
868
  (ngModelChange)="onDateRangeChange($event)">
850
869
  </ngx-dual-datepicker>
851
870
 
852
- <div *ngIf="dateRange.start && dateRange.end">
853
- Selected: {{ formatDateRange() }}
871
+ <div *ngIf="dateRange">
872
+ Selected: {{ dateRange.rangeText }}
873
+ <br>
874
+ From: {{ dateRange.startDate }} to {{ dateRange.endDate }}
854
875
  </div>
855
876
  `
856
877
  })
857
878
  export class ExampleComponent {
858
- dateRange: DateRange = { start: null, end: null };
879
+ dateRange: DateRange | null = null;
859
880
 
860
881
  onDateRangeChange(range: DateRange) {
861
- console.log('Start:', range.start);
862
- console.log('End:', range.end);
863
-
864
- if (range.start && range.end) {
865
- // Both dates selected - do something
866
- this.fetchData(range.start, range.end);
867
- }
882
+ console.log('Start:', range.startDate);
883
+ console.log('End:', range.endDate);
884
+ console.log('Text:', range.rangeText);
868
885
  }
886
+ }
887
+ ```
869
888
 
870
- formatDateRange(): string {
871
- if (!this.dateRange.start || !this.dateRange.end) return '';
872
- return `${this.dateRange.start.toLocaleDateString()} - ${this.dateRange.end.toLocaleDateString()}`;
873
- }
889
+ ### With Styling
874
890
 
875
- fetchData(start: Date, end: Date) {
876
- // Your API call here
877
- }
878
- }
891
+ ```html
892
+ <ngx-dual-datepicker
893
+ [startDate]="startDate"
894
+ [endDate]="endDate"
895
+ placeholder="Pick your dates"
896
+ inputBackgroundColor="#fef3c7"
897
+ inputTextColor="#92400e"
898
+ inputBorderColor="#fbbf24"
899
+ inputBorderColorHover="#f59e0b"
900
+ inputBorderColorFocus="#d97706"
901
+ inputPadding="12px 16px"
902
+ (dateRangeSelected)="onDateRangeSelected($event)">
903
+ </ngx-dual-datepicker>
879
904
  ```
880
905
 
881
906
  ## 🛠️ Requirements
882
907
 
883
908
  - Angular 17.0.0 or higher
884
- - Angular 18.0.0 or higher
885
- - Angular 19.0.0 or higher
886
- - Angular 20.0.0 or higher
887
909
 
888
910
  ## 🗺️ Roadmap
889
911
 
@@ -0,0 +1,101 @@
1
+ import { EventEmitter, OnInit, OnChanges, SimpleChanges, ElementRef } from '@angular/core';
2
+ import { ControlValueAccessor } from '@angular/forms';
3
+ import * as i0 from "@angular/core";
4
+ export interface DateRange {
5
+ startDate: string;
6
+ endDate: string;
7
+ rangeText: string;
8
+ }
9
+ export interface MultiDateRange {
10
+ ranges: DateRange[];
11
+ }
12
+ export interface PresetRange {
13
+ start: string;
14
+ end: string;
15
+ }
16
+ export interface PresetConfig {
17
+ label: string;
18
+ getValue: () => PresetRange;
19
+ }
20
+ export interface LocaleConfig {
21
+ monthNames?: string[];
22
+ monthNamesShort?: string[];
23
+ dayNames?: string[];
24
+ dayNamesShort?: string[];
25
+ firstDayOfWeek?: number;
26
+ }
27
+ export declare class DualDatepickerComponent implements OnInit, OnChanges, ControlValueAccessor {
28
+ private elementRef;
29
+ placeholder: string;
30
+ startDate: string;
31
+ endDate: string;
32
+ showPresets: boolean;
33
+ showClearButton: boolean;
34
+ multiRange: boolean;
35
+ closeOnSelection: boolean;
36
+ closeOnPresetSelection: boolean;
37
+ closeOnClickOutside: boolean;
38
+ presets: PresetConfig[];
39
+ inputBackgroundColor: string;
40
+ inputTextColor: string;
41
+ inputBorderColor: string;
42
+ inputBorderColorHover: string;
43
+ inputBorderColorFocus: string;
44
+ inputPadding: string;
45
+ locale: LocaleConfig;
46
+ dateRangeChange: EventEmitter<DateRange>;
47
+ dateRangeSelected: EventEmitter<DateRange>;
48
+ multiDateRangeChange: EventEmitter<MultiDateRange>;
49
+ multiDateRangeSelected: EventEmitter<MultiDateRange>;
50
+ private dateAdapter;
51
+ showDatePicker: import("@angular/core").WritableSignal<boolean>;
52
+ dateRangeText: import("@angular/core").WritableSignal<string>;
53
+ selectingStartDate: import("@angular/core").WritableSignal<boolean>;
54
+ currentMonth: import("@angular/core").WritableSignal<any>;
55
+ previousMonth: import("@angular/core").WritableSignal<any>;
56
+ currentMonthDays: import("@angular/core").WritableSignal<any[]>;
57
+ previousMonthDays: import("@angular/core").WritableSignal<any[]>;
58
+ isDisabled: import("@angular/core").WritableSignal<boolean>;
59
+ selectedRanges: import("@angular/core").WritableSignal<DateRange[]>;
60
+ currentRangeIndex: import("@angular/core").WritableSignal<number>;
61
+ currentMonthName: import("@angular/core").Signal<string>;
62
+ previousMonthName: import("@angular/core").Signal<string>;
63
+ weekDayNames: import("@angular/core").Signal<string[]>;
64
+ private readonly defaultMonthNames;
65
+ private readonly defaultMonthNamesShort;
66
+ private readonly defaultDayNames;
67
+ private readonly defaultDayNamesShort;
68
+ private onChange;
69
+ private onTouched;
70
+ constructor(elementRef: ElementRef);
71
+ onClickOutside(event: MouseEvent): void;
72
+ ngOnInit(): void;
73
+ ngOnChanges(changes: SimpleChanges): void;
74
+ formatDate(date: Date): string;
75
+ formatDateDisplay(dateStr: string): string;
76
+ updateDateRangeText(): void;
77
+ toggleDatePicker(): void;
78
+ closeDatePicker(): void;
79
+ generateCalendars(): void;
80
+ generateMonthCalendar(date: Date): any[];
81
+ isInRange(dateStr: string): boolean;
82
+ selectDay(dayObj: any): void;
83
+ changeMonth(direction: number): void;
84
+ getMonthName(date: Date): string;
85
+ getDayNames(): string[];
86
+ selectPresetRange(preset: PresetConfig): void;
87
+ clear(): void;
88
+ removeRange(index: number): void;
89
+ private updateMultiRangeText;
90
+ private emitChange;
91
+ private emitSelection;
92
+ private emitMultiChange;
93
+ private emitMultiSelection;
94
+ private getDateRangeValue;
95
+ writeValue(value: DateRange | null): void;
96
+ registerOnChange(fn: (value: DateRange | null) => void): void;
97
+ registerOnTouched(fn: () => void): void;
98
+ setDisabledState(isDisabled: boolean): void;
99
+ static ɵfac: i0.ɵɵFactoryDeclaration<DualDatepickerComponent, never>;
100
+ static ɵcmp: i0.ɵɵComponentDeclaration<DualDatepickerComponent, "ngx-dual-datepicker", never, { "placeholder": { "alias": "placeholder"; "required": false; }; "startDate": { "alias": "startDate"; "required": false; }; "endDate": { "alias": "endDate"; "required": false; }; "showPresets": { "alias": "showPresets"; "required": false; }; "showClearButton": { "alias": "showClearButton"; "required": false; }; "multiRange": { "alias": "multiRange"; "required": false; }; "closeOnSelection": { "alias": "closeOnSelection"; "required": false; }; "closeOnPresetSelection": { "alias": "closeOnPresetSelection"; "required": false; }; "closeOnClickOutside": { "alias": "closeOnClickOutside"; "required": false; }; "presets": { "alias": "presets"; "required": false; }; "inputBackgroundColor": { "alias": "inputBackgroundColor"; "required": false; }; "inputTextColor": { "alias": "inputTextColor"; "required": false; }; "inputBorderColor": { "alias": "inputBorderColor"; "required": false; }; "inputBorderColorHover": { "alias": "inputBorderColorHover"; "required": false; }; "inputBorderColorFocus": { "alias": "inputBorderColorFocus"; "required": false; }; "inputPadding": { "alias": "inputPadding"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
101
+ }