ngxsmk-datepicker 1.2.1 → 1.2.3
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 +1 -2
- package/fesm2022/ngxsmk-datepicker.mjs +35 -104
- package/fesm2022/ngxsmk-datepicker.mjs.map +1 -1
- package/index.d.ts +3 -42
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A powerful, modern, and highly customizable date range picker component for Angular 17+ applications.
|
|
4
4
|
|
|
5
|
-
*
|
|
6
|
-
* Live Demo (StackBlitz): https://stackblitz.com/~/github.com/toozuuu/ngxsmk-datepicker
|
|
5
|
+
* NPM: [https://github.com/toozuuu/ngxsmk-datepicker](https://www.npmjs.com/package/ngxsmk-datepicker)
|
|
7
6
|
|
|
8
7
|
Built with Angular Signals for optimal performance and a clean, declarative API. The component is standalone and has zero dependencies, making it lightweight and easy to integrate into any project.
|
|
9
8
|
|
|
@@ -1,42 +1,33 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, HostListener, Output, Input, Component, PLATFORM_ID, HostBinding, Inject } from '@angular/core';
|
|
2
|
+
import { EventEmitter, inject, ElementRef, HostListener, Output, Input, Component, PLATFORM_ID, HostBinding, Inject } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
|
5
5
|
import { FormsModule } from '@angular/forms';
|
|
6
6
|
|
|
7
|
-
// #####################################################################
|
|
8
|
-
// ## Reusable Custom Select Component
|
|
9
|
-
// #####################################################################
|
|
10
7
|
class CustomSelectComponent {
|
|
11
|
-
constructor(
|
|
12
|
-
this.elementRef = elementRef;
|
|
13
|
-
/** The list of available options to display in the dropdown. */
|
|
8
|
+
constructor() {
|
|
14
9
|
this.options = [];
|
|
15
|
-
/** Emits the new value when an option is selected. */
|
|
16
10
|
this.valueChange = new EventEmitter();
|
|
17
11
|
this.isOpen = false;
|
|
12
|
+
this.elementRef = inject(ElementRef);
|
|
18
13
|
}
|
|
19
|
-
/** Closes the dropdown when a click occurs outside the component boundary. */
|
|
20
14
|
onDocumentClick(event) {
|
|
21
15
|
if (!this.elementRef.nativeElement.contains(event.target))
|
|
22
16
|
this.isOpen = false;
|
|
23
17
|
}
|
|
24
|
-
/** Gets the display label for the currently selected value. */
|
|
25
18
|
get displayValue() {
|
|
26
19
|
const selectedOption = this.options.find((opt) => opt.value === this.value);
|
|
27
20
|
return selectedOption ? selectedOption.label : '';
|
|
28
21
|
}
|
|
29
|
-
/** Toggles the visibility of the dropdown panel. */
|
|
30
22
|
toggleDropdown() {
|
|
31
23
|
this.isOpen = !this.isOpen;
|
|
32
24
|
}
|
|
33
|
-
/** Handles the selection of a new option. */
|
|
34
25
|
selectOption(option) {
|
|
35
26
|
this.value = option.value;
|
|
36
27
|
this.valueChange.emit(this.value);
|
|
37
28
|
this.isOpen = false;
|
|
38
29
|
}
|
|
39
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: CustomSelectComponent, deps: [
|
|
30
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: CustomSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
40
31
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: CustomSelectComponent, isStandalone: true, selector: "app-custom-select", inputs: { options: "options", value: "value" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, ngImport: i0, template: `
|
|
41
32
|
<div class="ngxsmk-select-container" (click)="toggleDropdown()">
|
|
42
33
|
<button type="button" class="ngxsmk-select-display">
|
|
@@ -84,7 +75,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
84
75
|
}
|
|
85
76
|
</div>
|
|
86
77
|
`, styles: [":host{position:relative;display:inline-block}.ngxsmk-select-container{cursor:pointer}.ngxsmk-select-display{display:flex;align-items:center;justify-content:space-between;width:var(--custom-select-width, 115px);background:var(--datepicker-background, #fff);border:1px solid var(--datepicker-border-color, #ccc);color:var(--datepicker-text-color, #333);border-radius:4px;padding:4px 8px;font-size:14px;text-align:left;height:30px}.ngxsmk-arrow-icon{width:12px;height:12px;margin-left:8px}.ngxsmk-options-panel{position:absolute;top:110%;left:0;width:100%;background:var(--datepicker-background, #fff);border:1px solid var(--datepicker-border-color, #ccc);color:var(--datepicker-text-color, #333);border-radius:4px;box-shadow:0 4px 8px #0000001a;max-height:200px;overflow-y:auto;z-index:9999}.ngxsmk-options-panel ul{list-style:none;padding:4px;margin:0}.ngxsmk-options-panel li{padding:8px 12px;border-radius:4px;cursor:pointer}.ngxsmk-options-panel li:hover{background-color:var(--datepicker-hover-background, #f0f0f0)}.ngxsmk-options-panel li.selected{background-color:var(--datepicker-primary-color, #3880ff);color:var(--datepicker-primary-contrast, #fff)}\n"] }]
|
|
87
|
-
}],
|
|
78
|
+
}], propDecorators: { options: [{
|
|
88
79
|
type: Input
|
|
89
80
|
}], value: [{
|
|
90
81
|
type: Input
|
|
@@ -95,25 +86,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
95
86
|
args: ['document:click', ['$event']]
|
|
96
87
|
}] } });
|
|
97
88
|
class NgxsmkDatepickerComponent {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return this._locale;
|
|
104
|
-
}
|
|
105
|
-
get isDarkMode() {
|
|
106
|
-
return this.theme === 'dark';
|
|
107
|
-
}
|
|
108
|
-
/** The earliest selectable date. */
|
|
109
|
-
set minDate(value) {
|
|
110
|
-
this._minDate = this._normalizeDate(value);
|
|
111
|
-
}
|
|
112
|
-
/** The latest selectable date. */
|
|
113
|
-
set maxDate(value) {
|
|
114
|
-
this._maxDate = this._normalizeDate(value);
|
|
115
|
-
}
|
|
116
|
-
/** An object of predefined date ranges for quick selection. */
|
|
89
|
+
set locale(value) { this._locale = value; }
|
|
90
|
+
get locale() { return this._locale; }
|
|
91
|
+
get isDarkMode() { return this.theme === 'dark'; }
|
|
92
|
+
set minDate(value) { this._minDate = this._normalizeDate(value); }
|
|
93
|
+
set maxDate(value) { this._maxDate = this._normalizeDate(value); }
|
|
117
94
|
set ranges(value) {
|
|
118
95
|
if (!value) {
|
|
119
96
|
this._ranges = null;
|
|
@@ -130,23 +107,14 @@ class NgxsmkDatepickerComponent {
|
|
|
130
107
|
this.updateRangesArray();
|
|
131
108
|
}
|
|
132
109
|
constructor(platformId) {
|
|
133
|
-
this.platformId = platformId;
|
|
134
|
-
/** Sets the selection mode: 'single' date or 'range' selection. */
|
|
135
110
|
this.mode = 'single';
|
|
136
|
-
/** A function to programmatically disable specific dates. Returns true if the date should be disabled. */
|
|
137
111
|
this.isInvalidDate = () => false;
|
|
138
|
-
/** If true, displays the predefined ranges panel when in 'range' mode. */
|
|
139
112
|
this.showRanges = true;
|
|
140
|
-
/** If true, displays the time selection controls (hour/minute). */
|
|
141
113
|
this.showTime = false;
|
|
142
|
-
/** Sets the minute selection step/interval (e.g., 5, 15, 30). */
|
|
143
114
|
this.minuteInterval = 1;
|
|
144
|
-
/** The initial selected date or date range. Accepts Date, or { start: Date, end: Date }. */
|
|
145
115
|
this.value = null;
|
|
146
116
|
this._locale = 'en-US';
|
|
147
|
-
/** Controls the visual theme: 'light' or 'dark'. */
|
|
148
117
|
this.theme = 'light';
|
|
149
|
-
/** Emits the newly selected date or date range. */
|
|
150
118
|
this.valueChange = new EventEmitter();
|
|
151
119
|
this._minDate = null;
|
|
152
120
|
this._maxDate = null;
|
|
@@ -163,24 +131,19 @@ class NgxsmkDatepickerComponent {
|
|
|
163
131
|
this.monthOptions = [];
|
|
164
132
|
this.yearOptions = [];
|
|
165
133
|
this.firstDayOfWeek = 0;
|
|
166
|
-
|
|
167
|
-
this.currentHour = 0; // Internal 24h format (0-23)
|
|
134
|
+
this.currentHour = 0;
|
|
168
135
|
this.currentMinute = 0;
|
|
169
|
-
this.currentDisplayHour = 12;
|
|
170
|
-
this.isPm = false;
|
|
136
|
+
this.currentDisplayHour = 12;
|
|
137
|
+
this.isPm = false;
|
|
171
138
|
this.hourOptions = [];
|
|
172
139
|
this.minuteOptions = [];
|
|
173
140
|
this.ampmOptions = [
|
|
174
141
|
{ label: 'AM', value: false },
|
|
175
142
|
{ label: 'PM', value: true }
|
|
176
143
|
];
|
|
177
|
-
|
|
178
|
-
this._locale = navigator.language;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
get currentMonth() {
|
|
182
|
-
return this._currentMonth;
|
|
144
|
+
this.platformId = platformId;
|
|
183
145
|
}
|
|
146
|
+
get currentMonth() { return this._currentMonth; }
|
|
184
147
|
set currentMonth(month) {
|
|
185
148
|
if (this._currentMonth !== month) {
|
|
186
149
|
this._currentMonth = month;
|
|
@@ -188,9 +151,7 @@ class NgxsmkDatepickerComponent {
|
|
|
188
151
|
this.generateCalendar();
|
|
189
152
|
}
|
|
190
153
|
}
|
|
191
|
-
get currentYear() {
|
|
192
|
-
return this._currentYear;
|
|
193
|
-
}
|
|
154
|
+
get currentYear() { return this._currentYear; }
|
|
194
155
|
set currentYear(year) {
|
|
195
156
|
if (this._currentYear !== year) {
|
|
196
157
|
this._currentYear = year;
|
|
@@ -199,10 +160,14 @@ class NgxsmkDatepickerComponent {
|
|
|
199
160
|
}
|
|
200
161
|
}
|
|
201
162
|
ngOnInit() {
|
|
163
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
164
|
+
if (this._locale === 'en-US') {
|
|
165
|
+
this._locale = navigator.language;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
202
168
|
this.today.setHours(0, 0, 0, 0);
|
|
203
169
|
this.generateLocaleData();
|
|
204
170
|
this.generateTimeOptions();
|
|
205
|
-
// Set default time to current time if enabled and no initial value
|
|
206
171
|
if (this.showTime && !this.value) {
|
|
207
172
|
const now = new Date();
|
|
208
173
|
this.currentHour = now.getHours();
|
|
@@ -223,10 +188,8 @@ class NgxsmkDatepickerComponent {
|
|
|
223
188
|
this.generateLocaleData();
|
|
224
189
|
this.generateCalendar();
|
|
225
190
|
}
|
|
226
|
-
// Regenerate time options if the interval changes
|
|
227
191
|
if (changes['minuteInterval']) {
|
|
228
192
|
this.generateTimeOptions();
|
|
229
|
-
// Recalculate and round current minute to the new interval
|
|
230
193
|
this.currentMinute = Math.floor(this.currentMinute / this.minuteInterval) * this.minuteInterval;
|
|
231
194
|
this.onTimeChange();
|
|
232
195
|
}
|
|
@@ -235,28 +198,21 @@ class NgxsmkDatepickerComponent {
|
|
|
235
198
|
this.generateCalendar();
|
|
236
199
|
}
|
|
237
200
|
}
|
|
238
|
-
/** Converts the displayed 12h time (currentDisplayHour + isPm) into the 24h internal time (currentHour). */
|
|
239
201
|
get24Hour(displayHour, isPm) {
|
|
240
202
|
if (isPm) {
|
|
241
|
-
return displayHour === 12 ? 12 : displayHour + 12;
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
return displayHour === 12 ? 0 : displayHour; // 12 AM is 0 (midnight), 1-11 AM is 1-11
|
|
203
|
+
return displayHour === 12 ? 12 : displayHour + 12;
|
|
245
204
|
}
|
|
205
|
+
return displayHour === 12 ? 0 : displayHour;
|
|
246
206
|
}
|
|
247
|
-
/** Updates the display time variables (12h format and AM/PM state) from the 24h internal time. */
|
|
248
207
|
update12HourState(fullHour) {
|
|
249
208
|
this.isPm = fullHour >= 12;
|
|
250
|
-
this.currentDisplayHour = fullHour % 12 || 12;
|
|
209
|
+
this.currentDisplayHour = fullHour % 12 || 12;
|
|
251
210
|
}
|
|
252
|
-
/** Applies the currently selected hour and minute to a given date object. */
|
|
253
211
|
applyCurrentTime(date) {
|
|
254
|
-
// Convert 12h display state back to 24h format
|
|
255
212
|
this.currentHour = this.get24Hour(this.currentDisplayHour, this.isPm);
|
|
256
213
|
date.setHours(this.currentHour, this.currentMinute, 0, 0);
|
|
257
214
|
return date;
|
|
258
215
|
}
|
|
259
|
-
/** Initializes selection state and time controls from the provided input value. */
|
|
260
216
|
initializeValue(value) {
|
|
261
217
|
if (!value) {
|
|
262
218
|
this.selectedDate = null;
|
|
@@ -276,15 +232,12 @@ class NgxsmkDatepickerComponent {
|
|
|
276
232
|
}
|
|
277
233
|
if (initialDate) {
|
|
278
234
|
this.currentDate = new Date(initialDate);
|
|
279
|
-
// Set time selectors based on 24h value from initial date
|
|
280
235
|
this.currentHour = initialDate.getHours();
|
|
281
236
|
this.currentMinute = initialDate.getMinutes();
|
|
282
237
|
this.update12HourState(this.currentHour);
|
|
283
|
-
// Round minute to nearest interval, in case the initial value time doesn't match the current interval
|
|
284
238
|
this.currentMinute = Math.floor(this.currentMinute / this.minuteInterval) * this.minuteInterval;
|
|
285
239
|
}
|
|
286
240
|
}
|
|
287
|
-
/** Normalizes a date input to a Date object, keeping time information. */
|
|
288
241
|
_normalizeDate(date) {
|
|
289
242
|
if (!date)
|
|
290
243
|
return null;
|
|
@@ -293,12 +246,10 @@ class NgxsmkDatepickerComponent {
|
|
|
293
246
|
return null;
|
|
294
247
|
return d;
|
|
295
248
|
}
|
|
296
|
-
/** Generates options for the hour and minute selectors based on the interval. */
|
|
297
249
|
generateTimeOptions() {
|
|
298
|
-
// Hours are 1 through 12 for 12h format display
|
|
299
250
|
this.hourOptions = Array.from({ length: 12 }).map((_, i) => ({
|
|
300
251
|
label: (i + 1).toString().padStart(2, '0'),
|
|
301
|
-
value: i + 1,
|
|
252
|
+
value: i + 1,
|
|
302
253
|
}));
|
|
303
254
|
this.minuteOptions = [];
|
|
304
255
|
for (let i = 0; i < 60; i += this.minuteInterval) {
|
|
@@ -308,17 +259,19 @@ class NgxsmkDatepickerComponent {
|
|
|
308
259
|
});
|
|
309
260
|
}
|
|
310
261
|
}
|
|
311
|
-
/** Generates locale-dependent month and weekday names. */
|
|
312
262
|
generateLocaleData() {
|
|
313
263
|
this.monthOptions = Array.from({ length: 12 }).map((_, i) => ({
|
|
314
264
|
label: new Date(2024, i, 1).toLocaleDateString(this.locale, { month: 'long' }),
|
|
315
265
|
value: i,
|
|
316
266
|
}));
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
267
|
+
this.firstDayOfWeek = 0;
|
|
268
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
269
|
+
try {
|
|
270
|
+
this.firstDayOfWeek = (new Intl.Locale(this.locale).weekInfo?.firstDay || 0) % 7;
|
|
271
|
+
}
|
|
272
|
+
catch (e) {
|
|
273
|
+
this.firstDayOfWeek = 0;
|
|
274
|
+
}
|
|
322
275
|
}
|
|
323
276
|
const day = new Date(2024, 0, 7 + this.firstDayOfWeek);
|
|
324
277
|
this.weekDays = Array.from({ length: 7 }).map(() => {
|
|
@@ -327,27 +280,22 @@ class NgxsmkDatepickerComponent {
|
|
|
327
280
|
return weekDay;
|
|
328
281
|
});
|
|
329
282
|
}
|
|
330
|
-
/** Populates the internal array of predefined ranges. */
|
|
331
283
|
updateRangesArray() {
|
|
332
284
|
this.rangesArray = this._ranges ? Object.entries(this._ranges).map(([key, value]) => ({ key, value })) : [];
|
|
333
285
|
}
|
|
334
|
-
/** Handles selection of a predefined date range. */
|
|
335
286
|
selectRange(range) {
|
|
336
287
|
this.startDate = this.applyCurrentTime(range[0]);
|
|
337
288
|
this.endDate = this.applyCurrentTime(range[1]);
|
|
338
289
|
if (this.startDate && this.endDate) {
|
|
339
|
-
/** Type assertion is safe here as both dates are explicitly set */
|
|
340
290
|
this.valueChange.emit({ start: this.startDate, end: this.endDate });
|
|
341
291
|
}
|
|
342
292
|
this.currentDate = new Date(this.startDate);
|
|
343
|
-
this.initializeValue({ start: this.startDate, end: this.endDate });
|
|
293
|
+
this.initializeValue({ start: this.startDate, end: this.endDate });
|
|
344
294
|
this.generateCalendar();
|
|
345
295
|
}
|
|
346
|
-
/** Checks if a specific date should be disabled based on minDate, maxDate, or custom function. */
|
|
347
296
|
isDateDisabled(date) {
|
|
348
297
|
if (!date)
|
|
349
298
|
return false;
|
|
350
|
-
// Check against minDate/maxDate, ensuring we compare only the date part
|
|
351
299
|
const dateOnly = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
352
300
|
if (this._minDate) {
|
|
353
301
|
const minDateOnly = new Date(this._minDate.getFullYear(), this._minDate.getMonth(), this._minDate.getDate());
|
|
@@ -359,11 +307,8 @@ class NgxsmkDatepickerComponent {
|
|
|
359
307
|
if (dateOnly > maxDateOnly)
|
|
360
308
|
return true;
|
|
361
309
|
}
|
|
362
|
-
|
|
363
|
-
return true;
|
|
364
|
-
return false;
|
|
310
|
+
return this.isInvalidDate(date);
|
|
365
311
|
}
|
|
366
|
-
/** Updates the time component of the selected date(s) when hour/minute selectors change. */
|
|
367
312
|
onTimeChange() {
|
|
368
313
|
if (this.mode === 'single' && this.selectedDate) {
|
|
369
314
|
this.selectedDate = this.applyCurrentTime(this.selectedDate);
|
|
@@ -372,15 +317,12 @@ class NgxsmkDatepickerComponent {
|
|
|
372
317
|
else if (this.mode === 'range' && this.startDate && this.endDate) {
|
|
373
318
|
this.startDate = this.applyCurrentTime(this.startDate);
|
|
374
319
|
this.endDate = this.applyCurrentTime(this.endDate);
|
|
375
|
-
/** Type assertion is safe here as both dates are confirmed */
|
|
376
320
|
this.valueChange.emit({ start: this.startDate, end: this.endDate });
|
|
377
321
|
}
|
|
378
322
|
else if (this.mode === 'range' && this.startDate && !this.endDate) {
|
|
379
|
-
// If range started but not completed, update time on the start date only (no emit)
|
|
380
323
|
this.startDate = this.applyCurrentTime(this.startDate);
|
|
381
324
|
}
|
|
382
325
|
}
|
|
383
|
-
/** Handles the click event on a calendar day cell. */
|
|
384
326
|
onDateClick(day) {
|
|
385
327
|
if (!day || this.isDateDisabled(day))
|
|
386
328
|
return;
|
|
@@ -389,14 +331,12 @@ class NgxsmkDatepickerComponent {
|
|
|
389
331
|
this.valueChange.emit(this.selectedDate);
|
|
390
332
|
}
|
|
391
333
|
else {
|
|
392
|
-
// Range selection logic
|
|
393
334
|
if (!this.startDate || (this.startDate && this.endDate)) {
|
|
394
335
|
this.startDate = this.applyCurrentTime(day);
|
|
395
336
|
this.endDate = null;
|
|
396
337
|
}
|
|
397
338
|
else if (day >= this.startDate) {
|
|
398
339
|
this.endDate = this.applyCurrentTime(day);
|
|
399
|
-
/** Type assertion is safe here as both dates are set when ending a range */
|
|
400
340
|
this.valueChange.emit({ start: this.startDate, end: this.endDate });
|
|
401
341
|
}
|
|
402
342
|
else {
|
|
@@ -405,7 +345,6 @@ class NgxsmkDatepickerComponent {
|
|
|
405
345
|
}
|
|
406
346
|
this.hoveredDate = null;
|
|
407
347
|
}
|
|
408
|
-
// Update time controls to reflect the time of the newly selected date
|
|
409
348
|
if (this.mode === 'single' && this.selectedDate) {
|
|
410
349
|
this.update12HourState(this.selectedDate.getHours());
|
|
411
350
|
this.currentMinute = this.selectedDate.getMinutes();
|
|
@@ -415,13 +354,11 @@ class NgxsmkDatepickerComponent {
|
|
|
415
354
|
this.currentMinute = this.startDate.getMinutes();
|
|
416
355
|
}
|
|
417
356
|
}
|
|
418
|
-
/** Handles hover events for range preview when only the start date is selected. */
|
|
419
357
|
onDateHover(day) {
|
|
420
358
|
if (this.mode === 'range' && this.startDate && !this.endDate && day) {
|
|
421
359
|
this.hoveredDate = day;
|
|
422
360
|
}
|
|
423
361
|
}
|
|
424
|
-
/** Checks if a date is within the range being previewed (during hover). */
|
|
425
362
|
isPreviewInRange(day) {
|
|
426
363
|
if (this.mode !== 'range' || !this.startDate || this.endDate || !this.hoveredDate || !day)
|
|
427
364
|
return false;
|
|
@@ -430,7 +367,6 @@ class NgxsmkDatepickerComponent {
|
|
|
430
367
|
const time = day.getTime();
|
|
431
368
|
return time > Math.min(start, end) && time < Math.max(start, end);
|
|
432
369
|
}
|
|
433
|
-
/** Generates the calendar grid for the currently active month. */
|
|
434
370
|
generateCalendar() {
|
|
435
371
|
this.daysInMonth = [];
|
|
436
372
|
const year = this.currentDate.getFullYear();
|
|
@@ -449,7 +385,6 @@ class NgxsmkDatepickerComponent {
|
|
|
449
385
|
this.daysInMonth.push(this._normalizeDate(new Date(year, month, i)));
|
|
450
386
|
}
|
|
451
387
|
}
|
|
452
|
-
/** Generates month and year options for dropdowns. */
|
|
453
388
|
generateDropdownOptions() {
|
|
454
389
|
const startYear = this._currentYear - 10;
|
|
455
390
|
const endYear = this._currentYear + 10;
|
|
@@ -458,12 +393,10 @@ class NgxsmkDatepickerComponent {
|
|
|
458
393
|
this.yearOptions.push({ label: `${i}`, value: i });
|
|
459
394
|
}
|
|
460
395
|
}
|
|
461
|
-
/** Moves the calendar view forward or backward by one month. */
|
|
462
396
|
changeMonth(delta) {
|
|
463
397
|
this.currentDate.setMonth(this.currentDate.getMonth() + delta);
|
|
464
398
|
this.generateCalendar();
|
|
465
399
|
}
|
|
466
|
-
/** Utility function to check if two dates represent the same day (ignoring time). */
|
|
467
400
|
isSameDay(d1, d2) {
|
|
468
401
|
if (!d1 || !d2)
|
|
469
402
|
return false;
|
|
@@ -471,11 +404,9 @@ class NgxsmkDatepickerComponent {
|
|
|
471
404
|
d1.getMonth() === d2.getMonth() &&
|
|
472
405
|
d1.getDate() === d2.getDate());
|
|
473
406
|
}
|
|
474
|
-
/** Checks if a date is strictly between the start and end of a selected range (ignoring time). */
|
|
475
407
|
isInRange(d) {
|
|
476
408
|
if (!d || !this.startDate || !this.endDate)
|
|
477
409
|
return false;
|
|
478
|
-
// Use date-only comparison for highlighting the days
|
|
479
410
|
const dTime = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
|
|
480
411
|
const startDayTime = new Date(this.startDate.getFullYear(), this.startDate.getMonth(), this.startDate.getDate()).getTime();
|
|
481
412
|
const endDayTime = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate()).getTime();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngxsmk-datepicker.mjs","sources":["../../../projects/ngxsmk-datepicker/src/lib/ngxsmk-datepicker.ts","../../../projects/ngxsmk-datepicker/src/public-api.ts","../../../projects/ngxsmk-datepicker/src/ngxsmk-datepicker.ts"],"sourcesContent":["import {\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n HostBinding,\r\n HostListener,\r\n Inject,\r\n Input,\r\n OnChanges,\r\n OnInit,\r\n Output,\r\n PLATFORM_ID,\r\n SimpleChanges,\r\n} from '@angular/core';\r\nimport {CommonModule, isPlatformBrowser} from '@angular/common';\r\nimport {FormsModule} from '@angular/forms';\r\n\r\n// #####################################################################\r\n// ## Reusable Custom Select Component\r\n// #####################################################################\r\n@Component({\r\n selector: 'app-custom-select',\r\n standalone: true,\r\n imports: [CommonModule],\r\n template: `\r\n <div class=\"ngxsmk-select-container\" (click)=\"toggleDropdown()\">\r\n <button type=\"button\" class=\"ngxsmk-select-display\">\r\n <span>{{ displayValue }}</span>\r\n <svg class=\"ngxsmk-arrow-icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48\"\r\n d=\"M112 184l144 144 144-144\"/>\r\n </svg>\r\n </button>\r\n @if (isOpen) {\r\n <div class=\"ngxsmk-options-panel\">\r\n <ul>\r\n @for (option of options; track option.value) {\r\n <li [class.selected]=\"option.value === value\" (click)=\"selectOption(option); $event.stopPropagation()\">\r\n {{ option.label }}\r\n </li>\r\n }\r\n </ul>\r\n </div>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n position: relative;\r\n display: inline-block;\r\n }\r\n\r\n .ngxsmk-select-container {\r\n cursor: pointer;\r\n }\r\n\r\n .ngxsmk-select-display {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n width: var(--custom-select-width, 115px);\r\n background: var(--datepicker-background, #fff);\r\n border: 1px solid var(--datepicker-border-color, #ccc);\r\n color: var(--datepicker-text-color, #333);\r\n border-radius: 4px;\r\n padding: 4px 8px;\r\n font-size: 14px;\r\n text-align: left;\r\n height: 30px;\r\n }\r\n\r\n .ngxsmk-arrow-icon {\r\n width: 12px;\r\n height: 12px;\r\n margin-left: 8px;\r\n }\r\n\r\n .ngxsmk-options-panel {\r\n position: absolute;\r\n top: 110%; /* Relative to the host element's height */\r\n left: 0;\r\n width: 100%;\r\n background: var(--datepicker-background, #fff);\r\n border: 1px solid var(--datepicker-border-color, #ccc);\r\n color: var(--datepicker-text-color, #333);\r\n border-radius: 4px;\r\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\r\n max-height: 200px;\r\n overflow-y: auto;\r\n z-index: 9999; /* Highest Z-index for visibility */\r\n }\r\n\r\n .ngxsmk-options-panel ul {\r\n list-style: none;\r\n padding: 4px;\r\n margin: 0;\r\n }\r\n\r\n .ngxsmk-options-panel li {\r\n padding: 8px 12px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n }\r\n\r\n .ngxsmk-options-panel li:hover {\r\n background-color: var(--datepicker-hover-background, #f0f0f0);\r\n }\r\n\r\n .ngxsmk-options-panel li.selected {\r\n background-color: var(--datepicker-primary-color, #3880ff);\r\n color: var(--datepicker-primary-contrast, #fff);\r\n }\r\n `],\r\n})\r\nexport class CustomSelectComponent {\r\n /** The list of available options to display in the dropdown. */\r\n @Input() options: { label: string; value: any }[] = [];\r\n /** The currently selected value. */\r\n @Input() value: any;\r\n /** Emits the new value when an option is selected. */\r\n @Output() valueChange = new EventEmitter<any>();\r\n public isOpen = false;\r\n\r\n constructor(private readonly elementRef: ElementRef) {\r\n }\r\n\r\n /** Closes the dropdown when a click occurs outside the component boundary. */\r\n @HostListener('document:click', ['$event'])\r\n onDocumentClick(event: MouseEvent): void {\r\n if (!this.elementRef.nativeElement.contains(event.target)) this.isOpen = false;\r\n }\r\n\r\n /** Gets the display label for the currently selected value. */\r\n get displayValue(): string {\r\n const selectedOption = this.options.find((opt) => opt.value === this.value);\r\n return selectedOption ? selectedOption.label : '';\r\n }\r\n\r\n /** Toggles the visibility of the dropdown panel. */\r\n toggleDropdown(): void {\r\n this.isOpen = !this.isOpen;\r\n }\r\n\r\n /** Handles the selection of a new option. */\r\n selectOption(option: { label: string; value: any }): void {\r\n this.value = option.value;\r\n this.valueChange.emit(this.value);\r\n this.isOpen = false;\r\n }\r\n}\r\n\r\n// #####################################################################\r\n// ## Datepicker Component\r\n// #####################################################################\r\nexport type DateInput = Date | string | { toDate: () => Date; _isAMomentObject?: boolean; $d?: Date };\r\n\r\nexport interface DateRange {\r\n [key: string]: [DateInput, DateInput];\r\n}\r\n\r\n@Component({\r\n selector: 'ngxsmk-datepicker',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule, CustomSelectComponent],\r\n template: `\r\n <div class=\"ngxsmk-datepicker-container\">\r\n @if (showRanges && rangesArray.length > 0 && mode === 'range') {\r\n <div class=\"ngxsmk-ranges-container\">\r\n <ul>\r\n @for (range of rangesArray; track range.key) {\r\n <li (click)=\"selectRange(range.value)\">{{ range.key }}</li>\r\n }\r\n </ul>\r\n </div>\r\n }\r\n <div class=\"ngxsmk-calendar-container\">\r\n <div class=\"ngxsmk-header\">\r\n <div class=\"ngxsmk-month-year-selects\">\r\n <app-custom-select class=\"month-select\" [options]=\"monthOptions\"\r\n [(value)]=\"currentMonth\"></app-custom-select>\r\n <app-custom-select class=\"year-select\" [options]=\"yearOptions\" [(value)]=\"currentYear\"></app-custom-select>\r\n </div>\r\n <div class=\"ngxsmk-nav-buttons\">\r\n <button type=\"button\" class=\"ngxsmk-nav-button\" (click)=\"changeMonth(-1)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48\"\r\n d=\"M328 112L184 256l144 144\"/>\r\n </svg>\r\n </button>\r\n <button type=\"button\" class=\"ngxsmk-nav-button\" (click)=\"changeMonth(1)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48\"\r\n d=\"M184 112l144 144-144 144\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"ngxsmk-days-grid-wrapper\">\r\n <div class=\"ngxsmk-days-grid\">\r\n @for (day of weekDays; track day) {\r\n <div class=\"ngxsmk-day-name\">{{ day }}</div>\r\n }\r\n @for (day of daysInMonth; track $index) {\r\n <div class=\"ngxsmk-day-cell\"\r\n [class.empty]=\"!day\" [class.disabled]=\"isDateDisabled(day)\" [class.today]=\"isSameDay(day, today)\"\r\n [class.selected]=\"mode === 'single' && isSameDay(day, selectedDate)\"\r\n [class.start-date]=\"mode === 'range' && isSameDay(day, startDate)\"\r\n [class.end-date]=\"mode === 'range' && isSameDay(day, endDate)\"\r\n [class.in-range]=\"mode === 'range' && isInRange(day)\"\r\n [class.preview-range]=\"isPreviewInRange(day)\"\r\n (click)=\"onDateClick(day)\" (mouseenter)=\"onDateHover(day)\">\r\n @if (day) {\r\n <div class=\"ngxsmk-day-number\">{{ day | date : 'd' }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (showTime) {\r\n <div class=\"ngxsmk-time-selection\">\r\n <span class=\"ngxsmk-time-label\">Time:</span>\r\n <app-custom-select\r\n class=\"hour-select\"\r\n [options]=\"hourOptions\"\r\n [(value)]=\"currentDisplayHour\"\r\n (valueChange)=\"onTimeChange()\"\r\n ></app-custom-select>\r\n <span class=\"ngxsmk-time-separator\">:</span>\r\n <app-custom-select\r\n class=\"minute-select\"\r\n [options]=\"minuteOptions\"\r\n [(value)]=\"currentMinute\"\r\n (valueChange)=\"onTimeChange()\"\r\n ></app-custom-select>\r\n <app-custom-select\r\n class=\"ampm-select\"\r\n [options]=\"ampmOptions\"\r\n [(value)]=\"isPm\"\r\n (valueChange)=\"onTimeChange()\"\r\n ></app-custom-select>\r\n </div>\r\n }\r\n\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n --datepicker-primary-color: #6d28d9;\r\n --datepicker-primary-contrast: #ffffff;\r\n --datepicker-range-background: #f5f3ff;\r\n --datepicker-background: #ffffff;\r\n --datepicker-text-color: #222428;\r\n --datepicker-subtle-text-color: #9ca3af;\r\n --datepicker-border-color: #e9e9e9;\r\n --datepicker-hover-background: #f0f0f0;\r\n }\r\n\r\n :host(.dark-theme) {\r\n --datepicker-range-background: rgba(139, 92, 246, 0.2);\r\n --datepicker-background: #1f2937;\r\n --datepicker-text-color: #d1d5db;\r\n --datepicker-subtle-text-color: #6b7280;\r\n --datepicker-border-color: #4b5563;\r\n --datepicker-hover-background: #374151;\r\n }\r\n\r\n .ngxsmk-datepicker-container {\r\n display: flex;\r\n }\r\n\r\n .ngxsmk-calendar-container {\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n border-radius: 10px;\r\n padding: 16px;\r\n background: var(--datepicker-background);\r\n }\r\n\r\n .ngxsmk-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n position: relative;\r\n z-index: 2;\r\n gap: 5px;\r\n }\r\n\r\n .ngxsmk-month-year-selects {\r\n display: flex;\r\n gap: 5px;\r\n }\r\n\r\n .ngxsmk-month-year-selects app-custom-select.month-select {\r\n --custom-select-width: 120px;\r\n }\r\n\r\n .ngxsmk-month-year-selects app-custom-select.year-select {\r\n --custom-select-width: 90px;\r\n }\r\n\r\n .ngxsmk-nav-buttons {\r\n display: flex;\r\n }\r\n\r\n .ngxsmk-nav-button {\r\n background: none;\r\n border: none;\r\n padding: 8px;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--datepicker-text-color);\r\n }\r\n\r\n .ngxsmk-nav-button:hover {\r\n background-color: var(--datepicker-hover-background);\r\n }\r\n\r\n .ngxsmk-nav-button svg {\r\n width: 18px;\r\n height: 18px;\r\n }\r\n\r\n .ngxsmk-days-grid-wrapper {\r\n position: relative;\r\n }\r\n\r\n .ngxsmk-days-grid {\r\n display: grid;\r\n grid-template-columns: repeat(7, 1fr);\r\n text-align: center;\r\n gap: 0;\r\n }\r\n\r\n .ngxsmk-day-name {\r\n font-weight: 600;\r\n font-size: 0.8rem;\r\n color: var(--datepicker-subtle-text-color);\r\n padding: 8px 0;\r\n }\r\n\r\n .ngxsmk-day-cell {\r\n position: relative;\r\n height: 38px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n cursor: pointer;\r\n border-radius: 0;\r\n }\r\n\r\n .ngxsmk-day-number {\r\n width: 36px;\r\n height: 36px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n border-radius: 50%;\r\n color: var(--datepicker-text-color);\r\n position: relative;\r\n z-index: 1;\r\n }\r\n\r\n .ngxsmk-day-cell:not(.disabled):hover .ngxsmk-day-number {\r\n background-color: var(--datepicker-hover-background);\r\n color: var(--datepicker-primary-color);\r\n }\r\n\r\n .ngxsmk-day-cell.start-date .ngxsmk-day-number,\r\n .ngxsmk-day-cell.end-date .ngxsmk-day-number,\r\n .ngxsmk-day-cell.selected .ngxsmk-day-number {\r\n background-color: var(--datepicker-primary-color);\r\n color: var(--datepicker-primary-contrast);\r\n }\r\n\r\n /* --- Range Highlight --- */\r\n .ngxsmk-day-cell.in-range,\r\n .ngxsmk-day-cell.start-date,\r\n .ngxsmk-day-cell.end-date,\r\n .ngxsmk-day-cell.preview-range {\r\n background-color: var(--datepicker-range-background);\r\n }\r\n\r\n /* Apply radius to the edge cells */\r\n .ngxsmk-day-cell.start-date {\r\n border-top-left-radius: 100%;\r\n border-bottom-left-radius: 100%;\r\n }\r\n\r\n .ngxsmk-day-cell.end-date {\r\n border-top-right-radius: 100%;\r\n border-bottom-right-radius: 100%;\r\n }\r\n\r\n .ngxsmk-day-cell.start-date.end-date {\r\n border-radius: 50px;\r\n }\r\n /* --- End Range Highlight --- */\r\n\r\n .ngxsmk-day-cell.disabled {\r\n background-color: transparent !important;\r\n color: #4b5563;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n opacity: 0.5;\r\n }\r\n\r\n .ngxsmk-day-cell.today .ngxsmk-day-number {\r\n border: 1px solid var(--datepicker-primary-color);\r\n }\r\n\r\n .ngxsmk-ranges-container {\r\n width: 180px;\r\n padding: 16px;\r\n border-right: 1px solid var(--datepicker-border-color);\r\n background: var(--datepicker-background);\r\n }\r\n\r\n .ngxsmk-ranges-container ul {\r\n list-style: none;\r\n padding: 0;\r\n margin: 0;\r\n }\r\n\r\n .ngxsmk-ranges-container li {\r\n padding: 10px;\r\n margin-bottom: 8px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n color: var(--datepicker-text-color);\r\n }\r\n\r\n .ngxsmk-ranges-container li:hover {\r\n background-color: var(--datepicker-hover-background);\r\n }\r\n\r\n .ngxsmk-time-selection {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n margin-top: 16px;\r\n padding-top: 12px;\r\n border-top: 1px solid var(--datepicker-border-color);\r\n }\r\n\r\n .ngxsmk-time-label {\r\n font-size: 0.9rem;\r\n color: var(--datepicker-subtle-text-color);\r\n margin-right: 4px;\r\n }\r\n\r\n .ngxsmk-time-selection app-custom-select {\r\n --custom-select-width: 60px;\r\n height: 30px;\r\n }\r\n\r\n .ngxsmk-time-selection app-custom-select.ampm-select {\r\n --custom-select-width: 70px;\r\n }\r\n\r\n .ngxsmk-time-separator {\r\n font-weight: 600;\r\n font-size: 1.1rem;\r\n color: var(--datepicker-text-color);\r\n }\r\n `],\r\n})\r\nexport class NgxsmkDatepickerComponent implements OnInit, OnChanges {\r\n /** Sets the selection mode: 'single' date or 'range' selection. */\r\n @Input() mode: 'single' | 'range' = 'single';\r\n /** A function to programmatically disable specific dates. Returns true if the date should be disabled. */\r\n @Input() isInvalidDate: (date: Date) => boolean = () => false;\r\n /** If true, displays the predefined ranges panel when in 'range' mode. */\r\n @Input() showRanges: boolean = true;\r\n /** If true, displays the time selection controls (hour/minute). */\r\n @Input() showTime: boolean = false;\r\n /** Sets the minute selection step/interval (e.g., 5, 15, 30). */\r\n @Input() minuteInterval: number = 1;\r\n\r\n /** The initial selected date or date range. Accepts Date, or { start: Date, end: Date }. */\r\n @Input() value: Date | { start: Date, end: Date } | null = null;\r\n\r\n private _locale: string = 'en-US';\r\n\r\n /** Sets the locale for language and regional formatting (e.g., 'en-US', 'de-DE'). */\r\n @Input() set locale(value: string) {\r\n this._locale = value;\r\n }\r\n\r\n get locale(): string {\r\n return this._locale;\r\n }\r\n\r\n /** Controls the visual theme: 'light' or 'dark'. */\r\n @Input() theme: 'light' | 'dark' = 'light';\r\n\r\n @HostBinding('class.dark-theme') get isDarkMode() {\r\n return this.theme === 'dark';\r\n }\r\n\r\n /** Emits the newly selected date or date range. */\r\n @Output() valueChange = new EventEmitter<Date | { start: Date; end: Date }>();\r\n\r\n private _minDate: Date | null = null;\r\n\r\n /** The earliest selectable date. */\r\n @Input() set minDate(value: DateInput | null) {\r\n this._minDate = this._normalizeDate(value);\r\n }\r\n\r\n private _maxDate: Date | null = null;\r\n\r\n /** The latest selectable date. */\r\n @Input() set maxDate(value: DateInput | null) {\r\n this._maxDate = this._normalizeDate(value);\r\n }\r\n\r\n private _ranges: { [key: string]: [Date, Date] } | null = null;\r\n\r\n /** An object of predefined date ranges for quick selection. */\r\n @Input() set ranges(value: DateRange | null) {\r\n if (!value) {\r\n this._ranges = null;\r\n } else {\r\n this._ranges = Object.entries(value).reduce((acc, [key, dates]) => {\r\n const start = this._normalizeDate(dates[0]);\r\n const end = this._normalizeDate(dates[1]);\r\n if (start && end) acc[key] = [start, end];\r\n return acc;\r\n }, {} as { [key: string]: [Date, Date] });\r\n }\r\n this.updateRangesArray();\r\n }\r\n\r\n public currentDate: Date = new Date();\r\n public daysInMonth: (Date | null)[] = [];\r\n public weekDays: string[] = [];\r\n public readonly today: Date = new Date();\r\n public selectedDate: Date | null = null;\r\n public startDate: Date | null = null;\r\n public endDate: Date | null = null;\r\n public hoveredDate: Date | null = null;\r\n public rangesArray: { key: string; value: [Date, Date] }[] = [];\r\n private _currentMonth!: number;\r\n private _currentYear!: number;\r\n public monthOptions: { label: string; value: number }[] = [];\r\n public yearOptions: { label: string; value: number }[] = [];\r\n private firstDayOfWeek: number = 0;\r\n\r\n // Time selection state\r\n public currentHour: number = 0; // Internal 24h format (0-23)\r\n public currentMinute: number = 0;\r\n public currentDisplayHour: number = 12; // Display 12h format (1-12)\r\n public isPm: boolean = false; // Tracks AM/PM status\r\n\r\n public hourOptions: { label: string; value: number }[] = [];\r\n public minuteOptions: { label: string; value: number }[] = [];\r\n public ampmOptions: { label: string; value: boolean }[] = [\r\n { label: 'AM', value: false },\r\n { label: 'PM', value: true }\r\n ];\r\n\r\n\r\n constructor(@Inject(PLATFORM_ID) private readonly platformId: Object) {\r\n if (isPlatformBrowser(this.platformId)) {\r\n this._locale = navigator.language;\r\n }\r\n }\r\n\r\n get currentMonth(): number {\r\n return this._currentMonth;\r\n }\r\n\r\n set currentMonth(month: number) {\r\n if (this._currentMonth !== month) {\r\n this._currentMonth = month;\r\n this.currentDate.setMonth(month);\r\n this.generateCalendar();\r\n }\r\n }\r\n\r\n get currentYear(): number {\r\n return this._currentYear;\r\n }\r\n\r\n set currentYear(year: number) {\r\n if (this._currentYear !== year) {\r\n this._currentYear = year;\r\n this.currentDate.setFullYear(year);\r\n this.generateCalendar();\r\n }\r\n }\r\n\r\n ngOnInit(): void {\r\n this.today.setHours(0, 0, 0, 0);\r\n this.generateLocaleData();\r\n this.generateTimeOptions();\r\n\r\n // Set default time to current time if enabled and no initial value\r\n if (this.showTime && !this.value) {\r\n const now = new Date();\r\n\r\n this.currentHour = now.getHours();\r\n this.currentMinute = Math.floor(now.getMinutes() / this.minuteInterval) * this.minuteInterval;\r\n\r\n if (this.currentMinute === 60) {\r\n this.currentMinute = 0;\r\n this.currentHour = (this.currentHour + 1) % 24;\r\n }\r\n\r\n this.update12HourState(this.currentHour);\r\n }\r\n\r\n if (this.value) {\r\n this.initializeValue(this.value);\r\n }\r\n this.generateCalendar();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['locale']) {\r\n this.generateLocaleData();\r\n this.generateCalendar();\r\n }\r\n\r\n // Regenerate time options if the interval changes\r\n if (changes['minuteInterval']) {\r\n this.generateTimeOptions();\r\n // Recalculate and round current minute to the new interval\r\n this.currentMinute = Math.floor(this.currentMinute / this.minuteInterval) * this.minuteInterval;\r\n this.onTimeChange();\r\n }\r\n\r\n if (changes['value'] && changes['value'].currentValue !== changes['value'].previousValue) {\r\n this.initializeValue(changes['value'].currentValue);\r\n this.generateCalendar();\r\n }\r\n }\r\n\r\n /** Converts the displayed 12h time (currentDisplayHour + isPm) into the 24h internal time (currentHour). */\r\n private get24Hour(displayHour: number, isPm: boolean): number {\r\n if (isPm) {\r\n return displayHour === 12 ? 12 : displayHour + 12; // 12 PM is 12, 1-11 PM is 13-23\r\n } else {\r\n return displayHour === 12 ? 0 : displayHour; // 12 AM is 0 (midnight), 1-11 AM is 1-11\r\n }\r\n }\r\n\r\n /** Updates the display time variables (12h format and AM/PM state) from the 24h internal time. */\r\n private update12HourState(fullHour: number): void {\r\n this.isPm = fullHour >= 12;\r\n this.currentDisplayHour = fullHour % 12 || 12; // 0 (midnight) or 12 PM both become 12\r\n }\r\n\r\n /** Applies the currently selected hour and minute to a given date object. */\r\n private applyCurrentTime(date: Date): Date {\r\n // Convert 12h display state back to 24h format\r\n this.currentHour = this.get24Hour(this.currentDisplayHour, this.isPm);\r\n date.setHours(this.currentHour, this.currentMinute, 0, 0);\r\n return date;\r\n }\r\n\r\n /** Initializes selection state and time controls from the provided input value. */\r\n private initializeValue(value: Date | { start: Date, end: Date } | null): void {\r\n if (!value) {\r\n this.selectedDate = null;\r\n this.startDate = null;\r\n this.endDate = null;\r\n return;\r\n }\r\n\r\n let initialDate: Date | null = null;\r\n\r\n if (this.mode === 'single' && value instanceof Date) {\r\n this.selectedDate = this._normalizeDate(value);\r\n initialDate = this.selectedDate;\r\n\r\n } else if (this.mode === 'range' && typeof value === 'object' && 'start' in value && 'end' in value) {\r\n this.startDate = this._normalizeDate(value.start);\r\n this.endDate = this._normalizeDate(value.end);\r\n initialDate = this.startDate;\r\n }\r\n\r\n if (initialDate) {\r\n this.currentDate = new Date(initialDate);\r\n\r\n // Set time selectors based on 24h value from initial date\r\n this.currentHour = initialDate.getHours();\r\n this.currentMinute = initialDate.getMinutes();\r\n\r\n this.update12HourState(this.currentHour);\r\n\r\n // Round minute to nearest interval, in case the initial value time doesn't match the current interval\r\n this.currentMinute = Math.floor(this.currentMinute / this.minuteInterval) * this.minuteInterval;\r\n }\r\n }\r\n\r\n /** Normalizes a date input to a Date object, keeping time information. */\r\n private _normalizeDate(date: DateInput | null): Date | null {\r\n if (!date) return null;\r\n const d = (date instanceof Date) ? new Date(date.getTime()) : new Date(date as any);\r\n if (isNaN(d.getTime())) return null;\r\n return d;\r\n }\r\n\r\n /** Generates options for the hour and minute selectors based on the interval. */\r\n private generateTimeOptions(): void {\r\n // Hours are 1 through 12 for 12h format display\r\n this.hourOptions = Array.from({ length: 12 }).map((_, i) => ({\r\n label: (i + 1).toString().padStart(2, '0'),\r\n value: i + 1, // Values 1 through 12\r\n }));\r\n\r\n this.minuteOptions = [];\r\n for (let i = 0; i < 60; i += this.minuteInterval) {\r\n this.minuteOptions.push({\r\n label: i.toString().padStart(2, '0'),\r\n value: i,\r\n });\r\n }\r\n }\r\n\r\n /** Generates locale-dependent month and weekday names. */\r\n private generateLocaleData(): void {\r\n this.monthOptions = Array.from({length: 12}).map((_, i) => ({\r\n label: new Date(2024, i, 1).toLocaleDateString(this.locale, {month: 'long'}),\r\n value: i,\r\n }));\r\n try {\r\n this.firstDayOfWeek = ((new Intl.Locale(this.locale) as any).weekInfo?.firstDay || 0) % 7;\r\n } catch (e) {\r\n this.firstDayOfWeek = 0;\r\n }\r\n const day = new Date(2024, 0, 7 + this.firstDayOfWeek);\r\n this.weekDays = Array.from({length: 7}).map(() => {\r\n const weekDay = new Date(day).toLocaleDateString(this.locale, {weekday: 'short'});\r\n day.setDate(day.getDate() + 1);\r\n return weekDay;\r\n });\r\n }\r\n\r\n /** Populates the internal array of predefined ranges. */\r\n private updateRangesArray(): void {\r\n this.rangesArray = this._ranges ? Object.entries(this._ranges).map(([key, value]) => ({key, value})) : [];\r\n }\r\n\r\n /** Handles selection of a predefined date range. */\r\n public selectRange(range: [Date, Date]): void {\r\n this.startDate = this.applyCurrentTime(range[0]);\r\n this.endDate = this.applyCurrentTime(range[1]);\r\n\r\n if (this.startDate && this.endDate) {\r\n /** Type assertion is safe here as both dates are explicitly set */\r\n this.valueChange.emit({start: this.startDate as Date, end: this.endDate as Date});\r\n }\r\n\r\n this.currentDate = new Date(this.startDate);\r\n this.initializeValue({start: this.startDate, end: this.endDate}); // Update time selectors\r\n this.generateCalendar();\r\n }\r\n\r\n /** Checks if a specific date should be disabled based on minDate, maxDate, or custom function. */\r\n public isDateDisabled(date: Date | null): boolean {\r\n if (!date) return false;\r\n // Check against minDate/maxDate, ensuring we compare only the date part\r\n const dateOnly = new Date(date.getFullYear(), date.getMonth(), date.getDate());\r\n\r\n if (this._minDate) {\r\n const minDateOnly = new Date(this._minDate.getFullYear(), this._minDate.getMonth(), this._minDate.getDate());\r\n if (dateOnly < minDateOnly) return true;\r\n }\r\n if (this._maxDate) {\r\n const maxDateOnly = new Date(this._maxDate.getFullYear(), this._maxDate.getMonth(), this._maxDate.getDate());\r\n if (dateOnly > maxDateOnly) return true;\r\n }\r\n\r\n if (this.isInvalidDate(date)) return true;\r\n return false;\r\n }\r\n\r\n /** Updates the time component of the selected date(s) when hour/minute selectors change. */\r\n public onTimeChange(): void {\r\n if (this.mode === 'single' && this.selectedDate) {\r\n this.selectedDate = this.applyCurrentTime(this.selectedDate);\r\n this.valueChange.emit(this.selectedDate);\r\n\r\n } else if (this.mode === 'range' && this.startDate && this.endDate) {\r\n\r\n this.startDate = this.applyCurrentTime(this.startDate);\r\n this.endDate = this.applyCurrentTime(this.endDate);\r\n\r\n /** Type assertion is safe here as both dates are confirmed */\r\n this.valueChange.emit({start: this.startDate as Date, end: this.endDate as Date});\r\n\r\n } else if (this.mode === 'range' && this.startDate && !this.endDate) {\r\n // If range started but not completed, update time on the start date only (no emit)\r\n this.startDate = this.applyCurrentTime(this.startDate);\r\n }\r\n }\r\n\r\n /** Handles the click event on a calendar day cell. */\r\n public onDateClick(day: Date | null): void {\r\n if (!day || this.isDateDisabled(day)) return;\r\n\r\n if (this.mode === 'single') {\r\n this.selectedDate = this.applyCurrentTime(day);\r\n this.valueChange.emit(this.selectedDate);\r\n\r\n } else {\r\n // Range selection logic\r\n if (!this.startDate || (this.startDate && this.endDate)) {\r\n this.startDate = this.applyCurrentTime(day);\r\n this.endDate = null;\r\n } else if (day >= this.startDate) {\r\n this.endDate = this.applyCurrentTime(day);\r\n /** Type assertion is safe here as both dates are set when ending a range */\r\n this.valueChange.emit({start: this.startDate as Date, end: this.endDate as Date});\r\n } else {\r\n this.startDate = this.applyCurrentTime(day);\r\n this.endDate = null;\r\n }\r\n this.hoveredDate = null;\r\n }\r\n\r\n // Update time controls to reflect the time of the newly selected date\r\n if (this.mode === 'single' && this.selectedDate) {\r\n this.update12HourState(this.selectedDate.getHours());\r\n this.currentMinute = this.selectedDate.getMinutes();\r\n } else if (this.mode === 'range' && this.startDate) {\r\n this.update12HourState(this.startDate.getHours());\r\n this.currentMinute = this.startDate.getMinutes();\r\n }\r\n }\r\n\r\n /** Handles hover events for range preview when only the start date is selected. */\r\n public onDateHover(day: Date | null): void {\r\n if (this.mode === 'range' && this.startDate && !this.endDate && day) {\r\n this.hoveredDate = day;\r\n }\r\n }\r\n\r\n /** Checks if a date is within the range being previewed (during hover). */\r\n public isPreviewInRange(day: Date | null): boolean {\r\n if (this.mode !== 'range' || !this.startDate || this.endDate || !this.hoveredDate || !day) return false;\r\n const start = this.startDate.getTime();\r\n const end = this.hoveredDate.getTime();\r\n const time = day.getTime();\r\n return time > Math.min(start, end) && time < Math.max(start, end);\r\n }\r\n\r\n /** Generates the calendar grid for the currently active month. */\r\n public generateCalendar(): void {\r\n this.daysInMonth = [];\r\n const year = this.currentDate.getFullYear();\r\n const month = this.currentDate.getMonth();\r\n this._currentMonth = month;\r\n this._currentYear = year;\r\n this.generateDropdownOptions();\r\n const firstDayOfMonth = new Date(year, month, 1);\r\n const lastDayOfMonth = new Date(year, month + 1, 0);\r\n const startDayOfWeek = firstDayOfMonth.getDay();\r\n const emptyCellCount = (startDayOfWeek - this.firstDayOfWeek + 7) % 7;\r\n\r\n for (let i = 0; i < emptyCellCount; i++) {\r\n this.daysInMonth.push(null);\r\n }\r\n for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {\r\n this.daysInMonth.push(this._normalizeDate(new Date(year, month, i)));\r\n }\r\n }\r\n\r\n /** Generates month and year options for dropdowns. */\r\n private generateDropdownOptions(): void {\r\n const startYear = this._currentYear - 10;\r\n const endYear = this._currentYear + 10;\r\n this.yearOptions = [];\r\n for (let i = startYear; i <= endYear; i++) {\r\n this.yearOptions.push({label: `${i}`, value: i});\r\n }\r\n }\r\n\r\n /** Moves the calendar view forward or backward by one month. */\r\n public changeMonth(delta: number): void {\r\n this.currentDate.setMonth(this.currentDate.getMonth() + delta);\r\n this.generateCalendar();\r\n }\r\n\r\n /** Utility function to check if two dates represent the same day (ignoring time). */\r\n public isSameDay(d1: Date | null, d2: Date | null): boolean {\r\n if (!d1 || !d2) return false;\r\n return (\r\n d1.getFullYear() === d2.getFullYear() &&\r\n d1.getMonth() === d2.getMonth() &&\r\n d1.getDate() === d2.getDate()\r\n );\r\n }\r\n\r\n /** Checks if a date is strictly between the start and end of a selected range (ignoring time). */\r\n public isInRange(d: Date | null): boolean {\r\n if (!d || !this.startDate || !this.endDate) return false;\r\n\r\n // Use date-only comparison for highlighting the days\r\n const dTime = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();\r\n const startDayTime = new Date(this.startDate.getFullYear(), this.startDate.getMonth(), this.startDate.getDate()).getTime();\r\n const endDayTime = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate()).getTime();\r\n\r\n const startTime = Math.min(startDayTime, endDayTime);\r\n const endTime = Math.max(startDayTime, endDayTime);\r\n\r\n return dTime > startTime && dTime < endTime;\r\n }\r\n}\r\n","/*\r\n * Public API Surface of ngxsmk-datepicker\r\n */\r\n\r\nexport * from './lib/ngxsmk-datepicker';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngxsmk-datepicker.mjs","sources":["../../../projects/ngxsmk-datepicker/src/lib/ngxsmk-datepicker.ts","../../../projects/ngxsmk-datepicker/src/public-api.ts","../../../projects/ngxsmk-datepicker/src/ngxsmk-datepicker.ts"],"sourcesContent":["import {\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n HostBinding,\r\n HostListener,\r\n inject,\r\n Input,\r\n OnChanges,\r\n OnInit,\r\n Output,\r\n PLATFORM_ID,\r\n SimpleChanges,\r\n Inject,\r\n} from '@angular/core';\r\nimport {CommonModule, isPlatformBrowser} from '@angular/common';\r\nimport {FormsModule} from '@angular/forms';\r\n\r\n@Component({\r\n selector: 'app-custom-select',\r\n standalone: true,\r\n imports: [CommonModule],\r\n template: `\r\n <div class=\"ngxsmk-select-container\" (click)=\"toggleDropdown()\">\r\n <button type=\"button\" class=\"ngxsmk-select-display\">\r\n <span>{{ displayValue }}</span>\r\n <svg class=\"ngxsmk-arrow-icon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48\"\r\n d=\"M112 184l144 144 144-144\"/>\r\n </svg>\r\n </button>\r\n @if (isOpen) {\r\n <div class=\"ngxsmk-options-panel\">\r\n <ul>\r\n @for (option of options; track option.value) {\r\n <li [class.selected]=\"option.value === value\" (click)=\"selectOption(option); $event.stopPropagation()\">\r\n {{ option.label }}\r\n </li>\r\n }\r\n </ul>\r\n </div>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n position: relative;\r\n display: inline-block;\r\n }\r\n .ngxsmk-select-container { cursor: pointer; }\r\n .ngxsmk-select-display {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n width: var(--custom-select-width, 115px);\r\n background: var(--datepicker-background, #fff);\r\n border: 1px solid var(--datepicker-border-color, #ccc);\r\n color: var(--datepicker-text-color, #333);\r\n border-radius: 4px;\r\n padding: 4px 8px;\r\n font-size: 14px;\r\n text-align: left;\r\n height: 30px;\r\n }\r\n .ngxsmk-arrow-icon {\r\n width: 12px;\r\n height: 12px;\r\n margin-left: 8px;\r\n }\r\n .ngxsmk-options-panel {\r\n position: absolute;\r\n top: 110%;\r\n left: 0;\r\n width: 100%;\r\n background: var(--datepicker-background, #fff);\r\n border: 1px solid var(--datepicker-border-color, #ccc);\r\n color: var(--datepicker-text-color, #333);\r\n border-radius: 4px;\r\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\r\n max-height: 200px;\r\n overflow-y: auto;\r\n z-index: 9999;\r\n }\r\n .ngxsmk-options-panel ul {\r\n list-style: none;\r\n padding: 4px;\r\n margin: 0;\r\n }\r\n .ngxsmk-options-panel li {\r\n padding: 8px 12px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n }\r\n .ngxsmk-options-panel li:hover {\r\n background-color: var(--datepicker-hover-background, #f0f0f0);\r\n }\r\n .ngxsmk-options-panel li.selected {\r\n background-color: var(--datepicker-primary-color, #3880ff);\r\n color: var(--datepicker-primary-contrast, #fff);\r\n }\r\n `],\r\n})\r\nexport class CustomSelectComponent {\r\n @Input() options: { label: string; value: any }[] = [];\r\n @Input() value: any;\r\n @Output() valueChange = new EventEmitter<any>();\r\n public isOpen = false;\r\n\r\n private readonly elementRef: ElementRef = inject(ElementRef);\r\n\r\n @HostListener('document:click', ['$event'])\r\n onDocumentClick(event: MouseEvent): void {\r\n if (!this.elementRef.nativeElement.contains(event.target)) this.isOpen = false;\r\n }\r\n\r\n get displayValue(): string {\r\n const selectedOption = this.options.find((opt) => opt.value === this.value);\r\n return selectedOption ? selectedOption.label : '';\r\n }\r\n\r\n toggleDropdown(): void {\r\n this.isOpen = !this.isOpen;\r\n }\r\n\r\n selectOption(option: { label: string; value: any }): void {\r\n this.value = option.value;\r\n this.valueChange.emit(this.value);\r\n this.isOpen = false;\r\n }\r\n}\r\n\r\nexport type DateInput = Date | string | { toDate: () => Date; _isAMomentObject?: boolean; $d?: Date };\r\n\r\nexport interface DateRange {\r\n [key: string]: [DateInput, DateInput];\r\n}\r\n\r\n@Component({\r\n selector: 'ngxsmk-datepicker',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule, CustomSelectComponent],\r\n template: `\r\n <div class=\"ngxsmk-datepicker-container\">\r\n @if (showRanges && rangesArray.length > 0 && mode === 'range') {\r\n <div class=\"ngxsmk-ranges-container\">\r\n <ul>\r\n @for (range of rangesArray; track range.key) {\r\n <li (click)=\"selectRange(range.value)\">{{ range.key }}</li>\r\n }\r\n </ul>\r\n </div>\r\n }\r\n <div class=\"ngxsmk-calendar-container\">\r\n <div class=\"ngxsmk-header\">\r\n <div class=\"ngxsmk-month-year-selects\">\r\n <app-custom-select class=\"month-select\" [options]=\"monthOptions\"\r\n [(value)]=\"currentMonth\"></app-custom-select>\r\n <app-custom-select class=\"year-select\" [options]=\"yearOptions\" [(value)]=\"currentYear\"></app-custom-select>\r\n </div>\r\n <div class=\"ngxsmk-nav-buttons\">\r\n <button type=\"button\" class=\"ngxsmk-nav-button\" (click)=\"changeMonth(-1)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48\"\r\n d=\"M328 112L184 256l144 144\"/>\r\n </svg>\r\n </button>\r\n <button type=\"button\" class=\"ngxsmk-nav-button\" (click)=\"changeMonth(1)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48\"\r\n d=\"M184 112l144 144-144 144\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"ngxsmk-days-grid-wrapper\">\r\n <div class=\"ngxsmk-days-grid\">\r\n @for (day of weekDays; track day) {\r\n <div class=\"ngxsmk-day-name\">{{ day }}</div>\r\n }\r\n @for (day of daysInMonth; track $index) {\r\n <div class=\"ngxsmk-day-cell\"\r\n [class.empty]=\"!day\" [class.disabled]=\"isDateDisabled(day)\" [class.today]=\"isSameDay(day, today)\"\r\n [class.selected]=\"mode === 'single' && isSameDay(day, selectedDate)\"\r\n [class.start-date]=\"mode === 'range' && isSameDay(day, startDate)\"\r\n [class.end-date]=\"mode === 'range' && isSameDay(day, endDate)\"\r\n [class.in-range]=\"mode === 'range' && isInRange(day)\"\r\n [class.preview-range]=\"isPreviewInRange(day)\"\r\n (click)=\"onDateClick(day)\" (mouseenter)=\"onDateHover(day)\">\r\n @if (day) {\r\n <div class=\"ngxsmk-day-number\">{{ day | date : 'd' }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (showTime) {\r\n <div class=\"ngxsmk-time-selection\">\r\n <span class=\"ngxsmk-time-label\">Time:</span>\r\n <app-custom-select\r\n class=\"hour-select\"\r\n [options]=\"hourOptions\"\r\n [(value)]=\"currentDisplayHour\"\r\n (valueChange)=\"onTimeChange()\"\r\n ></app-custom-select>\r\n <span class=\"ngxsmk-time-separator\">:</span>\r\n <app-custom-select\r\n class=\"minute-select\"\r\n [options]=\"minuteOptions\"\r\n [(value)]=\"currentMinute\"\r\n (valueChange)=\"onTimeChange()\"\r\n ></app-custom-select>\r\n <app-custom-select\r\n class=\"ampm-select\"\r\n [options]=\"ampmOptions\"\r\n [(value)]=\"isPm\"\r\n (valueChange)=\"onTimeChange()\"\r\n ></app-custom-select>\r\n </div>\r\n }\r\n\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n :host {\r\n --datepicker-primary-color: #6d28d9;\r\n --datepicker-primary-contrast: #ffffff;\r\n --datepicker-range-background: #f5f3ff;\r\n --datepicker-background: #ffffff;\r\n --datepicker-text-color: #222428;\r\n --datepicker-subtle-text-color: #9ca3af;\r\n --datepicker-border-color: #e9e9e9;\r\n --datepicker-hover-background: #f0f0f0;\r\n }\r\n :host(.dark-theme) {\r\n --datepicker-range-background: rgba(139, 92, 246, 0.2);\r\n --datepicker-background: #1f2937;\r\n --datepicker-text-color: #d1d5db;\r\n --datepicker-subtle-text-color: #6b7280;\r\n --datepicker-border-color: #4b5563;\r\n --datepicker-hover-background: #374151;\r\n }\r\n .ngxsmk-datepicker-container { display: flex; }\r\n .ngxsmk-calendar-container {\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n border-radius: 10px;\r\n padding: 16px;\r\n background: var(--datepicker-background);\r\n }\r\n .ngxsmk-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n position: relative;\r\n z-index: 2;\r\n gap: 5px;\r\n }\r\n .ngxsmk-month-year-selects { display: flex; gap: 5px; }\r\n .ngxsmk-month-year-selects app-custom-select.month-select { --custom-select-width: 120px; }\r\n .ngxsmk-month-year-selects app-custom-select.year-select { --custom-select-width: 90px; }\r\n .ngxsmk-nav-buttons { display: flex; }\r\n .ngxsmk-nav-button {\r\n background: none;\r\n border: none;\r\n padding: 8px;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--datepicker-text-color);\r\n }\r\n .ngxsmk-nav-button:hover { background-color: var(--datepicker-hover-background); }\r\n .ngxsmk-nav-button svg { width: 18px; height: 18px; }\r\n .ngxsmk-days-grid-wrapper { position: relative; }\r\n .ngxsmk-days-grid {\r\n display: grid;\r\n grid-template-columns: repeat(7, 1fr);\r\n text-align: center;\r\n gap: 0;\r\n }\r\n .ngxsmk-day-name {\r\n font-weight: 600;\r\n font-size: 0.8rem;\r\n color: var(--datepicker-subtle-text-color);\r\n padding: 8px 0;\r\n }\r\n .ngxsmk-day-cell {\r\n position: relative;\r\n height: 38px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n cursor: pointer;\r\n border-radius: 0;\r\n }\r\n .ngxsmk-day-number {\r\n width: 36px;\r\n height: 36px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n border-radius: 50%;\r\n color: var(--datepicker-text-color);\r\n position: relative;\r\n z-index: 1;\r\n }\r\n .ngxsmk-day-cell:not(.disabled):hover .ngxsmk-day-number {\r\n background-color: var(--datepicker-hover-background);\r\n color: var(--datepicker-primary-color);\r\n }\r\n .ngxsmk-day-cell.start-date .ngxsmk-day-number,\r\n .ngxsmk-day-cell.end-date .ngxsmk-day-number,\r\n .ngxsmk-day-cell.selected .ngxsmk-day-number {\r\n background-color: var(--datepicker-primary-color);\r\n color: var(--datepicker-primary-contrast);\r\n }\r\n .ngxsmk-day-cell.in-range,\r\n .ngxsmk-day-cell.start-date,\r\n .ngxsmk-day-cell.end-date,\r\n .ngxsmk-day-cell.preview-range {\r\n background-color: var(--datepicker-range-background);\r\n }\r\n .ngxsmk-day-cell.start-date {\r\n border-top-left-radius: 100%;\r\n border-bottom-left-radius: 100%;\r\n }\r\n .ngxsmk-day-cell.end-date {\r\n border-top-right-radius: 100%;\r\n border-bottom-right-radius: 100%;\r\n }\r\n .ngxsmk-day-cell.start-date.end-date { border-radius: 50px; }\r\n .ngxsmk-day-cell.disabled {\r\n background-color: transparent !important;\r\n color: #4b5563;\r\n cursor: not-allowed;\r\n pointer-events: none;\r\n opacity: 0.5;\r\n }\r\n .ngxsmk-day-cell.today .ngxsmk-day-number { border: 1px solid var(--datepicker-primary-color); }\r\n .ngxsmk-ranges-container {\r\n width: 180px;\r\n padding: 16px;\r\n border-right: 1px solid var(--datepicker-border-color);\r\n background: var(--datepicker-background);\r\n }\r\n .ngxsmk-ranges-container ul {\r\n list-style: none;\r\n padding: 0;\r\n margin: 0;\r\n }\r\n .ngxsmk-ranges-container li {\r\n padding: 10px;\r\n margin-bottom: 8px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n color: var(--datepicker-text-color);\r\n }\r\n .ngxsmk-ranges-container li:hover { background-color: var(--datepicker-hover-background); }\r\n .ngxsmk-time-selection {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n margin-top: 16px;\r\n padding-top: 12px;\r\n border-top: 1px solid var(--datepicker-border-color);\r\n }\r\n .ngxsmk-time-label {\r\n font-size: 0.9rem;\r\n color: var(--datepicker-subtle-text-color);\r\n margin-right: 4px;\r\n }\r\n .ngxsmk-time-selection app-custom-select {\r\n --custom-select-width: 60px;\r\n height: 30px;\r\n }\r\n .ngxsmk-time-selection app-custom-select.ampm-select { --custom-select-width: 70px; }\r\n .ngxsmk-time-separator {\r\n font-weight: 600;\r\n font-size: 1.1rem;\r\n color: var(--datepicker-text-color);\r\n }\r\n `],\r\n})\r\nexport class NgxsmkDatepickerComponent implements OnInit, OnChanges {\r\n public readonly platformId: Object;\r\n\r\n @Input() mode: 'single' | 'range' = 'single';\r\n @Input() isInvalidDate: (date: Date) => boolean = () => false;\r\n @Input() showRanges: boolean = true;\r\n @Input() showTime: boolean = false;\r\n @Input() minuteInterval: number = 1;\r\n\r\n @Input() value: Date | { start: Date, end: Date } | null = null;\r\n\r\n private _locale: string = 'en-US';\r\n\r\n @Input() set locale(value: string) { this._locale = value; }\r\n get locale(): string { return this._locale; }\r\n\r\n @Input() theme: 'light' | 'dark' = 'light';\r\n @HostBinding('class.dark-theme') get isDarkMode() { return this.theme === 'dark'; }\r\n\r\n @Output() valueChange = new EventEmitter<Date | { start: Date; end: Date }>();\r\n\r\n private _minDate: Date | null = null;\r\n @Input() set minDate(value: DateInput | null) { this._minDate = this._normalizeDate(value); }\r\n\r\n private _maxDate: Date | null = null;\r\n @Input() set maxDate(value: DateInput | null) { this._maxDate = this._normalizeDate(value); }\r\n\r\n private _ranges: { [key: string]: [Date, Date] } | null = null;\r\n @Input() set ranges(value: DateRange | null) {\r\n if (!value) {\r\n this._ranges = null;\r\n } else {\r\n this._ranges = Object.entries(value).reduce((acc, [key, dates]) => {\r\n const start = this._normalizeDate(dates[0]);\r\n const end = this._normalizeDate(dates[1]);\r\n if (start && end) acc[key] = [start, end];\r\n return acc;\r\n }, {} as { [key: string]: [Date, Date] });\r\n }\r\n this.updateRangesArray();\r\n }\r\n\r\n public currentDate: Date = new Date();\r\n public daysInMonth: (Date | null)[] = [];\r\n public weekDays: string[] = [];\r\n public readonly today: Date = new Date();\r\n public selectedDate: Date | null = null;\r\n public startDate: Date | null = null;\r\n public endDate: Date | null = null;\r\n public hoveredDate: Date | null = null;\r\n public rangesArray: { key: string; value: [Date, Date] }[] = [];\r\n private _currentMonth!: number;\r\n private _currentYear!: number;\r\n public monthOptions: { label: string; value: number }[] = [];\r\n public yearOptions: { label: string; value: number }[] = [];\r\n private firstDayOfWeek: number = 0;\r\n\r\n public currentHour: number = 0;\r\n public currentMinute: number = 0;\r\n public currentDisplayHour: number = 12;\r\n public isPm: boolean = false;\r\n\r\n public hourOptions: { label: string; value: number }[] = [];\r\n public minuteOptions: { label: string; value: number }[] = [];\r\n public ampmOptions: { label: string; value: boolean }[] = [\r\n {label: 'AM', value: false},\r\n {label: 'PM', value: true}\r\n ];\r\n\r\n constructor(@Inject(PLATFORM_ID) platformId: Object) {\r\n this.platformId = platformId;\r\n }\r\n\r\n get currentMonth(): number { return this._currentMonth; }\r\n\r\n set currentMonth(month: number) {\r\n if (this._currentMonth !== month) {\r\n this._currentMonth = month;\r\n this.currentDate.setMonth(month);\r\n this.generateCalendar();\r\n }\r\n }\r\n\r\n get currentYear(): number { return this._currentYear; }\r\n\r\n set currentYear(year: number) {\r\n if (this._currentYear !== year) {\r\n this._currentYear = year;\r\n this.currentDate.setFullYear(year);\r\n this.generateCalendar();\r\n }\r\n }\r\n\r\n ngOnInit(): void {\r\n if (isPlatformBrowser(this.platformId)) {\r\n if (this._locale === 'en-US') {\r\n this._locale = navigator.language;\r\n }\r\n }\r\n\r\n this.today.setHours(0, 0, 0, 0);\r\n this.generateLocaleData();\r\n this.generateTimeOptions();\r\n\r\n if (this.showTime && !this.value) {\r\n const now = new Date();\r\n this.currentHour = now.getHours();\r\n this.currentMinute = Math.floor(now.getMinutes() / this.minuteInterval) * this.minuteInterval;\r\n\r\n if (this.currentMinute === 60) {\r\n this.currentMinute = 0;\r\n this.currentHour = (this.currentHour + 1) % 24;\r\n }\r\n this.update12HourState(this.currentHour);\r\n }\r\n\r\n if (this.value) {\r\n this.initializeValue(this.value);\r\n }\r\n this.generateCalendar();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['locale']) {\r\n this.generateLocaleData();\r\n this.generateCalendar();\r\n }\r\n\r\n if (changes['minuteInterval']) {\r\n this.generateTimeOptions();\r\n this.currentMinute = Math.floor(this.currentMinute / this.minuteInterval) * this.minuteInterval;\r\n this.onTimeChange();\r\n }\r\n\r\n if (changes['value'] && changes['value'].currentValue !== changes['value'].previousValue) {\r\n this.initializeValue(changes['value'].currentValue);\r\n this.generateCalendar();\r\n }\r\n }\r\n\r\n private get24Hour(displayHour: number, isPm: boolean): number {\r\n if (isPm) { return displayHour === 12 ? 12 : displayHour + 12; }\r\n return displayHour === 12 ? 0 : displayHour;\r\n }\r\n\r\n private update12HourState(fullHour: number): void {\r\n this.isPm = fullHour >= 12;\r\n this.currentDisplayHour = fullHour % 12 || 12;\r\n }\r\n\r\n private applyCurrentTime(date: Date): Date {\r\n this.currentHour = this.get24Hour(this.currentDisplayHour, this.isPm);\r\n date.setHours(this.currentHour, this.currentMinute, 0, 0);\r\n return date;\r\n }\r\n\r\n private initializeValue(value: Date | { start: Date, end: Date } | null): void {\r\n if (!value) {\r\n this.selectedDate = null;\r\n this.startDate = null;\r\n this.endDate = null;\r\n return;\r\n }\r\n\r\n let initialDate: Date | null = null;\r\n if (this.mode === 'single' && value instanceof Date) {\r\n this.selectedDate = this._normalizeDate(value);\r\n initialDate = this.selectedDate;\r\n } else if (this.mode === 'range' && typeof value === 'object' && 'start' in value && 'end' in value) {\r\n this.startDate = this._normalizeDate(value.start);\r\n this.endDate = this._normalizeDate(value.end);\r\n initialDate = this.startDate;\r\n }\r\n\r\n if (initialDate) {\r\n this.currentDate = new Date(initialDate);\r\n this.currentHour = initialDate.getHours();\r\n this.currentMinute = initialDate.getMinutes();\r\n this.update12HourState(this.currentHour);\r\n this.currentMinute = Math.floor(this.currentMinute / this.minuteInterval) * this.minuteInterval;\r\n }\r\n }\r\n\r\n private _normalizeDate(date: DateInput | null): Date | null {\r\n if (!date) return null;\r\n const d = (date instanceof Date) ? new Date(date.getTime()) : new Date(date as any);\r\n if (isNaN(d.getTime())) return null;\r\n return d;\r\n }\r\n\r\n private generateTimeOptions(): void {\r\n this.hourOptions = Array.from({length: 12}).map((_, i) => ({\r\n label: (i + 1).toString().padStart(2, '0'),\r\n value: i + 1,\r\n }));\r\n\r\n this.minuteOptions = [];\r\n for (let i = 0; i < 60; i += this.minuteInterval) {\r\n this.minuteOptions.push({\r\n label: i.toString().padStart(2, '0'),\r\n value: i,\r\n });\r\n }\r\n }\r\n\r\n private generateLocaleData(): void {\r\n this.monthOptions = Array.from({length: 12}).map((_, i) => ({\r\n label: new Date(2024, i, 1).toLocaleDateString(this.locale, {month: 'long'}),\r\n value: i,\r\n }));\r\n\r\n this.firstDayOfWeek = 0;\r\n if (isPlatformBrowser(this.platformId)) {\r\n try {\r\n this.firstDayOfWeek = ((new Intl.Locale(this.locale) as any).weekInfo?.firstDay || 0) % 7;\r\n } catch (e) {\r\n this.firstDayOfWeek = 0;\r\n }\r\n }\r\n\r\n const day = new Date(2024, 0, 7 + this.firstDayOfWeek);\r\n this.weekDays = Array.from({length: 7}).map(() => {\r\n const weekDay = new Date(day).toLocaleDateString(this.locale, {weekday: 'short'});\r\n day.setDate(day.getDate() + 1);\r\n return weekDay;\r\n });\r\n }\r\n\r\n private updateRangesArray(): void {\r\n this.rangesArray = this._ranges ? Object.entries(this._ranges).map(([key, value]) => ({key, value})) : [];\r\n }\r\n\r\n public selectRange(range: [Date, Date]): void {\r\n this.startDate = this.applyCurrentTime(range[0]);\r\n this.endDate = this.applyCurrentTime(range[1]);\r\n\r\n if (this.startDate && this.endDate) {\r\n this.valueChange.emit({start: this.startDate as Date, end: this.endDate as Date});\r\n }\r\n\r\n this.currentDate = new Date(this.startDate);\r\n this.initializeValue({start: this.startDate, end: this.endDate});\r\n this.generateCalendar();\r\n }\r\n\r\n public isDateDisabled(date: Date | null): boolean {\r\n if (!date) return false;\r\n const dateOnly = new Date(date.getFullYear(), date.getMonth(), date.getDate());\r\n\r\n if (this._minDate) {\r\n const minDateOnly = new Date(this._minDate.getFullYear(), this._minDate.getMonth(), this._minDate.getDate());\r\n if (dateOnly < minDateOnly) return true;\r\n }\r\n if (this._maxDate) {\r\n const maxDateOnly = new Date(this._maxDate.getFullYear(), this._maxDate.getMonth(), this._maxDate.getDate());\r\n if (dateOnly > maxDateOnly) return true;\r\n }\r\n return this.isInvalidDate(date);\r\n }\r\n\r\n public onTimeChange(): void {\r\n if (this.mode === 'single' && this.selectedDate) {\r\n this.selectedDate = this.applyCurrentTime(this.selectedDate);\r\n this.valueChange.emit(this.selectedDate);\r\n } else if (this.mode === 'range' && this.startDate && this.endDate) {\r\n this.startDate = this.applyCurrentTime(this.startDate);\r\n this.endDate = this.applyCurrentTime(this.endDate);\r\n this.valueChange.emit({start: this.startDate as Date, end: this.endDate as Date});\r\n } else if (this.mode === 'range' && this.startDate && !this.endDate) {\r\n this.startDate = this.applyCurrentTime(this.startDate);\r\n }\r\n }\r\n\r\n public onDateClick(day: Date | null): void {\r\n if (!day || this.isDateDisabled(day)) return;\r\n\r\n if (this.mode === 'single') {\r\n this.selectedDate = this.applyCurrentTime(day);\r\n this.valueChange.emit(this.selectedDate);\r\n } else {\r\n if (!this.startDate || (this.startDate && this.endDate)) {\r\n this.startDate = this.applyCurrentTime(day);\r\n this.endDate = null;\r\n } else if (day >= this.startDate) {\r\n this.endDate = this.applyCurrentTime(day);\r\n this.valueChange.emit({start: this.startDate as Date, end: this.endDate as Date});\r\n } else {\r\n this.startDate = this.applyCurrentTime(day);\r\n this.endDate = null;\r\n }\r\n this.hoveredDate = null;\r\n }\r\n\r\n if (this.mode === 'single' && this.selectedDate) {\r\n this.update12HourState(this.selectedDate.getHours());\r\n this.currentMinute = this.selectedDate.getMinutes();\r\n } else if (this.mode === 'range' && this.startDate) {\r\n this.update12HourState(this.startDate.getHours());\r\n this.currentMinute = this.startDate.getMinutes();\r\n }\r\n }\r\n\r\n public onDateHover(day: Date | null): void {\r\n if (this.mode === 'range' && this.startDate && !this.endDate && day) {\r\n this.hoveredDate = day;\r\n }\r\n }\r\n\r\n public isPreviewInRange(day: Date | null): boolean {\r\n if (this.mode !== 'range' || !this.startDate || this.endDate || !this.hoveredDate || !day) return false;\r\n const start = this.startDate.getTime();\r\n const end = this.hoveredDate.getTime();\r\n const time = day.getTime();\r\n return time > Math.min(start, end) && time < Math.max(start, end);\r\n }\r\n\r\n public generateCalendar(): void {\r\n this.daysInMonth = [];\r\n const year = this.currentDate.getFullYear();\r\n const month = this.currentDate.getMonth();\r\n this._currentMonth = month;\r\n this._currentYear = year;\r\n this.generateDropdownOptions();\r\n const firstDayOfMonth = new Date(year, month, 1);\r\n const lastDayOfMonth = new Date(year, month + 1, 0);\r\n const startDayOfWeek = firstDayOfMonth.getDay();\r\n const emptyCellCount = (startDayOfWeek - this.firstDayOfWeek + 7) % 7;\r\n\r\n for (let i = 0; i < emptyCellCount; i++) {\r\n this.daysInMonth.push(null);\r\n }\r\n for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {\r\n this.daysInMonth.push(this._normalizeDate(new Date(year, month, i)));\r\n }\r\n }\r\n\r\n private generateDropdownOptions(): void {\r\n const startYear = this._currentYear - 10;\r\n const endYear = this._currentYear + 10;\r\n this.yearOptions = [];\r\n for (let i = startYear; i <= endYear; i++) {\r\n this.yearOptions.push({label: `${i}`, value: i});\r\n }\r\n }\r\n\r\n public changeMonth(delta: number): void {\r\n this.currentDate.setMonth(this.currentDate.getMonth() + delta);\r\n this.generateCalendar();\r\n }\r\n\r\n public isSameDay(d1: Date | null, d2: Date | null): boolean {\r\n if (!d1 || !d2) return false;\r\n return (\r\n d1.getFullYear() === d2.getFullYear() &&\r\n d1.getMonth() === d2.getMonth() &&\r\n d1.getDate() === d2.getDate()\r\n );\r\n }\r\n\r\n public isInRange(d: Date | null): boolean {\r\n if (!d || !this.startDate || !this.endDate) return false;\r\n\r\n const dTime = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();\r\n const startDayTime = new Date(this.startDate.getFullYear(), this.startDate.getMonth(), this.startDate.getDate()).getTime();\r\n const endDayTime = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate()).getTime();\r\n\r\n const startTime = Math.min(startDayTime, endDayTime);\r\n const endTime = Math.max(startDayTime, endDayTime);\r\n\r\n return dTime > startTime && dTime < endTime;\r\n }\r\n}\r\n","/*\r\n * Public API Surface of ngxsmk-datepicker\r\n */\r\n\r\nexport * from './lib/ngxsmk-datepicker';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter,
|
|
2
|
+
import { EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';
|
|
3
3
|
|
|
4
4
|
declare class CustomSelectComponent {
|
|
5
|
-
private readonly elementRef;
|
|
6
|
-
/** The list of available options to display in the dropdown. */
|
|
7
5
|
options: {
|
|
8
6
|
label: string;
|
|
9
7
|
value: any;
|
|
10
8
|
}[];
|
|
11
|
-
/** The currently selected value. */
|
|
12
9
|
value: any;
|
|
13
|
-
/** Emits the new value when an option is selected. */
|
|
14
10
|
valueChange: EventEmitter<any>;
|
|
15
11
|
isOpen: boolean;
|
|
16
|
-
|
|
17
|
-
/** Closes the dropdown when a click occurs outside the component boundary. */
|
|
12
|
+
private readonly elementRef;
|
|
18
13
|
onDocumentClick(event: MouseEvent): void;
|
|
19
|
-
/** Gets the display label for the currently selected value. */
|
|
20
14
|
get displayValue(): string;
|
|
21
|
-
/** Toggles the visibility of the dropdown panel. */
|
|
22
15
|
toggleDropdown(): void;
|
|
23
|
-
/** Handles the selection of a new option. */
|
|
24
16
|
selectOption(option: {
|
|
25
17
|
label: string;
|
|
26
18
|
value: any;
|
|
@@ -37,42 +29,30 @@ interface DateRange {
|
|
|
37
29
|
[key: string]: [DateInput, DateInput];
|
|
38
30
|
}
|
|
39
31
|
declare class NgxsmkDatepickerComponent implements OnInit, OnChanges {
|
|
40
|
-
|
|
41
|
-
/** Sets the selection mode: 'single' date or 'range' selection. */
|
|
32
|
+
readonly platformId: Object;
|
|
42
33
|
mode: 'single' | 'range';
|
|
43
|
-
/** A function to programmatically disable specific dates. Returns true if the date should be disabled. */
|
|
44
34
|
isInvalidDate: (date: Date) => boolean;
|
|
45
|
-
/** If true, displays the predefined ranges panel when in 'range' mode. */
|
|
46
35
|
showRanges: boolean;
|
|
47
|
-
/** If true, displays the time selection controls (hour/minute). */
|
|
48
36
|
showTime: boolean;
|
|
49
|
-
/** Sets the minute selection step/interval (e.g., 5, 15, 30). */
|
|
50
37
|
minuteInterval: number;
|
|
51
|
-
/** The initial selected date or date range. Accepts Date, or { start: Date, end: Date }. */
|
|
52
38
|
value: Date | {
|
|
53
39
|
start: Date;
|
|
54
40
|
end: Date;
|
|
55
41
|
} | null;
|
|
56
42
|
private _locale;
|
|
57
|
-
/** Sets the locale for language and regional formatting (e.g., 'en-US', 'de-DE'). */
|
|
58
43
|
set locale(value: string);
|
|
59
44
|
get locale(): string;
|
|
60
|
-
/** Controls the visual theme: 'light' or 'dark'. */
|
|
61
45
|
theme: 'light' | 'dark';
|
|
62
46
|
get isDarkMode(): boolean;
|
|
63
|
-
/** Emits the newly selected date or date range. */
|
|
64
47
|
valueChange: EventEmitter<Date | {
|
|
65
48
|
start: Date;
|
|
66
49
|
end: Date;
|
|
67
50
|
}>;
|
|
68
51
|
private _minDate;
|
|
69
|
-
/** The earliest selectable date. */
|
|
70
52
|
set minDate(value: DateInput | null);
|
|
71
53
|
private _maxDate;
|
|
72
|
-
/** The latest selectable date. */
|
|
73
54
|
set maxDate(value: DateInput | null);
|
|
74
55
|
private _ranges;
|
|
75
|
-
/** An object of predefined date ranges for quick selection. */
|
|
76
56
|
set ranges(value: DateRange | null);
|
|
77
57
|
currentDate: Date;
|
|
78
58
|
daysInMonth: (Date | null)[];
|
|
@@ -120,43 +100,24 @@ declare class NgxsmkDatepickerComponent implements OnInit, OnChanges {
|
|
|
120
100
|
set currentYear(year: number);
|
|
121
101
|
ngOnInit(): void;
|
|
122
102
|
ngOnChanges(changes: SimpleChanges): void;
|
|
123
|
-
/** Converts the displayed 12h time (currentDisplayHour + isPm) into the 24h internal time (currentHour). */
|
|
124
103
|
private get24Hour;
|
|
125
|
-
/** Updates the display time variables (12h format and AM/PM state) from the 24h internal time. */
|
|
126
104
|
private update12HourState;
|
|
127
|
-
/** Applies the currently selected hour and minute to a given date object. */
|
|
128
105
|
private applyCurrentTime;
|
|
129
|
-
/** Initializes selection state and time controls from the provided input value. */
|
|
130
106
|
private initializeValue;
|
|
131
|
-
/** Normalizes a date input to a Date object, keeping time information. */
|
|
132
107
|
private _normalizeDate;
|
|
133
|
-
/** Generates options for the hour and minute selectors based on the interval. */
|
|
134
108
|
private generateTimeOptions;
|
|
135
|
-
/** Generates locale-dependent month and weekday names. */
|
|
136
109
|
private generateLocaleData;
|
|
137
|
-
/** Populates the internal array of predefined ranges. */
|
|
138
110
|
private updateRangesArray;
|
|
139
|
-
/** Handles selection of a predefined date range. */
|
|
140
111
|
selectRange(range: [Date, Date]): void;
|
|
141
|
-
/** Checks if a specific date should be disabled based on minDate, maxDate, or custom function. */
|
|
142
112
|
isDateDisabled(date: Date | null): boolean;
|
|
143
|
-
/** Updates the time component of the selected date(s) when hour/minute selectors change. */
|
|
144
113
|
onTimeChange(): void;
|
|
145
|
-
/** Handles the click event on a calendar day cell. */
|
|
146
114
|
onDateClick(day: Date | null): void;
|
|
147
|
-
/** Handles hover events for range preview when only the start date is selected. */
|
|
148
115
|
onDateHover(day: Date | null): void;
|
|
149
|
-
/** Checks if a date is within the range being previewed (during hover). */
|
|
150
116
|
isPreviewInRange(day: Date | null): boolean;
|
|
151
|
-
/** Generates the calendar grid for the currently active month. */
|
|
152
117
|
generateCalendar(): void;
|
|
153
|
-
/** Generates month and year options for dropdowns. */
|
|
154
118
|
private generateDropdownOptions;
|
|
155
|
-
/** Moves the calendar view forward or backward by one month. */
|
|
156
119
|
changeMonth(delta: number): void;
|
|
157
|
-
/** Utility function to check if two dates represent the same day (ignoring time). */
|
|
158
120
|
isSameDay(d1: Date | null, d2: Date | null): boolean;
|
|
159
|
-
/** Checks if a date is strictly between the start and end of a selected range (ignoring time). */
|
|
160
121
|
isInRange(d: Date | null): boolean;
|
|
161
122
|
static ɵfac: i0.ɵɵFactoryDeclaration<NgxsmkDatepickerComponent, never>;
|
|
162
123
|
static ɵcmp: i0.ɵɵComponentDeclaration<NgxsmkDatepickerComponent, "ngxsmk-datepicker", never, { "mode": { "alias": "mode"; "required": false; }; "isInvalidDate": { "alias": "isInvalidDate"; "required": false; }; "showRanges": { "alias": "showRanges"; "required": false; }; "showTime": { "alias": "showTime"; "required": false; }; "minuteInterval": { "alias": "minuteInterval"; "required": false; }; "value": { "alias": "value"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "minDate": { "alias": "minDate"; "required": false; }; "maxDate": { "alias": "maxDate"; "required": false; }; "ranges": { "alias": "ranges"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
|