ngxsmk-datepicker 1.1.9 → 1.2.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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, EventEmitter, HostListener, Output, Input, Component, PLATFORM_ID, HostBinding } from '@angular/core';
2
+ import { EventEmitter, 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';
@@ -7,54 +7,36 @@ import { FormsModule } from '@angular/forms';
7
7
  // #####################################################################
8
8
  // ## Reusable Custom Select Component
9
9
  // #####################################################################
10
- /**
11
- * @title Custom Select Component
12
- * @description A standalone component implementing a custom styled dropdown selector.
13
- * It handles options display, value tracking, and document click-away logic for closing.
14
- *
15
- * @selector app-custom-select
16
- * @export
17
- */
18
10
  class CustomSelectComponent {
19
- constructor() {
20
- /** The ElementRef injected via `inject()` for DOM manipulation and click detection. */
21
- this.elementRef = inject(ElementRef);
11
+ constructor(elementRef) {
12
+ this.elementRef = elementRef;
22
13
  /** The list of available options to display in the dropdown. */
23
14
  this.options = [];
24
15
  /** Emits the new value when an option is selected. */
25
16
  this.valueChange = new EventEmitter();
26
17
  this.isOpen = false;
27
18
  }
28
- /**
29
- * Closes the dropdown when a click event occurs outside the component's native element.
30
- * @param event The mouse event triggered on the document.
31
- */
19
+ /** Closes the dropdown when a click occurs outside the component boundary. */
32
20
  onDocumentClick(event) {
33
21
  if (!this.elementRef.nativeElement.contains(event.target))
34
22
  this.isOpen = false;
35
23
  }
36
- /**
37
- * Retrieves the display label corresponding to the currently selected value.
38
- * @returns The label string or an empty string if no option is selected.
39
- */
24
+ /** Gets the display label for the currently selected value. */
40
25
  get displayValue() {
41
26
  const selectedOption = this.options.find((opt) => opt.value === this.value);
42
27
  return selectedOption ? selectedOption.label : '';
43
28
  }
44
- /** Toggles the visibility state of the options dropdown panel. */
29
+ /** Toggles the visibility of the dropdown panel. */
45
30
  toggleDropdown() {
46
31
  this.isOpen = !this.isOpen;
47
32
  }
48
- /**
49
- * Handles the selection of a new option, updating the value and closing the dropdown.
50
- * @param option The selected option object containing label and value.
51
- */
33
+ /** Handles the selection of a new option. */
52
34
  selectOption(option) {
53
35
  this.value = option.value;
54
36
  this.valueChange.emit(this.value);
55
37
  this.isOpen = false;
56
38
  }
57
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: CustomSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
39
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: CustomSelectComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
58
40
  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: `
59
41
  <div class="ngxsmk-select-container" (click)="toggleDropdown()">
60
42
  <button type="button" class="ngxsmk-select-display">
@@ -102,7 +84,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
102
84
  }
103
85
  </div>
104
86
  `, 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"] }]
105
- }], ctorParameters: () => [], propDecorators: { options: [{
87
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { options: [{
106
88
  type: Input
107
89
  }], value: [{
108
90
  type: Input
@@ -112,15 +94,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
112
94
  type: HostListener,
113
95
  args: ['document:click', ['$event']]
114
96
  }] } });
115
- /**
116
- * @title Ngxsmk Datepicker Component
117
- * @description A fully featured, standalone datepicker component supporting single date selection,
118
- * date range selection, time selection, custom date ranges, and theme toggling.
119
- *
120
- * @selector ngxsmk-datepicker
121
- * @implements OnInit, OnChanges
122
- * @export
123
- */
124
97
  class NgxsmkDatepickerComponent {
125
98
  /** Sets the locale for language and regional formatting (e.g., 'en-US', 'de-DE'). */
126
99
  set locale(value) {
@@ -129,7 +102,6 @@ class NgxsmkDatepickerComponent {
129
102
  get locale() {
130
103
  return this._locale;
131
104
  }
132
- /** Binds the dark-theme class to the host element when theme is 'dark'. */
133
105
  get isDarkMode() {
134
106
  return this.theme === 'dark';
135
107
  }
@@ -157,9 +129,8 @@ class NgxsmkDatepickerComponent {
157
129
  }
158
130
  this.updateRangesArray();
159
131
  }
160
- constructor() {
161
- /** Platform ID injected via `inject()` for Server-Side Rendering (SSR) checks. */
162
- this.platformId = inject(PLATFORM_ID);
132
+ constructor(platformId) {
133
+ this.platformId = platformId;
163
134
  /** Sets the selection mode: 'single' date or 'range' selection. */
164
135
  this.mode = 'single';
165
136
  /** A function to programmatically disable specific dates. Returns true if the date should be disabled. */
@@ -203,12 +174,13 @@ class NgxsmkDatepickerComponent {
203
174
  { label: 'AM', value: false },
204
175
  { label: 'PM', value: true }
205
176
  ];
177
+ if (isPlatformBrowser(this.platformId)) {
178
+ this._locale = navigator.language;
179
+ }
206
180
  }
207
- /** Retrieves the currently displayed calendar month index. */
208
181
  get currentMonth() {
209
182
  return this._currentMonth;
210
183
  }
211
- /** Sets the month index and regenerates the calendar grid. */
212
184
  set currentMonth(month) {
213
185
  if (this._currentMonth !== month) {
214
186
  this._currentMonth = month;
@@ -216,11 +188,9 @@ class NgxsmkDatepickerComponent {
216
188
  this.generateCalendar();
217
189
  }
218
190
  }
219
- /** Retrieves the currently displayed calendar year. */
220
191
  get currentYear() {
221
192
  return this._currentYear;
222
193
  }
223
- /** Sets the year and regenerates the calendar grid. */
224
194
  set currentYear(year) {
225
195
  if (this._currentYear !== year) {
226
196
  this._currentYear = year;
@@ -228,11 +198,7 @@ class NgxsmkDatepickerComponent {
228
198
  this.generateCalendar();
229
199
  }
230
200
  }
231
- /** Initializes the component, performs platform checks, and sets up date/time states. */
232
201
  ngOnInit() {
233
- if (isPlatformBrowser(this.platformId)) {
234
- this._locale = navigator.language;
235
- }
236
202
  this.today.setHours(0, 0, 0, 0);
237
203
  this.generateLocaleData();
238
204
  this.generateTimeOptions();
@@ -252,14 +218,15 @@ class NgxsmkDatepickerComponent {
252
218
  }
253
219
  this.generateCalendar();
254
220
  }
255
- /** Handles input changes, particularly for `locale`, `minuteInterval`, and `value`. */
256
221
  ngOnChanges(changes) {
257
222
  if (changes['locale']) {
258
223
  this.generateLocaleData();
259
224
  this.generateCalendar();
260
225
  }
226
+ // Regenerate time options if the interval changes
261
227
  if (changes['minuteInterval']) {
262
228
  this.generateTimeOptions();
229
+ // Recalculate and round current minute to the new interval
263
230
  this.currentMinute = Math.floor(this.currentMinute / this.minuteInterval) * this.minuteInterval;
264
231
  this.onTimeChange();
265
232
  }
@@ -268,42 +235,28 @@ class NgxsmkDatepickerComponent {
268
235
  this.generateCalendar();
269
236
  }
270
237
  }
271
- /**
272
- * Converts the displayed 12-hour time (displayHour + isPm) into the 24-hour internal time.
273
- * @param displayHour The 12-hour display hour (1-12).
274
- * @param isPm Whether the time is PM (true) or AM (false).
275
- * @returns The 24-hour time (0-23).
276
- */
238
+ /** Converts the displayed 12h time (currentDisplayHour + isPm) into the 24h internal time (currentHour). */
277
239
  get24Hour(displayHour, isPm) {
278
240
  if (isPm) {
279
- return displayHour === 12 ? 12 : displayHour + 12;
241
+ return displayHour === 12 ? 12 : displayHour + 12; // 12 PM is 12, 1-11 PM is 13-23
280
242
  }
281
243
  else {
282
- return displayHour === 12 ? 0 : displayHour;
244
+ return displayHour === 12 ? 0 : displayHour; // 12 AM is 0 (midnight), 1-11 AM is 1-11
283
245
  }
284
246
  }
285
- /**
286
- * Updates the display time variables (12h format and AM/PM state) from the 24h internal time.
287
- * @param fullHour The 24-hour time (0-23).
288
- */
247
+ /** Updates the display time variables (12h format and AM/PM state) from the 24h internal time. */
289
248
  update12HourState(fullHour) {
290
249
  this.isPm = fullHour >= 12;
291
- this.currentDisplayHour = fullHour % 12 || 12;
250
+ this.currentDisplayHour = fullHour % 12 || 12; // 0 (midnight) or 12 PM both become 12
292
251
  }
293
- /**
294
- * Applies the currently selected hour and minute to a given date object.
295
- * @param date The date object to modify.
296
- * @returns The modified date object.
297
- */
252
+ /** Applies the currently selected hour and minute to a given date object. */
298
253
  applyCurrentTime(date) {
254
+ // Convert 12h display state back to 24h format
299
255
  this.currentHour = this.get24Hour(this.currentDisplayHour, this.isPm);
300
256
  date.setHours(this.currentHour, this.currentMinute, 0, 0);
301
257
  return date;
302
258
  }
303
- /**
304
- * Initializes selection state and time controls from the provided input value.
305
- * @param value The input date or date range.
306
- */
259
+ /** Initializes selection state and time controls from the provided input value. */
307
260
  initializeValue(value) {
308
261
  if (!value) {
309
262
  this.selectedDate = null;
@@ -323,17 +276,15 @@ class NgxsmkDatepickerComponent {
323
276
  }
324
277
  if (initialDate) {
325
278
  this.currentDate = new Date(initialDate);
279
+ // Set time selectors based on 24h value from initial date
326
280
  this.currentHour = initialDate.getHours();
327
281
  this.currentMinute = initialDate.getMinutes();
328
282
  this.update12HourState(this.currentHour);
283
+ // Round minute to nearest interval, in case the initial value time doesn't match the current interval
329
284
  this.currentMinute = Math.floor(this.currentMinute / this.minuteInterval) * this.minuteInterval;
330
285
  }
331
286
  }
332
- /**
333
- * Normalizes a date input to a Date object, handling various types.
334
- * @param date The input date type.
335
- * @returns A valid Date object or null.
336
- */
287
+ /** Normalizes a date input to a Date object, keeping time information. */
337
288
  _normalizeDate(date) {
338
289
  if (!date)
339
290
  return null;
@@ -344,9 +295,10 @@ class NgxsmkDatepickerComponent {
344
295
  }
345
296
  /** Generates options for the hour and minute selectors based on the interval. */
346
297
  generateTimeOptions() {
298
+ // Hours are 1 through 12 for 12h format display
347
299
  this.hourOptions = Array.from({ length: 12 }).map((_, i) => ({
348
300
  label: (i + 1).toString().padStart(2, '0'),
349
- value: i + 1,
301
+ value: i + 1, // Values 1 through 12
350
302
  }));
351
303
  this.minuteOptions = [];
352
304
  for (let i = 0; i < 60; i += this.minuteInterval) {
@@ -356,22 +308,16 @@ class NgxsmkDatepickerComponent {
356
308
  });
357
309
  }
358
310
  }
359
- /** Generates locale-dependent month and weekday names for display. */
311
+ /** Generates locale-dependent month and weekday names. */
360
312
  generateLocaleData() {
361
313
  this.monthOptions = Array.from({ length: 12 }).map((_, i) => ({
362
314
  label: new Date(2024, i, 1).toLocaleDateString(this.locale, { month: 'long' }),
363
315
  value: i,
364
316
  }));
365
- // ⭐ FIX: Guarding Intl.Locale access with isPlatformBrowser to prevent SSR crash.
366
- if (isPlatformBrowser(this.platformId)) {
367
- try {
368
- this.firstDayOfWeek = (new Intl.Locale(this.locale).weekInfo?.firstDay || 0) % 7;
369
- }
370
- catch (e) {
371
- this.firstDayOfWeek = 0;
372
- }
317
+ try {
318
+ this.firstDayOfWeek = (new Intl.Locale(this.locale).weekInfo?.firstDay || 0) % 7;
373
319
  }
374
- else {
320
+ catch (e) {
375
321
  this.firstDayOfWeek = 0;
376
322
  }
377
323
  const day = new Date(2024, 0, 7 + this.firstDayOfWeek);
@@ -381,32 +327,27 @@ class NgxsmkDatepickerComponent {
381
327
  return weekDay;
382
328
  });
383
329
  }
384
- /** Populates the internal array of predefined ranges from the input object. */
330
+ /** Populates the internal array of predefined ranges. */
385
331
  updateRangesArray() {
386
332
  this.rangesArray = this._ranges ? Object.entries(this._ranges).map(([key, value]) => ({ key, value })) : [];
387
333
  }
388
- /**
389
- * Handles selection of a predefined date range, updates the view, and emits the new range.
390
- * @param range The selected date range [start, end].
391
- */
334
+ /** Handles selection of a predefined date range. */
392
335
  selectRange(range) {
393
336
  this.startDate = this.applyCurrentTime(range[0]);
394
337
  this.endDate = this.applyCurrentTime(range[1]);
395
338
  if (this.startDate && this.endDate) {
339
+ /** Type assertion is safe here as both dates are explicitly set */
396
340
  this.valueChange.emit({ start: this.startDate, end: this.endDate });
397
341
  }
398
342
  this.currentDate = new Date(this.startDate);
399
- this.initializeValue({ start: this.startDate, end: this.endDate });
343
+ this.initializeValue({ start: this.startDate, end: this.endDate }); // Update time selectors
400
344
  this.generateCalendar();
401
345
  }
402
- /**
403
- * Checks if a specific date should be disabled based on minDate, maxDate, or custom function.
404
- * @param date The date to check.
405
- * @returns True if the date is disabled, false otherwise.
406
- */
346
+ /** Checks if a specific date should be disabled based on minDate, maxDate, or custom function. */
407
347
  isDateDisabled(date) {
408
348
  if (!date)
409
349
  return false;
350
+ // Check against minDate/maxDate, ensuring we compare only the date part
410
351
  const dateOnly = new Date(date.getFullYear(), date.getMonth(), date.getDate());
411
352
  if (this._minDate) {
412
353
  const minDateOnly = new Date(this._minDate.getFullYear(), this._minDate.getMonth(), this._minDate.getDate());
@@ -422,7 +363,7 @@ class NgxsmkDatepickerComponent {
422
363
  return true;
423
364
  return false;
424
365
  }
425
- /** Updates the time component of the selected date(s) when hour/minute selectors change and emits the new value. */
366
+ /** Updates the time component of the selected date(s) when hour/minute selectors change. */
426
367
  onTimeChange() {
427
368
  if (this.mode === 'single' && this.selectedDate) {
428
369
  this.selectedDate = this.applyCurrentTime(this.selectedDate);
@@ -431,16 +372,15 @@ class NgxsmkDatepickerComponent {
431
372
  else if (this.mode === 'range' && this.startDate && this.endDate) {
432
373
  this.startDate = this.applyCurrentTime(this.startDate);
433
374
  this.endDate = this.applyCurrentTime(this.endDate);
375
+ /** Type assertion is safe here as both dates are confirmed */
434
376
  this.valueChange.emit({ start: this.startDate, end: this.endDate });
435
377
  }
436
378
  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)
437
380
  this.startDate = this.applyCurrentTime(this.startDate);
438
381
  }
439
382
  }
440
- /**
441
- * Handles the click event on a calendar day cell to manage single or range selection.
442
- * @param day The date clicked.
443
- */
383
+ /** Handles the click event on a calendar day cell. */
444
384
  onDateClick(day) {
445
385
  if (!day || this.isDateDisabled(day))
446
386
  return;
@@ -449,12 +389,14 @@ class NgxsmkDatepickerComponent {
449
389
  this.valueChange.emit(this.selectedDate);
450
390
  }
451
391
  else {
392
+ // Range selection logic
452
393
  if (!this.startDate || (this.startDate && this.endDate)) {
453
394
  this.startDate = this.applyCurrentTime(day);
454
395
  this.endDate = null;
455
396
  }
456
397
  else if (day >= this.startDate) {
457
398
  this.endDate = this.applyCurrentTime(day);
399
+ /** Type assertion is safe here as both dates are set when ending a range */
458
400
  this.valueChange.emit({ start: this.startDate, end: this.endDate });
459
401
  }
460
402
  else {
@@ -464,26 +406,22 @@ class NgxsmkDatepickerComponent {
464
406
  this.hoveredDate = null;
465
407
  }
466
408
  // Update time controls to reflect the time of the newly selected date
467
- const selectedTimeRef = this.mode === 'single' ? this.selectedDate : this.startDate;
468
- if (selectedTimeRef) {
469
- this.update12HourState(selectedTimeRef.getHours());
470
- this.currentMinute = selectedTimeRef.getMinutes();
409
+ if (this.mode === 'single' && this.selectedDate) {
410
+ this.update12HourState(this.selectedDate.getHours());
411
+ this.currentMinute = this.selectedDate.getMinutes();
412
+ }
413
+ else if (this.mode === 'range' && this.startDate) {
414
+ this.update12HourState(this.startDate.getHours());
415
+ this.currentMinute = this.startDate.getMinutes();
471
416
  }
472
417
  }
473
- /**
474
- * Updates the hovered date for range preview during selection.
475
- * @param day The date being hovered over.
476
- */
418
+ /** Handles hover events for range preview when only the start date is selected. */
477
419
  onDateHover(day) {
478
420
  if (this.mode === 'range' && this.startDate && !this.endDate && day) {
479
421
  this.hoveredDate = day;
480
422
  }
481
423
  }
482
- /**
483
- * Checks if a date is within the range being previewed (during hover).
484
- * @param day The date to check.
485
- * @returns True if the date is in the preview range.
486
- */
424
+ /** Checks if a date is within the range being previewed (during hover). */
487
425
  isPreviewInRange(day) {
488
426
  if (this.mode !== 'range' || !this.startDate || this.endDate || !this.hoveredDate || !day)
489
427
  return false;
@@ -492,7 +430,7 @@ class NgxsmkDatepickerComponent {
492
430
  const time = day.getTime();
493
431
  return time > Math.min(start, end) && time < Math.max(start, end);
494
432
  }
495
- /** Generates the calendar grid (days and empty cells) for the currently active month. */
433
+ /** Generates the calendar grid for the currently active month. */
496
434
  generateCalendar() {
497
435
  this.daysInMonth = [];
498
436
  const year = this.currentDate.getFullYear();
@@ -511,7 +449,7 @@ class NgxsmkDatepickerComponent {
511
449
  this.daysInMonth.push(this._normalizeDate(new Date(year, month, i)));
512
450
  }
513
451
  }
514
- /** Generates month and year options for the dropdown selectors. */
452
+ /** Generates month and year options for dropdowns. */
515
453
  generateDropdownOptions() {
516
454
  const startYear = this._currentYear - 10;
517
455
  const endYear = this._currentYear + 10;
@@ -520,20 +458,12 @@ class NgxsmkDatepickerComponent {
520
458
  this.yearOptions.push({ label: `${i}`, value: i });
521
459
  }
522
460
  }
523
- /**
524
- * Moves the calendar view forward or backward by one month.
525
- * @param delta -1 for previous month, 1 for next month.
526
- */
461
+ /** Moves the calendar view forward or backward by one month. */
527
462
  changeMonth(delta) {
528
463
  this.currentDate.setMonth(this.currentDate.getMonth() + delta);
529
464
  this.generateCalendar();
530
465
  }
531
- /**
532
- * Utility function to check if two dates represent the same day (ignoring time).
533
- * @param d1 The first date.
534
- * @param d2 The second date.
535
- * @returns True if they are the same day.
536
- */
466
+ /** Utility function to check if two dates represent the same day (ignoring time). */
537
467
  isSameDay(d1, d2) {
538
468
  if (!d1 || !d2)
539
469
  return false;
@@ -541,14 +471,11 @@ class NgxsmkDatepickerComponent {
541
471
  d1.getMonth() === d2.getMonth() &&
542
472
  d1.getDate() === d2.getDate());
543
473
  }
544
- /**
545
- * Checks if a date is strictly between the start and end of a selected range (ignoring time).
546
- * @param d The date to check.
547
- * @returns True if the date is in the selected range.
548
- */
474
+ /** Checks if a date is strictly between the start and end of a selected range (ignoring time). */
549
475
  isInRange(d) {
550
476
  if (!d || !this.startDate || !this.endDate)
551
477
  return false;
478
+ // Use date-only comparison for highlighting the days
552
479
  const dTime = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
553
480
  const startDayTime = new Date(this.startDate.getFullYear(), this.startDate.getMonth(), this.startDate.getDate()).getTime();
554
481
  const endDayTime = new Date(this.endDate.getFullYear(), this.endDate.getMonth(), this.endDate.getDate()).getTime();
@@ -556,7 +483,7 @@ class NgxsmkDatepickerComponent {
556
483
  const endTime = Math.max(startDayTime, endDayTime);
557
484
  return dTime > startTime && dTime < endTime;
558
485
  }
559
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: NgxsmkDatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
486
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: NgxsmkDatepickerComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component }); }
560
487
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: NgxsmkDatepickerComponent, isStandalone: true, selector: "ngxsmk-datepicker", inputs: { mode: "mode", isInvalidDate: "isInvalidDate", showRanges: "showRanges", showTime: "showTime", minuteInterval: "minuteInterval", value: "value", locale: "locale", theme: "theme", minDate: "minDate", maxDate: "maxDate", ranges: "ranges" }, outputs: { valueChange: "valueChange" }, host: { properties: { "class.dark-theme": "this.isDarkMode" } }, usesOnChanges: true, ngImport: i0, template: `
561
488
  <div class="ngxsmk-datepicker-container">
562
489
  @if (showRanges && rangesArray.length > 0 && mode === 'range') {
@@ -639,7 +566,7 @@ class NgxsmkDatepickerComponent {
639
566
 
640
567
  </div>
641
568
  </div>
642
- `, isInline: true, styles: [":host{--datepicker-primary-color: #6d28d9;--datepicker-primary-contrast: #ffffff;--datepicker-range-background: #f5f3ff;--datepicker-background: #ffffff;--datepicker-text-color: #222428;--datepicker-subtle-text-color: #9ca3af;--datepicker-border-color: #e9e9e9;--datepicker-hover-background: #f0f0f0}:host(.dark-theme){--datepicker-range-background: rgba(139, 92, 246, .2);--datepicker-background: #1f2937;--datepicker-text-color: #d1d5db;--datepicker-subtle-text-color: #6b7280;--datepicker-border-color: #4b5563;--datepicker-hover-background: #374151}.ngxsmk-datepicker-container{display:flex}.ngxsmk-calendar-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;border-radius:10px;padding:16px;background:var(--datepicker-background)}.ngxsmk-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;position:relative;z-index:2;gap:5px}.ngxsmk-month-year-selects{display:flex;gap:5px}.ngxsmk-month-year-selects app-custom-select.month-select{--custom-select-width: 120px}.ngxsmk-month-year-selects app-custom-select.year-select{--custom-select-width: 90px}.ngxsmk-nav-buttons{display:flex}.ngxsmk-nav-button{background:none;border:none;padding:8px;cursor:pointer;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:var(--datepicker-text-color)}.ngxsmk-nav-button:hover{background-color:var(--datepicker-hover-background)}.ngxsmk-nav-button svg{width:18px;height:18px}.ngxsmk-days-grid-wrapper{position:relative}.ngxsmk-days-grid{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;gap:0}.ngxsmk-day-name{font-weight:600;font-size:.8rem;color:var(--datepicker-subtle-text-color);padding:8px 0}.ngxsmk-day-cell{position:relative;height:38px;display:flex;justify-content:center;align-items:center;cursor:pointer;border-radius:0}.ngxsmk-day-number{width:36px;height:36px;display:flex;justify-content:center;align-items:center;border-radius:50%;color:var(--datepicker-text-color);position:relative;z-index:1}.ngxsmk-day-cell:not(.disabled):hover .ngxsmk-day-number{background-color:var(--datepicker-hover-background);color:var(--datepicker-primary-color)}.ngxsmk-day-cell.in-range,.ngxsmk-day-cell.start-date,.ngxsmk-day-cell.end-date,.ngxsmk-day-cell.preview-range{background-color:var(--datepicker-range-background)}.ngxsmk-day-cell.start-date{border-top-left-radius:100%;border-bottom-left-radius:100%}.ngxsmk-day-cell.end-date{border-top-right-radius:100%;border-bottom-right-radius:100%}.ngxsmk-day-cell.start-date.end-date{border-radius:50px}.ngxsmk-day-cell.disabled{background-color:transparent!important;color:#4b5563;cursor:not-allowed;pointer-events:none;opacity:.5}.ngxsmk-day-cell.today .ngxsmk-day-number{border:1px solid var(--datepicker-primary-color)}.ngxsmk-ranges-container{width:180px;padding:16px;border-right:1px solid var(--datepicker-border-color);background:var(--datepicker-background)}.ngxsmk-ranges-container ul{list-style:none;padding:0;margin:0}.ngxsmk-ranges-container li{padding:10px;margin-bottom:8px;border-radius:6px;cursor:pointer;color:var(--datepicker-text-color)}.ngxsmk-ranges-container li:hover{background-color:var(--datepicker-hover-background)}.ngxsmk-time-selection{display:flex;align-items:center;justify-content:center;gap:4px;margin-top:16px;padding-top:12px;border-top:1px solid var(--datepicker-border-color)}.ngxsmk-time-label{font-size:.9rem;color:var(--datepicker-subtle-text-color);margin-right:4px}.ngxsmk-time-selection app-custom-select{--custom-select-width: 60px;height:30px}.ngxsmk-time-selection app-custom-select.ampm-select{--custom-select-width: 70px}.ngxsmk-time-separator{font-weight:600;font-size:1.1rem;color:var(--datepicker-text-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CustomSelectComponent, selector: "app-custom-select", inputs: ["options", "value"], outputs: ["valueChange"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] }); }
569
+ `, isInline: true, styles: [":host{--datepicker-primary-color: #6d28d9;--datepicker-primary-contrast: #ffffff;--datepicker-range-background: #f5f3ff;--datepicker-background: #ffffff;--datepicker-text-color: #222428;--datepicker-subtle-text-color: #9ca3af;--datepicker-border-color: #e9e9e9;--datepicker-hover-background: #f0f0f0}:host(.dark-theme){--datepicker-range-background: rgba(139, 92, 246, .2);--datepicker-background: #1f2937;--datepicker-text-color: #d1d5db;--datepicker-subtle-text-color: #6b7280;--datepicker-border-color: #4b5563;--datepicker-hover-background: #374151}.ngxsmk-datepicker-container{display:flex}.ngxsmk-calendar-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;border-radius:10px;padding:16px;background:var(--datepicker-background)}.ngxsmk-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;position:relative;z-index:2;gap:5px}.ngxsmk-month-year-selects{display:flex;gap:5px}.ngxsmk-month-year-selects app-custom-select.month-select{--custom-select-width: 120px}.ngxsmk-month-year-selects app-custom-select.year-select{--custom-select-width: 90px}.ngxsmk-nav-buttons{display:flex}.ngxsmk-nav-button{background:none;border:none;padding:8px;cursor:pointer;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:var(--datepicker-text-color)}.ngxsmk-nav-button:hover{background-color:var(--datepicker-hover-background)}.ngxsmk-nav-button svg{width:18px;height:18px}.ngxsmk-days-grid-wrapper{position:relative}.ngxsmk-days-grid{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;gap:0}.ngxsmk-day-name{font-weight:600;font-size:.8rem;color:var(--datepicker-subtle-text-color);padding:8px 0}.ngxsmk-day-cell{position:relative;height:38px;display:flex;justify-content:center;align-items:center;cursor:pointer;border-radius:0}.ngxsmk-day-number{width:36px;height:36px;display:flex;justify-content:center;align-items:center;border-radius:50%;color:var(--datepicker-text-color);position:relative;z-index:1}.ngxsmk-day-cell:not(.disabled):hover .ngxsmk-day-number{background-color:var(--datepicker-hover-background);color:var(--datepicker-primary-color)}.ngxsmk-day-cell.start-date .ngxsmk-day-number,.ngxsmk-day-cell.end-date .ngxsmk-day-number,.ngxsmk-day-cell.selected .ngxsmk-day-number{background-color:var(--datepicker-primary-color);color:var(--datepicker-primary-contrast)}.ngxsmk-day-cell.in-range,.ngxsmk-day-cell.start-date,.ngxsmk-day-cell.end-date,.ngxsmk-day-cell.preview-range{background-color:var(--datepicker-range-background)}.ngxsmk-day-cell.start-date{border-top-left-radius:100%;border-bottom-left-radius:100%}.ngxsmk-day-cell.end-date{border-top-right-radius:100%;border-bottom-right-radius:100%}.ngxsmk-day-cell.start-date.end-date{border-radius:50px}.ngxsmk-day-cell.disabled{background-color:transparent!important;color:#4b5563;cursor:not-allowed;pointer-events:none;opacity:.5}.ngxsmk-day-cell.today .ngxsmk-day-number{border:1px solid var(--datepicker-primary-color)}.ngxsmk-ranges-container{width:180px;padding:16px;border-right:1px solid var(--datepicker-border-color);background:var(--datepicker-background)}.ngxsmk-ranges-container ul{list-style:none;padding:0;margin:0}.ngxsmk-ranges-container li{padding:10px;margin-bottom:8px;border-radius:6px;cursor:pointer;color:var(--datepicker-text-color)}.ngxsmk-ranges-container li:hover{background-color:var(--datepicker-hover-background)}.ngxsmk-time-selection{display:flex;align-items:center;justify-content:center;gap:4px;margin-top:16px;padding-top:12px;border-top:1px solid var(--datepicker-border-color)}.ngxsmk-time-label{font-size:.9rem;color:var(--datepicker-subtle-text-color);margin-right:4px}.ngxsmk-time-selection app-custom-select{--custom-select-width: 60px;height:30px}.ngxsmk-time-selection app-custom-select.ampm-select{--custom-select-width: 70px}.ngxsmk-time-separator{font-weight:600;font-size:1.1rem;color:var(--datepicker-text-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CustomSelectComponent, selector: "app-custom-select", inputs: ["options", "value"], outputs: ["valueChange"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] }); }
643
570
  }
644
571
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: NgxsmkDatepickerComponent, decorators: [{
645
572
  type: Component,
@@ -725,8 +652,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
725
652
 
726
653
  </div>
727
654
  </div>
728
- `, styles: [":host{--datepicker-primary-color: #6d28d9;--datepicker-primary-contrast: #ffffff;--datepicker-range-background: #f5f3ff;--datepicker-background: #ffffff;--datepicker-text-color: #222428;--datepicker-subtle-text-color: #9ca3af;--datepicker-border-color: #e9e9e9;--datepicker-hover-background: #f0f0f0}:host(.dark-theme){--datepicker-range-background: rgba(139, 92, 246, .2);--datepicker-background: #1f2937;--datepicker-text-color: #d1d5db;--datepicker-subtle-text-color: #6b7280;--datepicker-border-color: #4b5563;--datepicker-hover-background: #374151}.ngxsmk-datepicker-container{display:flex}.ngxsmk-calendar-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;border-radius:10px;padding:16px;background:var(--datepicker-background)}.ngxsmk-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;position:relative;z-index:2;gap:5px}.ngxsmk-month-year-selects{display:flex;gap:5px}.ngxsmk-month-year-selects app-custom-select.month-select{--custom-select-width: 120px}.ngxsmk-month-year-selects app-custom-select.year-select{--custom-select-width: 90px}.ngxsmk-nav-buttons{display:flex}.ngxsmk-nav-button{background:none;border:none;padding:8px;cursor:pointer;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:var(--datepicker-text-color)}.ngxsmk-nav-button:hover{background-color:var(--datepicker-hover-background)}.ngxsmk-nav-button svg{width:18px;height:18px}.ngxsmk-days-grid-wrapper{position:relative}.ngxsmk-days-grid{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;gap:0}.ngxsmk-day-name{font-weight:600;font-size:.8rem;color:var(--datepicker-subtle-text-color);padding:8px 0}.ngxsmk-day-cell{position:relative;height:38px;display:flex;justify-content:center;align-items:center;cursor:pointer;border-radius:0}.ngxsmk-day-number{width:36px;height:36px;display:flex;justify-content:center;align-items:center;border-radius:50%;color:var(--datepicker-text-color);position:relative;z-index:1}.ngxsmk-day-cell:not(.disabled):hover .ngxsmk-day-number{background-color:var(--datepicker-hover-background);color:var(--datepicker-primary-color)}.ngxsmk-day-cell.in-range,.ngxsmk-day-cell.start-date,.ngxsmk-day-cell.end-date,.ngxsmk-day-cell.preview-range{background-color:var(--datepicker-range-background)}.ngxsmk-day-cell.start-date{border-top-left-radius:100%;border-bottom-left-radius:100%}.ngxsmk-day-cell.end-date{border-top-right-radius:100%;border-bottom-right-radius:100%}.ngxsmk-day-cell.start-date.end-date{border-radius:50px}.ngxsmk-day-cell.disabled{background-color:transparent!important;color:#4b5563;cursor:not-allowed;pointer-events:none;opacity:.5}.ngxsmk-day-cell.today .ngxsmk-day-number{border:1px solid var(--datepicker-primary-color)}.ngxsmk-ranges-container{width:180px;padding:16px;border-right:1px solid var(--datepicker-border-color);background:var(--datepicker-background)}.ngxsmk-ranges-container ul{list-style:none;padding:0;margin:0}.ngxsmk-ranges-container li{padding:10px;margin-bottom:8px;border-radius:6px;cursor:pointer;color:var(--datepicker-text-color)}.ngxsmk-ranges-container li:hover{background-color:var(--datepicker-hover-background)}.ngxsmk-time-selection{display:flex;align-items:center;justify-content:center;gap:4px;margin-top:16px;padding-top:12px;border-top:1px solid var(--datepicker-border-color)}.ngxsmk-time-label{font-size:.9rem;color:var(--datepicker-subtle-text-color);margin-right:4px}.ngxsmk-time-selection app-custom-select{--custom-select-width: 60px;height:30px}.ngxsmk-time-selection app-custom-select.ampm-select{--custom-select-width: 70px}.ngxsmk-time-separator{font-weight:600;font-size:1.1rem;color:var(--datepicker-text-color)}\n"] }]
729
- }], ctorParameters: () => [], propDecorators: { mode: [{
655
+ `, styles: [":host{--datepicker-primary-color: #6d28d9;--datepicker-primary-contrast: #ffffff;--datepicker-range-background: #f5f3ff;--datepicker-background: #ffffff;--datepicker-text-color: #222428;--datepicker-subtle-text-color: #9ca3af;--datepicker-border-color: #e9e9e9;--datepicker-hover-background: #f0f0f0}:host(.dark-theme){--datepicker-range-background: rgba(139, 92, 246, .2);--datepicker-background: #1f2937;--datepicker-text-color: #d1d5db;--datepicker-subtle-text-color: #6b7280;--datepicker-border-color: #4b5563;--datepicker-hover-background: #374151}.ngxsmk-datepicker-container{display:flex}.ngxsmk-calendar-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;border-radius:10px;padding:16px;background:var(--datepicker-background)}.ngxsmk-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;position:relative;z-index:2;gap:5px}.ngxsmk-month-year-selects{display:flex;gap:5px}.ngxsmk-month-year-selects app-custom-select.month-select{--custom-select-width: 120px}.ngxsmk-month-year-selects app-custom-select.year-select{--custom-select-width: 90px}.ngxsmk-nav-buttons{display:flex}.ngxsmk-nav-button{background:none;border:none;padding:8px;cursor:pointer;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:var(--datepicker-text-color)}.ngxsmk-nav-button:hover{background-color:var(--datepicker-hover-background)}.ngxsmk-nav-button svg{width:18px;height:18px}.ngxsmk-days-grid-wrapper{position:relative}.ngxsmk-days-grid{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;gap:0}.ngxsmk-day-name{font-weight:600;font-size:.8rem;color:var(--datepicker-subtle-text-color);padding:8px 0}.ngxsmk-day-cell{position:relative;height:38px;display:flex;justify-content:center;align-items:center;cursor:pointer;border-radius:0}.ngxsmk-day-number{width:36px;height:36px;display:flex;justify-content:center;align-items:center;border-radius:50%;color:var(--datepicker-text-color);position:relative;z-index:1}.ngxsmk-day-cell:not(.disabled):hover .ngxsmk-day-number{background-color:var(--datepicker-hover-background);color:var(--datepicker-primary-color)}.ngxsmk-day-cell.start-date .ngxsmk-day-number,.ngxsmk-day-cell.end-date .ngxsmk-day-number,.ngxsmk-day-cell.selected .ngxsmk-day-number{background-color:var(--datepicker-primary-color);color:var(--datepicker-primary-contrast)}.ngxsmk-day-cell.in-range,.ngxsmk-day-cell.start-date,.ngxsmk-day-cell.end-date,.ngxsmk-day-cell.preview-range{background-color:var(--datepicker-range-background)}.ngxsmk-day-cell.start-date{border-top-left-radius:100%;border-bottom-left-radius:100%}.ngxsmk-day-cell.end-date{border-top-right-radius:100%;border-bottom-right-radius:100%}.ngxsmk-day-cell.start-date.end-date{border-radius:50px}.ngxsmk-day-cell.disabled{background-color:transparent!important;color:#4b5563;cursor:not-allowed;pointer-events:none;opacity:.5}.ngxsmk-day-cell.today .ngxsmk-day-number{border:1px solid var(--datepicker-primary-color)}.ngxsmk-ranges-container{width:180px;padding:16px;border-right:1px solid var(--datepicker-border-color);background:var(--datepicker-background)}.ngxsmk-ranges-container ul{list-style:none;padding:0;margin:0}.ngxsmk-ranges-container li{padding:10px;margin-bottom:8px;border-radius:6px;cursor:pointer;color:var(--datepicker-text-color)}.ngxsmk-ranges-container li:hover{background-color:var(--datepicker-hover-background)}.ngxsmk-time-selection{display:flex;align-items:center;justify-content:center;gap:4px;margin-top:16px;padding-top:12px;border-top:1px solid var(--datepicker-border-color)}.ngxsmk-time-label{font-size:.9rem;color:var(--datepicker-subtle-text-color);margin-right:4px}.ngxsmk-time-selection app-custom-select{--custom-select-width: 60px;height:30px}.ngxsmk-time-selection app-custom-select.ampm-select{--custom-select-width: 70px}.ngxsmk-time-separator{font-weight:600;font-size:1.1rem;color:var(--datepicker-text-color)}\n"] }]
656
+ }], ctorParameters: () => [{ type: Object, decorators: [{
657
+ type: Inject,
658
+ args: [PLATFORM_ID]
659
+ }] }], propDecorators: { mode: [{
730
660
  type: Input
731
661
  }], isInvalidDate: [{
732
662
  type: Input
@@ -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 Input,\r\n OnChanges,\r\n OnInit,\r\n Output,\r\n SimpleChanges,\r\n PLATFORM_ID,\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// #####################################################################\r\n// ## Reusable Custom Select Component\r\n// #####################################################################\r\n/**\r\n * @title Custom Select Component\r\n * @description A standalone component implementing a custom styled dropdown selector.\r\n * It handles options display, value tracking, and document click-away logic for closing.\r\n *\r\n * @selector app-custom-select\r\n * @export\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%;\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\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 ElementRef injected via `inject()` for DOM manipulation and click detection. */\r\n private readonly elementRef: ElementRef = inject(ElementRef);\r\n\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() {}\r\n\r\n /**\r\n * Closes the dropdown when a click event occurs outside the component's native element.\r\n * @param event The mouse event triggered on the document.\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 /**\r\n * Retrieves the display label corresponding to the currently selected value.\r\n * @returns The label string or an empty string if no option is selected.\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 /** Toggles the visibility state of the options dropdown panel. */\r\n toggleDropdown(): void {\r\n this.isOpen = !this.isOpen;\r\n }\r\n\r\n /**\r\n * Handles the selection of a new option, updating the value and closing the dropdown.\r\n * @param option The selected option object containing label and value.\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\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/**\r\n * @title Ngxsmk Datepicker Component\r\n * @description A fully featured, standalone datepicker component supporting single date selection,\r\n * date range selection, time selection, custom date ranges, and theme toggling.\r\n *\r\n * @selector ngxsmk-datepicker\r\n * @implements OnInit, OnChanges\r\n * @export\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 /* --- 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\r\n /** Platform ID injected via `inject()` for Server-Side Rendering (SSR) checks. */\r\n private readonly platformId = inject(PLATFORM_ID);\r\n\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 /** Binds the dark-theme class to the host element when theme is 'dark'. */\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 constructor() {}\r\n\r\n /** Retrieves the currently displayed calendar month index. */\r\n get currentMonth(): number {\r\n return this._currentMonth;\r\n }\r\n\r\n /** Sets the month index and regenerates the calendar grid. */\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 /** Retrieves the currently displayed calendar year. */\r\n get currentYear(): number {\r\n return this._currentYear;\r\n }\r\n\r\n /** Sets the year and regenerates the calendar grid. */\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 /** Initializes the component, performs platform checks, and sets up date/time states. */\r\n ngOnInit(): void {\r\n if (isPlatformBrowser(this.platformId)) {\r\n this._locale = navigator.language;\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 // 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 /** Handles input changes, particularly for `locale`, `minuteInterval`, and `value`. */\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 /**\r\n * Converts the displayed 12-hour time (displayHour + isPm) into the 24-hour internal time.\r\n * @param displayHour The 12-hour display hour (1-12).\r\n * @param isPm Whether the time is PM (true) or AM (false).\r\n * @returns The 24-hour time (0-23).\r\n */\r\n private get24Hour(displayHour: number, isPm: boolean): number {\r\n if (isPm) {\r\n return displayHour === 12 ? 12 : displayHour + 12;\r\n } else {\r\n return displayHour === 12 ? 0 : displayHour;\r\n }\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 * @param fullHour The 24-hour time (0-23).\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 /**\r\n * Applies the currently selected hour and minute to a given date object.\r\n * @param date The date object to modify.\r\n * @returns The modified date object.\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 /**\r\n * Initializes selection state and time controls from the provided input value.\r\n * @param value The input date or date range.\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\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 this.currentHour = initialDate.getHours();\r\n this.currentMinute = initialDate.getMinutes();\r\n\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 /**\r\n * Normalizes a date input to a Date object, handling various types.\r\n * @param date The input date type.\r\n * @returns A valid Date object or null.\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 /** Generates options for the hour and minute selectors based on the interval. */\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 /** Generates locale-dependent month and weekday names for display. */\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 // ⭐ FIX: Guarding Intl.Locale access with isPlatformBrowser to prevent SSR crash.\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 } else {\r\n this.firstDayOfWeek = 0;\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 /** Populates the internal array of predefined ranges from the input object. */\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 /**\r\n * Handles selection of a predefined date range, updates the view, and emits the new range.\r\n * @param range The selected date range [start, end].\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 /**\r\n * Checks if a specific date should be disabled based on minDate, maxDate, or custom function.\r\n * @param date The date to check.\r\n * @returns True if the date is disabled, false otherwise.\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\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 and emits the new value. */\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 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\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 /**\r\n * Handles the click event on a calendar day cell to manage single or range selection.\r\n * @param day The date clicked.\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\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 // Update time controls to reflect the time of the newly selected date\r\n const selectedTimeRef = this.mode === 'single' ? this.selectedDate : this.startDate;\r\n if (selectedTimeRef) {\r\n this.update12HourState(selectedTimeRef.getHours());\r\n this.currentMinute = selectedTimeRef.getMinutes();\r\n }\r\n }\r\n\r\n /**\r\n * Updates the hovered date for range preview during selection.\r\n * @param day The date being hovered over.\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 /**\r\n * Checks if a date is within the range being previewed (during hover).\r\n * @param day The date to check.\r\n * @returns True if the date is in the preview range.\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 /** Generates the calendar grid (days and empty cells) 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 the dropdown selectors. */\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 /**\r\n * Moves the calendar view forward or backward by one month.\r\n * @param delta -1 for previous month, 1 for next month.\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 /**\r\n * Utility function to check if two dates represent the same day (ignoring time).\r\n * @param d1 The first date.\r\n * @param d2 The second date.\r\n * @returns True if they are the same day.\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 /**\r\n * Checks if a date is strictly between the start and end of a selected range (ignoring time).\r\n * @param d The date to check.\r\n * @returns True if the date is in the selected range.\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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"}
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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"}
package/index.d.ts CHANGED
@@ -1,16 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';
2
+ import { EventEmitter, ElementRef, OnInit, OnChanges, SimpleChanges } from '@angular/core';
3
3
 
4
- /**
5
- * @title Custom Select Component
6
- * @description A standalone component implementing a custom styled dropdown selector.
7
- * It handles options display, value tracking, and document click-away logic for closing.
8
- *
9
- * @selector app-custom-select
10
- * @export
11
- */
12
4
  declare class CustomSelectComponent {
13
- /** The ElementRef injected via `inject()` for DOM manipulation and click detection. */
14
5
  private readonly elementRef;
15
6
  /** The list of available options to display in the dropdown. */
16
7
  options: {
@@ -22,23 +13,14 @@ declare class CustomSelectComponent {
22
13
  /** Emits the new value when an option is selected. */
23
14
  valueChange: EventEmitter<any>;
24
15
  isOpen: boolean;
25
- constructor();
26
- /**
27
- * Closes the dropdown when a click event occurs outside the component's native element.
28
- * @param event The mouse event triggered on the document.
29
- */
16
+ constructor(elementRef: ElementRef);
17
+ /** Closes the dropdown when a click occurs outside the component boundary. */
30
18
  onDocumentClick(event: MouseEvent): void;
31
- /**
32
- * Retrieves the display label corresponding to the currently selected value.
33
- * @returns The label string or an empty string if no option is selected.
34
- */
19
+ /** Gets the display label for the currently selected value. */
35
20
  get displayValue(): string;
36
- /** Toggles the visibility state of the options dropdown panel. */
21
+ /** Toggles the visibility of the dropdown panel. */
37
22
  toggleDropdown(): void;
38
- /**
39
- * Handles the selection of a new option, updating the value and closing the dropdown.
40
- * @param option The selected option object containing label and value.
41
- */
23
+ /** Handles the selection of a new option. */
42
24
  selectOption(option: {
43
25
  label: string;
44
26
  value: any;
@@ -54,17 +36,7 @@ type DateInput = Date | string | {
54
36
  interface DateRange {
55
37
  [key: string]: [DateInput, DateInput];
56
38
  }
57
- /**
58
- * @title Ngxsmk Datepicker Component
59
- * @description A fully featured, standalone datepicker component supporting single date selection,
60
- * date range selection, time selection, custom date ranges, and theme toggling.
61
- *
62
- * @selector ngxsmk-datepicker
63
- * @implements OnInit, OnChanges
64
- * @export
65
- */
66
39
  declare class NgxsmkDatepickerComponent implements OnInit, OnChanges {
67
- /** Platform ID injected via `inject()` for Server-Side Rendering (SSR) checks. */
68
40
  private readonly platformId;
69
41
  /** Sets the selection mode: 'single' date or 'range' selection. */
70
42
  mode: 'single' | 'range';
@@ -87,7 +59,6 @@ declare class NgxsmkDatepickerComponent implements OnInit, OnChanges {
87
59
  get locale(): string;
88
60
  /** Controls the visual theme: 'light' or 'dark'. */
89
61
  theme: 'light' | 'dark';
90
- /** Binds the dark-theme class to the host element when theme is 'dark'. */
91
62
  get isDarkMode(): boolean;
92
63
  /** Emits the newly selected date or date range. */
93
64
  valueChange: EventEmitter<Date | {
@@ -142,104 +113,50 @@ declare class NgxsmkDatepickerComponent implements OnInit, OnChanges {
142
113
  label: string;
143
114
  value: boolean;
144
115
  }[];
145
- constructor();
146
- /** Retrieves the currently displayed calendar month index. */
116
+ constructor(platformId: Object);
147
117
  get currentMonth(): number;
148
- /** Sets the month index and regenerates the calendar grid. */
149
118
  set currentMonth(month: number);
150
- /** Retrieves the currently displayed calendar year. */
151
119
  get currentYear(): number;
152
- /** Sets the year and regenerates the calendar grid. */
153
120
  set currentYear(year: number);
154
- /** Initializes the component, performs platform checks, and sets up date/time states. */
155
121
  ngOnInit(): void;
156
- /** Handles input changes, particularly for `locale`, `minuteInterval`, and `value`. */
157
122
  ngOnChanges(changes: SimpleChanges): void;
158
- /**
159
- * Converts the displayed 12-hour time (displayHour + isPm) into the 24-hour internal time.
160
- * @param displayHour The 12-hour display hour (1-12).
161
- * @param isPm Whether the time is PM (true) or AM (false).
162
- * @returns The 24-hour time (0-23).
163
- */
123
+ /** Converts the displayed 12h time (currentDisplayHour + isPm) into the 24h internal time (currentHour). */
164
124
  private get24Hour;
165
- /**
166
- * Updates the display time variables (12h format and AM/PM state) from the 24h internal time.
167
- * @param fullHour The 24-hour time (0-23).
168
- */
125
+ /** Updates the display time variables (12h format and AM/PM state) from the 24h internal time. */
169
126
  private update12HourState;
170
- /**
171
- * Applies the currently selected hour and minute to a given date object.
172
- * @param date The date object to modify.
173
- * @returns The modified date object.
174
- */
127
+ /** Applies the currently selected hour and minute to a given date object. */
175
128
  private applyCurrentTime;
176
- /**
177
- * Initializes selection state and time controls from the provided input value.
178
- * @param value The input date or date range.
179
- */
129
+ /** Initializes selection state and time controls from the provided input value. */
180
130
  private initializeValue;
181
- /**
182
- * Normalizes a date input to a Date object, handling various types.
183
- * @param date The input date type.
184
- * @returns A valid Date object or null.
185
- */
131
+ /** Normalizes a date input to a Date object, keeping time information. */
186
132
  private _normalizeDate;
187
133
  /** Generates options for the hour and minute selectors based on the interval. */
188
134
  private generateTimeOptions;
189
- /** Generates locale-dependent month and weekday names for display. */
135
+ /** Generates locale-dependent month and weekday names. */
190
136
  private generateLocaleData;
191
- /** Populates the internal array of predefined ranges from the input object. */
137
+ /** Populates the internal array of predefined ranges. */
192
138
  private updateRangesArray;
193
- /**
194
- * Handles selection of a predefined date range, updates the view, and emits the new range.
195
- * @param range The selected date range [start, end].
196
- */
139
+ /** Handles selection of a predefined date range. */
197
140
  selectRange(range: [Date, Date]): void;
198
- /**
199
- * Checks if a specific date should be disabled based on minDate, maxDate, or custom function.
200
- * @param date The date to check.
201
- * @returns True if the date is disabled, false otherwise.
202
- */
141
+ /** Checks if a specific date should be disabled based on minDate, maxDate, or custom function. */
203
142
  isDateDisabled(date: Date | null): boolean;
204
- /** Updates the time component of the selected date(s) when hour/minute selectors change and emits the new value. */
143
+ /** Updates the time component of the selected date(s) when hour/minute selectors change. */
205
144
  onTimeChange(): void;
206
- /**
207
- * Handles the click event on a calendar day cell to manage single or range selection.
208
- * @param day The date clicked.
209
- */
145
+ /** Handles the click event on a calendar day cell. */
210
146
  onDateClick(day: Date | null): void;
211
- /**
212
- * Updates the hovered date for range preview during selection.
213
- * @param day The date being hovered over.
214
- */
147
+ /** Handles hover events for range preview when only the start date is selected. */
215
148
  onDateHover(day: Date | null): void;
216
- /**
217
- * Checks if a date is within the range being previewed (during hover).
218
- * @param day The date to check.
219
- * @returns True if the date is in the preview range.
220
- */
149
+ /** Checks if a date is within the range being previewed (during hover). */
221
150
  isPreviewInRange(day: Date | null): boolean;
222
- /** Generates the calendar grid (days and empty cells) for the currently active month. */
151
+ /** Generates the calendar grid for the currently active month. */
223
152
  generateCalendar(): void;
224
- /** Generates month and year options for the dropdown selectors. */
153
+ /** Generates month and year options for dropdowns. */
225
154
  private generateDropdownOptions;
226
- /**
227
- * Moves the calendar view forward or backward by one month.
228
- * @param delta -1 for previous month, 1 for next month.
229
- */
155
+ /** Moves the calendar view forward or backward by one month. */
230
156
  changeMonth(delta: number): void;
231
- /**
232
- * Utility function to check if two dates represent the same day (ignoring time).
233
- * @param d1 The first date.
234
- * @param d2 The second date.
235
- * @returns True if they are the same day.
236
- */
157
+ /** Utility function to check if two dates represent the same day (ignoring time). */
237
158
  isSameDay(d1: Date | null, d2: Date | null): boolean;
238
- /**
239
- * Checks if a date is strictly between the start and end of a selected range (ignoring time).
240
- * @param d The date to check.
241
- * @returns True if the date is in the selected range.
242
- */
159
+ /** Checks if a date is strictly between the start and end of a selected range (ignoring time). */
243
160
  isInRange(d: Date | null): boolean;
244
161
  static ɵfac: i0.ɵɵFactoryDeclaration<NgxsmkDatepickerComponent, never>;
245
162
  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>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngxsmk-datepicker",
3
- "version": "1.1.9",
3
+ "version": "1.2.1",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=17.0.0",
6
6
  "@angular/core": ">=17.0.0",