ngxsmk-datepicker 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,11 +10,11 @@ Built with Angular Signals for optimal performance and a clean, declarative API.
10
10
  ## Screenshots
11
11
 
12
12
  <p align="left">
13
- <img src="https://unpkg.com/ngxsmk-tel-input@latest/docs/1.png" alt="Angular Advanced Date Range Picker" width="420" />
13
+ <img src="https://unpkg.com/ngxsmk-datepicker@latest/docs/1.png" alt="Angular Advanced Date Range Picker" width="420" />
14
14
  &nbsp;&nbsp;
15
- <img src="https://unpkg.com/ngxsmk-tel-input@latest/docs/2.png" alt="Angular Localization" width="420" />
15
+ <img src="https://unpkg.com/ngxsmk-datepicker@latest/docs/2.png" alt="Angular Localization" width="420" />
16
16
  &nbsp;&nbsp;
17
- <img src="https://unpkg.com/ngxsmk-tel-input@latest/docs/3.png" alt="Angular Single Date Selection" width="420" />
17
+ <img src="https://unpkg.com/ngxsmk-datepicker@latest/docs/3.png" alt="Angular Single Date Selection" width="420" />
18
18
  </p>
19
19
 
20
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngxsmk-datepicker",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^20.3.0",
6
6
  "@angular/core": "^20.3.0"
@@ -9,6 +9,26 @@
9
9
  "tslib": "^2.3.0"
10
10
  },
11
11
  "sideEffects": false,
12
+ "files": [
13
+ "**/*.d.ts",
14
+ "**/*.metadata.json",
15
+ "**/*.js",
16
+ "README.md",
17
+ "LICENSE",
18
+ "docs"
19
+ ],
20
+ "keywords": [
21
+ "angular",
22
+ "datepicker",
23
+ "date-range-picker",
24
+ "calendar",
25
+ "standalone-component",
26
+ "angular-20",
27
+ "typescript",
28
+ "date-selection",
29
+ "i18n",
30
+ "localization"
31
+ ],
12
32
  "module": "fesm2022/ngxsmk-datepicker.mjs",
13
33
  "typings": "index.d.ts",
14
34
  "exports": {
@@ -1,463 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { EventEmitter, HostListener, Output, Input, Component, PLATFORM_ID, HostBinding, Inject } from '@angular/core';
3
- import * as i1 from '@angular/common';
4
- import { CommonModule, isPlatformBrowser } from '@angular/common';
5
- import { FormsModule } from '@angular/forms';
6
-
7
- // #####################################################################
8
- // ## Reusable Custom Select Component
9
- // #####################################################################
10
- class CustomSelectComponent {
11
- constructor(elementRef) {
12
- this.elementRef = elementRef;
13
- this.options = [];
14
- this.valueChange = new EventEmitter();
15
- this.isOpen = false;
16
- }
17
- onDocumentClick(event) {
18
- if (!this.elementRef.nativeElement.contains(event.target))
19
- this.isOpen = false;
20
- }
21
- get displayValue() {
22
- const selectedOption = this.options.find((opt) => opt.value === this.value);
23
- return selectedOption ? selectedOption.label : '';
24
- }
25
- toggleDropdown() {
26
- this.isOpen = !this.isOpen;
27
- }
28
- selectOption(option) {
29
- this.value = option.value;
30
- this.valueChange.emit(this.value);
31
- this.isOpen = false;
32
- }
33
- 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 }); }
34
- 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: `
35
- <div class="custom-select-container" (click)="toggleDropdown()">
36
- <button type="button" class="select-display">
37
- <span>{{ displayValue }}</span>
38
- <svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
39
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48"
40
- d="M112 184l144 144 144-144"/>
41
- </svg>
42
- </button>
43
- @if (isOpen) {
44
- <div class="options-panel">
45
- <ul>
46
- @for (option of options; track option.value) {
47
- <li [class.selected]="option.value === value" (click)="selectOption(option); $event.stopPropagation()">
48
- {{ option.label }}
49
- </li>
50
- }
51
- </ul>
52
- </div>
53
- }
54
- </div>
55
- `, isInline: true, styles: [":host{position:relative;display:inline-block}.custom-select-container{cursor:pointer}.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:1rem;text-align:left}.arrow-icon{width:12px;height:12px;margin-left:8px}.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:10}.options-panel ul{list-style:none;padding:4px;margin:0}.options-panel li{padding:8px 12px;border-radius:4px;cursor:pointer}.options-panel li:hover{background-color:var(--datepicker-hover-background, #f0f0f0)}.options-panel li.selected{background-color:var(--datepicker-primary-color, #3880ff);color:var(--datepicker-primary-contrast, #fff)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
56
- }
57
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: CustomSelectComponent, decorators: [{
58
- type: Component,
59
- args: [{ selector: 'app-custom-select', standalone: true, imports: [CommonModule], template: `
60
- <div class="custom-select-container" (click)="toggleDropdown()">
61
- <button type="button" class="select-display">
62
- <span>{{ displayValue }}</span>
63
- <svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
64
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48"
65
- d="M112 184l144 144 144-144"/>
66
- </svg>
67
- </button>
68
- @if (isOpen) {
69
- <div class="options-panel">
70
- <ul>
71
- @for (option of options; track option.value) {
72
- <li [class.selected]="option.value === value" (click)="selectOption(option); $event.stopPropagation()">
73
- {{ option.label }}
74
- </li>
75
- }
76
- </ul>
77
- </div>
78
- }
79
- </div>
80
- `, styles: [":host{position:relative;display:inline-block}.custom-select-container{cursor:pointer}.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:1rem;text-align:left}.arrow-icon{width:12px;height:12px;margin-left:8px}.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:10}.options-panel ul{list-style:none;padding:4px;margin:0}.options-panel li{padding:8px 12px;border-radius:4px;cursor:pointer}.options-panel li:hover{background-color:var(--datepicker-hover-background, #f0f0f0)}.options-panel li.selected{background-color:var(--datepicker-primary-color, #3880ff);color:var(--datepicker-primary-contrast, #fff)}\n"] }]
81
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { options: [{
82
- type: Input
83
- }], value: [{
84
- type: Input
85
- }], valueChange: [{
86
- type: Output
87
- }], onDocumentClick: [{
88
- type: HostListener,
89
- args: ['document:click', ['$event']]
90
- }] } });
91
- class NgxsmkDatepickerComponent {
92
- set locale(value) {
93
- this._locale = value;
94
- }
95
- get locale() {
96
- return this._locale;
97
- }
98
- get isDarkMode() {
99
- return this.theme === 'dark';
100
- }
101
- set minDate(value) {
102
- this._minDate = this._normalizeDate(value);
103
- }
104
- set maxDate(value) {
105
- this._maxDate = this._normalizeDate(value);
106
- }
107
- set ranges(value) {
108
- if (!value) {
109
- this._ranges = null;
110
- }
111
- else {
112
- this._ranges = Object.entries(value).reduce((acc, [key, dates]) => {
113
- const start = this._normalizeDate(dates[0]);
114
- const end = this._normalizeDate(dates[1]);
115
- if (start && end)
116
- acc[key] = [start, end];
117
- return acc;
118
- }, {});
119
- }
120
- this.updateRangesArray();
121
- }
122
- // FIX: Inject PLATFORM_ID and conditionally access navigator
123
- constructor(platformId) {
124
- this.platformId = platformId;
125
- this.mode = 'single';
126
- this.isInvalidDate = () => false;
127
- this.showRanges = true;
128
- // FIX: Use a private variable for locale with a fallback value.
129
- this._locale = 'en-US';
130
- this.theme = 'light';
131
- this.valueChange = new EventEmitter();
132
- this._minDate = null;
133
- this._maxDate = null;
134
- this._ranges = null;
135
- this.currentDate = new Date();
136
- this.daysInMonth = [];
137
- this.weekDays = [];
138
- this.today = new Date();
139
- this.selectedDate = null;
140
- this.startDate = null;
141
- this.endDate = null;
142
- this.hoveredDate = null;
143
- this.rangesArray = [];
144
- this.monthOptions = [];
145
- this.yearOptions = [];
146
- this.firstDayOfWeek = 0;
147
- if (isPlatformBrowser(this.platformId)) {
148
- this._locale = navigator.language;
149
- }
150
- }
151
- get currentMonth() {
152
- return this._currentMonth;
153
- }
154
- set currentMonth(month) {
155
- if (this._currentMonth !== month) {
156
- this._currentMonth = month;
157
- this.currentDate.setMonth(month);
158
- this.generateCalendar();
159
- }
160
- }
161
- get currentYear() {
162
- return this._currentYear;
163
- }
164
- set currentYear(year) {
165
- if (this._currentYear !== year) {
166
- this._currentYear = year;
167
- this.currentDate.setFullYear(year);
168
- this.generateCalendar();
169
- }
170
- }
171
- ngOnInit() {
172
- this.today.setHours(0, 0, 0, 0);
173
- this.generateLocaleData();
174
- this.generateCalendar();
175
- }
176
- ngOnChanges(changes) {
177
- if (changes['locale']) {
178
- this.generateLocaleData();
179
- this.generateCalendar();
180
- }
181
- }
182
- _normalizeDate(date) {
183
- if (!date)
184
- return null;
185
- const d = (date instanceof Date) ? new Date(date.getTime()) : new Date(date);
186
- if (isNaN(d.getTime()))
187
- return null;
188
- d.setHours(0, 0, 0, 0);
189
- return d;
190
- }
191
- generateLocaleData() {
192
- this.monthOptions = Array.from({ length: 12 }).map((_, i) => ({
193
- label: new Date(2024, i, 1).toLocaleDateString(this.locale, { month: 'long' }),
194
- value: i,
195
- }));
196
- try {
197
- // Use this.locale getter
198
- this.firstDayOfWeek = (new Intl.Locale(this.locale).weekInfo?.firstDay || 0) % 7;
199
- }
200
- catch (e) {
201
- this.firstDayOfWeek = 0;
202
- }
203
- const day = new Date(2024, 0, 7 + this.firstDayOfWeek);
204
- this.weekDays = Array.from({ length: 7 }).map(() => {
205
- const weekDay = new Date(day).toLocaleDateString(this.locale, { weekday: 'short' });
206
- day.setDate(day.getDate() + 1);
207
- return weekDay;
208
- });
209
- }
210
- updateRangesArray() {
211
- this.rangesArray = this._ranges ? Object.entries(this._ranges).map(([key, value]) => ({ key, value })) : [];
212
- }
213
- selectRange(range) {
214
- this.startDate = range[0];
215
- this.endDate = range[1];
216
- this.valueChange.emit({ start: this.startDate, end: this.endDate });
217
- this.currentDate = new Date(this.startDate);
218
- this.generateCalendar();
219
- }
220
- isDateDisabled(date) {
221
- if (!date)
222
- return false;
223
- if (this._minDate && date < this._minDate)
224
- return true;
225
- if (this._maxDate && date > this._maxDate)
226
- return true;
227
- if (this.isInvalidDate(date))
228
- return true;
229
- return false;
230
- }
231
- onDateClick(day) {
232
- if (!day || this.isDateDisabled(day))
233
- return;
234
- if (this.mode === 'single') {
235
- this.selectedDate = day;
236
- this.valueChange.emit(this.selectedDate);
237
- }
238
- else {
239
- if (!this.startDate || (this.startDate && this.endDate)) {
240
- this.startDate = day;
241
- this.endDate = null;
242
- }
243
- else if (day >= this.startDate) {
244
- this.endDate = day;
245
- this.valueChange.emit({ start: this.startDate, end: this.endDate });
246
- }
247
- else {
248
- this.startDate = day;
249
- this.endDate = null;
250
- }
251
- this.hoveredDate = null;
252
- }
253
- }
254
- onDateHover(day) {
255
- if (this.mode === 'range' && this.startDate && !this.endDate && day) {
256
- this.hoveredDate = day;
257
- }
258
- }
259
- isPreviewInRange(day) {
260
- if (this.mode !== 'range' || !this.startDate || this.endDate || !this.hoveredDate || !day)
261
- return false;
262
- const start = this.startDate.getTime();
263
- const end = this.hoveredDate.getTime();
264
- const time = day.getTime();
265
- return time > Math.min(start, end) && time < Math.max(start, end);
266
- }
267
- generateCalendar() {
268
- this.daysInMonth = [];
269
- const year = this.currentDate.getFullYear();
270
- const month = this.currentDate.getMonth();
271
- this._currentMonth = month;
272
- this._currentYear = year;
273
- this.generateDropdownOptions();
274
- const firstDayOfMonth = new Date(year, month, 1);
275
- const lastDayOfMonth = new Date(year, month + 1, 0);
276
- const startDayOfWeek = firstDayOfMonth.getDay();
277
- const emptyCellCount = (startDayOfWeek - this.firstDayOfWeek + 7) % 7;
278
- for (let i = 0; i < emptyCellCount; i++) {
279
- this.daysInMonth.push(null);
280
- }
281
- for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {
282
- this.daysInMonth.push(this._normalizeDate(new Date(year, month, i)));
283
- }
284
- }
285
- generateDropdownOptions() {
286
- const startYear = this._currentYear - 10;
287
- const endYear = this._currentYear + 10;
288
- this.yearOptions = [];
289
- for (let i = startYear; i <= endYear; i++) {
290
- this.yearOptions.push({ label: `${i}`, value: i });
291
- }
292
- }
293
- changeMonth(delta) {
294
- this.currentDate.setMonth(this.currentDate.getMonth() + delta);
295
- this.generateCalendar();
296
- }
297
- isSameDay(d1, d2) {
298
- if (!d1 || !d2)
299
- return false;
300
- return (d1.getFullYear() === d2.getFullYear() &&
301
- d1.getMonth() === d2.getMonth() &&
302
- d1.getDate() === d2.getDate());
303
- }
304
- isInRange(d) {
305
- if (!d || !this.startDate || !this.endDate)
306
- return false;
307
- return (d.getTime() > this.startDate.getTime() &&
308
- d.getTime() < this.endDate.getTime());
309
- }
310
- 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 }); }
311
- 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", 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: `
312
- <div class="datepicker-container">
313
- @if (showRanges && rangesArray.length > 0 && mode === 'range') {
314
- <div class="ranges-container">
315
- <ul>
316
- @for (range of rangesArray; track range.key) {
317
- <li (click)="selectRange(range.value)">{{ range.key }}</li>
318
- }
319
- </ul>
320
- </div>
321
- }
322
- <div class="calendar-container">
323
- <div class="header">
324
- <div class="month-year-selects">
325
- <app-custom-select class="month-select" [options]="monthOptions"
326
- [(value)]="currentMonth"></app-custom-select>
327
- <app-custom-select class="year-select" [options]="yearOptions" [(value)]="currentYear"></app-custom-select>
328
- </div>
329
- <div class="nav-buttons">
330
- <button type="button" class="nav-button" (click)="changeMonth(-1)">
331
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
332
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48"
333
- d="M328 112L184 256l144 144"/>
334
- </svg>
335
- </button>
336
- <button type="button" class="nav-button" (click)="changeMonth(1)">
337
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
338
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48"
339
- d="M184 112l144 144-144 144"/>
340
- </svg>
341
- </button>
342
- </div>
343
- </div>
344
- <div class="days-grid-wrapper">
345
- <div class="days-grid">
346
- @for (day of weekDays; track day) {
347
- <div class="day-name">{{ day }}</div>
348
- }
349
- @for (day of daysInMonth; track $index) {
350
- <div class="day-cell"
351
- [class.empty]="!day" [class.disabled]="isDateDisabled(day)" [class.today]="isSameDay(day, today)"
352
- [class.selected]="mode === 'single' && isSameDay(day, selectedDate)"
353
- [class.start-date]="mode === 'range' && isSameDay(day, startDate)"
354
- [class.end-date]="mode === 'range' && isSameDay(day, endDate)"
355
- [class.in-range]="mode === 'range' && isInRange(day)"
356
- [class.preview-range]="isPreviewInRange(day)"
357
- (click)="onDateClick(day)" (mouseenter)="onDateHover(day)">
358
- @if (day) {
359
- <div class="day-number">{{ day | date : 'd' }}</div>
360
- }
361
- </div>
362
- }
363
- </div>
364
- </div>
365
- </div>
366
- </div>
367
- `, 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}.datepicker-container{display:flex}.calendar-container{width:320px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;border:1px solid var(--datepicker-border-color);border-radius:10px;padding:16px;background:var(--datepicker-background);overflow:hidden}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;position:relative;z-index:2}.month-year-selects{display:flex;gap:8px}.month-year-selects app-custom-select.month-select{--custom-select-width: 120px}.month-year-selects app-custom-select.year-select{--custom-select-width: 90px}.nav-buttons{display:flex}.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)}.nav-button:hover{background-color:var(--datepicker-hover-background)}.nav-button svg{width:18px;height:18px}.days-grid-wrapper{position:relative}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;gap:0}.day-name{font-weight:600;font-size:.8rem;color:var(--datepicker-subtle-text-color);padding:8px 0}.day-cell{position:relative;height:38px;display:flex;justify-content:center;align-items:center;cursor:pointer;border-radius:0}.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}.day-cell:not(.disabled):hover .day-number{background-color:var(--datepicker-hover-background)}.day-cell.start-date .day-number,.day-cell.end-date .day-number,.day-cell.selected .day-number{background-color:var(--datepicker-primary-color);color:var(--datepicker-primary-contrast)}.day-cell.in-range,.day-cell.start-date,.day-cell.end-date,.day-cell.preview-range{background-color:var(--datepicker-range-background)}.day-cell.start-date{border-top-left-radius:50px;border-bottom-left-radius:50px}.day-cell.end-date{border-top-right-radius:50px;border-bottom-right-radius:50px}.day-cell.start-date.end-date{border-radius:50px}.day-cell.disabled{background-color:transparent!important;color:#4b5563;cursor:not-allowed;pointer-events:none;opacity:.5}.day-cell.today .day-number{border:1px solid var(--datepicker-primary-color)}.ranges-container{width:180px;padding:16px;border-right:1px solid var(--datepicker-border-color);background:var(--datepicker-background)}.ranges-container ul{list-style:none;padding:0;margin:0}.ranges-container li{padding:10px;margin-bottom:8px;border-radius:6px;cursor:pointer;color:var(--datepicker-text-color)}.ranges-container li:hover{background-color:var(--datepicker-hover-background)}\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" }] }); }
368
- }
369
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: NgxsmkDatepickerComponent, decorators: [{
370
- type: Component,
371
- args: [{ selector: 'ngxsmk-datepicker', standalone: true, imports: [CommonModule, FormsModule, CustomSelectComponent], template: `
372
- <div class="datepicker-container">
373
- @if (showRanges && rangesArray.length > 0 && mode === 'range') {
374
- <div class="ranges-container">
375
- <ul>
376
- @for (range of rangesArray; track range.key) {
377
- <li (click)="selectRange(range.value)">{{ range.key }}</li>
378
- }
379
- </ul>
380
- </div>
381
- }
382
- <div class="calendar-container">
383
- <div class="header">
384
- <div class="month-year-selects">
385
- <app-custom-select class="month-select" [options]="monthOptions"
386
- [(value)]="currentMonth"></app-custom-select>
387
- <app-custom-select class="year-select" [options]="yearOptions" [(value)]="currentYear"></app-custom-select>
388
- </div>
389
- <div class="nav-buttons">
390
- <button type="button" class="nav-button" (click)="changeMonth(-1)">
391
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
392
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48"
393
- d="M328 112L184 256l144 144"/>
394
- </svg>
395
- </button>
396
- <button type="button" class="nav-button" (click)="changeMonth(1)">
397
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
398
- <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48"
399
- d="M184 112l144 144-144 144"/>
400
- </svg>
401
- </button>
402
- </div>
403
- </div>
404
- <div class="days-grid-wrapper">
405
- <div class="days-grid">
406
- @for (day of weekDays; track day) {
407
- <div class="day-name">{{ day }}</div>
408
- }
409
- @for (day of daysInMonth; track $index) {
410
- <div class="day-cell"
411
- [class.empty]="!day" [class.disabled]="isDateDisabled(day)" [class.today]="isSameDay(day, today)"
412
- [class.selected]="mode === 'single' && isSameDay(day, selectedDate)"
413
- [class.start-date]="mode === 'range' && isSameDay(day, startDate)"
414
- [class.end-date]="mode === 'range' && isSameDay(day, endDate)"
415
- [class.in-range]="mode === 'range' && isInRange(day)"
416
- [class.preview-range]="isPreviewInRange(day)"
417
- (click)="onDateClick(day)" (mouseenter)="onDateHover(day)">
418
- @if (day) {
419
- <div class="day-number">{{ day | date : 'd' }}</div>
420
- }
421
- </div>
422
- }
423
- </div>
424
- </div>
425
- </div>
426
- </div>
427
- `, 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}.datepicker-container{display:flex}.calendar-container{width:320px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;border:1px solid var(--datepicker-border-color);border-radius:10px;padding:16px;background:var(--datepicker-background);overflow:hidden}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;position:relative;z-index:2}.month-year-selects{display:flex;gap:8px}.month-year-selects app-custom-select.month-select{--custom-select-width: 120px}.month-year-selects app-custom-select.year-select{--custom-select-width: 90px}.nav-buttons{display:flex}.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)}.nav-button:hover{background-color:var(--datepicker-hover-background)}.nav-button svg{width:18px;height:18px}.days-grid-wrapper{position:relative}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;gap:0}.day-name{font-weight:600;font-size:.8rem;color:var(--datepicker-subtle-text-color);padding:8px 0}.day-cell{position:relative;height:38px;display:flex;justify-content:center;align-items:center;cursor:pointer;border-radius:0}.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}.day-cell:not(.disabled):hover .day-number{background-color:var(--datepicker-hover-background)}.day-cell.start-date .day-number,.day-cell.end-date .day-number,.day-cell.selected .day-number{background-color:var(--datepicker-primary-color);color:var(--datepicker-primary-contrast)}.day-cell.in-range,.day-cell.start-date,.day-cell.end-date,.day-cell.preview-range{background-color:var(--datepicker-range-background)}.day-cell.start-date{border-top-left-radius:50px;border-bottom-left-radius:50px}.day-cell.end-date{border-top-right-radius:50px;border-bottom-right-radius:50px}.day-cell.start-date.end-date{border-radius:50px}.day-cell.disabled{background-color:transparent!important;color:#4b5563;cursor:not-allowed;pointer-events:none;opacity:.5}.day-cell.today .day-number{border:1px solid var(--datepicker-primary-color)}.ranges-container{width:180px;padding:16px;border-right:1px solid var(--datepicker-border-color);background:var(--datepicker-background)}.ranges-container ul{list-style:none;padding:0;margin:0}.ranges-container li{padding:10px;margin-bottom:8px;border-radius:6px;cursor:pointer;color:var(--datepicker-text-color)}.ranges-container li:hover{background-color:var(--datepicker-hover-background)}\n"] }]
428
- }], ctorParameters: () => [{ type: Object, decorators: [{
429
- type: Inject,
430
- args: [PLATFORM_ID]
431
- }] }], propDecorators: { mode: [{
432
- type: Input
433
- }], isInvalidDate: [{
434
- type: Input
435
- }], showRanges: [{
436
- type: Input
437
- }], locale: [{
438
- type: Input
439
- }], theme: [{
440
- type: Input
441
- }], isDarkMode: [{
442
- type: HostBinding,
443
- args: ['class.dark-theme']
444
- }], valueChange: [{
445
- type: Output
446
- }], minDate: [{
447
- type: Input
448
- }], maxDate: [{
449
- type: Input
450
- }], ranges: [{
451
- type: Input
452
- }] } });
453
-
454
- /*
455
- * Public API Surface of ngxsmk-datepicker
456
- */
457
-
458
- /**
459
- * Generated bundle index. Do not edit.
460
- */
461
-
462
- export { CustomSelectComponent, NgxsmkDatepickerComponent };
463
- //# sourceMappingURL=ngxsmk-datepicker.mjs.map
@@ -1 +0,0 @@
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=\"custom-select-container\" (click)=\"toggleDropdown()\">\r\n <button type=\"button\" class=\"select-display\">\r\n <span>{{ displayValue }}</span>\r\n <svg class=\"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=\"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 .custom-select-container {\r\n cursor: pointer;\r\n }\r\n\r\n .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: 1rem;\r\n text-align: left;\r\n }\r\n\r\n .arrow-icon {\r\n width: 12px;\r\n height: 12px;\r\n margin-left: 8px;\r\n }\r\n\r\n .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: 10;\r\n }\r\n\r\n .options-panel ul {\r\n list-style: none;\r\n padding: 4px;\r\n margin: 0;\r\n }\r\n\r\n .options-panel li {\r\n padding: 8px 12px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n }\r\n\r\n .options-panel li:hover {\r\n background-color: var(--datepicker-hover-background, #f0f0f0);\r\n }\r\n\r\n .options-panel li.selected {\r\n background-color: var(--datepicker-primary-color, #3880ff);\r\n color: var(--datepicker-primary-contrast, #fff);\r\n }\r\n `],\r\n})\r\nexport class CustomSelectComponent {\r\n @Input() options: { label: string; value: any }[] = [];\r\n @Input() value: any;\r\n @Output() valueChange = new EventEmitter<any>();\r\n public isOpen = false;\r\n\r\n constructor(private readonly elementRef: ElementRef) {\r\n }\r\n\r\n @HostListener('document:click', ['$event'])\r\n onDocumentClick(event: MouseEvent): void {\r\n if (!this.elementRef.nativeElement.contains(event.target)) this.isOpen = false;\r\n }\r\n\r\n get displayValue(): string {\r\n const selectedOption = this.options.find((opt) => opt.value === this.value);\r\n return selectedOption ? selectedOption.label : '';\r\n }\r\n\r\n toggleDropdown(): void {\r\n this.isOpen = !this.isOpen;\r\n }\r\n\r\n selectOption(option: { label: string; value: any }): void {\r\n this.value = option.value;\r\n this.valueChange.emit(this.value);\r\n this.isOpen = false;\r\n }\r\n}\r\n\r\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=\"datepicker-container\">\r\n @if (showRanges && rangesArray.length > 0 && mode === 'range') {\r\n <div class=\"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=\"calendar-container\">\r\n <div class=\"header\">\r\n <div class=\"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=\"nav-buttons\">\r\n <button type=\"button\" class=\"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=\"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=\"days-grid-wrapper\">\r\n <div class=\"days-grid\">\r\n @for (day of weekDays; track day) {\r\n <div class=\"day-name\">{{ day }}</div>\r\n }\r\n @for (day of daysInMonth; track $index) {\r\n <div class=\"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=\"day-number\">{{ day | date : 'd' }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\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 .datepicker-container {\r\n display: flex;\r\n }\r\n\r\n .calendar-container {\r\n width: 320px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n border: 1px solid var(--datepicker-border-color);\r\n border-radius: 10px;\r\n padding: 16px;\r\n background: var(--datepicker-background);\r\n overflow: hidden;\r\n }\r\n\r\n .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 }\r\n\r\n .month-year-selects {\r\n display: flex;\r\n gap: 8px;\r\n }\r\n\r\n .month-year-selects app-custom-select.month-select {\r\n --custom-select-width: 120px;\r\n }\r\n\r\n .month-year-selects app-custom-select.year-select {\r\n --custom-select-width: 90px;\r\n }\r\n\r\n .nav-buttons {\r\n display: flex;\r\n }\r\n\r\n .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 .nav-button:hover {\r\n background-color: var(--datepicker-hover-background);\r\n }\r\n\r\n .nav-button svg {\r\n width: 18px;\r\n height: 18px;\r\n }\r\n\r\n .days-grid-wrapper {\r\n position: relative;\r\n }\r\n\r\n .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 .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 .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 .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 .day-cell:not(.disabled):hover .day-number {\r\n background-color: var(--datepicker-hover-background);\r\n }\r\n\r\n .day-cell.start-date .day-number,\r\n .day-cell.end-date .day-number,\r\n .day-cell.selected .day-number {\r\n background-color: var(--datepicker-primary-color);\r\n color: var(--datepicker-primary-contrast);\r\n }\r\n\r\n .day-cell.in-range, .day-cell.start-date, .day-cell.end-date, .day-cell.preview-range {\r\n background-color: var(--datepicker-range-background);\r\n }\r\n\r\n .day-cell.start-date {\r\n border-top-left-radius: 50px;\r\n border-bottom-left-radius: 50px;\r\n }\r\n\r\n .day-cell.end-date {\r\n border-top-right-radius: 50px;\r\n border-bottom-right-radius: 50px;\r\n }\r\n\r\n .day-cell.start-date.end-date {\r\n border-radius: 50px;\r\n }\r\n\r\n .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 .day-cell.today .day-number {\r\n border: 1px solid var(--datepicker-primary-color);\r\n }\r\n\r\n .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 .ranges-container ul {\r\n list-style: none;\r\n padding: 0;\r\n margin: 0;\r\n }\r\n\r\n .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 .ranges-container li:hover {\r\n background-color: var(--datepicker-hover-background);\r\n }\r\n `],\r\n})\r\nexport class NgxsmkDatepickerComponent implements OnInit, OnChanges {\r\n @Input() mode: 'single' | 'range' = 'single';\r\n @Input() isInvalidDate: (date: Date) => boolean = () => false;\r\n @Input() showRanges: boolean = true;\r\n\r\n // FIX: Use a private variable for locale with a fallback value.\r\n private _locale: string = 'en-US';\r\n\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 @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 @Output() valueChange = new EventEmitter<Date | { start: Date; end: Date }>();\r\n\r\n private _minDate: Date | null = null;\r\n\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 @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 @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 // FIX: Inject PLATFORM_ID and conditionally access navigator\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.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\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 d.setHours(0, 0, 0, 0);\r\n return d;\r\n }\r\n\r\n private generateLocaleData(): void {\r\n this.monthOptions = Array.from({length: 12}).map((_, i) => ({\r\n label: new Date(2024, i, 1).toLocaleDateString(this.locale, {month: 'long'}),\r\n value: i,\r\n }));\r\n try {\r\n // Use this.locale getter\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 private updateRangesArray(): void {\r\n this.rangesArray = this._ranges ? Object.entries(this._ranges).map(([key, value]) => ({key, value})) : [];\r\n }\r\n\r\n public selectRange(range: [Date, Date]): void {\r\n this.startDate = range[0];\r\n this.endDate = range[1];\r\n this.valueChange.emit({start: this.startDate, end: this.endDate});\r\n this.currentDate = new Date(this.startDate);\r\n this.generateCalendar();\r\n }\r\n\r\n public isDateDisabled(date: Date | null): boolean {\r\n if (!date) return false;\r\n if (this._minDate && date < this._minDate) return true;\r\n if (this._maxDate && date > this._maxDate) return true;\r\n if (this.isInvalidDate(date)) return true;\r\n return false;\r\n }\r\n\r\n public onDateClick(day: Date | null): void {\r\n if (!day || this.isDateDisabled(day)) return;\r\n if (this.mode === 'single') {\r\n this.selectedDate = day;\r\n this.valueChange.emit(this.selectedDate);\r\n } else {\r\n if (!this.startDate || (this.startDate && this.endDate)) {\r\n this.startDate = day;\r\n this.endDate = null;\r\n } else if (day >= this.startDate) {\r\n this.endDate = day;\r\n this.valueChange.emit({start: this.startDate, end: this.endDate});\r\n } else {\r\n this.startDate = day;\r\n this.endDate = null;\r\n }\r\n this.hoveredDate = null;\r\n }\r\n }\r\n\r\n public onDateHover(day: Date | null): void {\r\n if (this.mode === 'range' && this.startDate && !this.endDate && day) {\r\n this.hoveredDate = day;\r\n }\r\n }\r\n\r\n public isPreviewInRange(day: Date | null): boolean {\r\n if (this.mode !== 'range' || !this.startDate || this.endDate || !this.hoveredDate || !day) return false;\r\n const start = this.startDate.getTime();\r\n const end = this.hoveredDate.getTime();\r\n const time = day.getTime();\r\n return time > Math.min(start, end) && time < Math.max(start, end);\r\n }\r\n\r\n public generateCalendar(): void {\r\n this.daysInMonth = [];\r\n const year = this.currentDate.getFullYear();\r\n const month = this.currentDate.getMonth();\r\n this._currentMonth = month;\r\n this._currentYear = year;\r\n this.generateDropdownOptions();\r\n const firstDayOfMonth = new Date(year, month, 1);\r\n const lastDayOfMonth = new Date(year, month + 1, 0);\r\n const startDayOfWeek = firstDayOfMonth.getDay();\r\n const emptyCellCount = (startDayOfWeek - this.firstDayOfWeek + 7) % 7;\r\n\r\n for (let i = 0; i < emptyCellCount; i++) {\r\n this.daysInMonth.push(null);\r\n }\r\n for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {\r\n this.daysInMonth.push(this._normalizeDate(new Date(year, month, i)));\r\n }\r\n }\r\n\r\n private generateDropdownOptions(): void {\r\n const startYear = this._currentYear - 10;\r\n const endYear = this._currentYear + 10;\r\n this.yearOptions = [];\r\n for (let i = startYear; i <= endYear; i++) {\r\n this.yearOptions.push({label: `${i}`, value: i});\r\n }\r\n }\r\n\r\n public changeMonth(delta: number): void {\r\n this.currentDate.setMonth(this.currentDate.getMonth() + delta);\r\n this.generateCalendar();\r\n }\r\n\r\n public isSameDay(d1: Date | null, d2: Date | null): boolean {\r\n if (!d1 || !d2) return false;\r\n return (\r\n d1.getFullYear() === d2.getFullYear() &&\r\n d1.getMonth() === d2.getMonth() &&\r\n d1.getDate() === d2.getDate()\r\n );\r\n }\r\n\r\n public isInRange(d: Date | null): boolean {\r\n if (!d || !this.startDate || !this.endDate) return false;\r\n return (\r\n d.getTime() > this.startDate.getTime() &&\r\n d.getTime() < this.endDate.getTime()\r\n );\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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"}