ngxsmk-datepicker 2.0.4 → 2.0.6

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
@@ -7,7 +7,7 @@
7
7
 
8
8
  **npm i ngxsmk-datepicker**
9
9
 
10
- > **Stable Version**: `2.0.3` is the current stable release. For production use, install the latest version from npm.
10
+ > **Stable Version**: `2.0.5` is the current stable release. For production use, install the latest version from npm.
11
11
  >
12
12
  > ⚠️ **Warning**: Version `1.9.26` contains broken styles. If you are using `1.9.26`, please upgrade to `1.9.28` or downgrade to `1.9.25` immediately.
13
13
 
@@ -33,6 +33,7 @@ Built with Angular Signals for optimal performance and a clean, declarative API.
33
33
  ## **✨ Features**
34
34
 
35
35
  * **Multiple Selection Modes**: Supports `single`, `range`, and `multiple` date selection.
36
+ * **Smart Range Reselection**: Clicking the start date again after selecting a complete range clears only the end date, allowing quick range adjustments without clearing the entire selection.
36
37
  * **Inline and Popover Display**: Can be rendered inline or as a popover with automatic mode detection.
37
38
  * **Light and Dark Themes**: Includes built-in support for light and dark modes.
38
39
  * **Holiday Marking**: Automatically mark and disable holidays using a custom `HolidayProvider`.
@@ -127,7 +128,7 @@ For details, see [CONTRIBUTING.md](https://github.com/NGXSMK/ngxsmk-datepicker/b
127
128
 
128
129
  Install the package using npm:
129
130
 
130
- npm install ngxsmk-datepicker@2.0.3
131
+ npm install ngxsmk-datepicker@2.0.5
131
132
 
132
133
  ## **Usage**
133
134
 
@@ -488,6 +489,26 @@ export class PlainFormComponent {
488
489
  </form>
489
490
  ```
490
491
 
492
+ ### **Form Validation**
493
+
494
+ By default, the datepicker input is `readonly` to prevent invalid date strings and force selection via the calendar. However, **browsers do not validate `readonly` fields** during native form submission.
495
+
496
+ **Behavior:**
497
+ - Native browser validation (e.g., blocking submit on `required` fields) will **NOT** trigger on the datepicker by default.
498
+ - Custom validation (e.g., Angular validators) works normally but often only shows errors after the control is "touched".
499
+
500
+ **Solutions:**
501
+
502
+ 1. **Enable Typing (Recommended for Native Validation):**
503
+ Set `[allowTyping]="true"` to make the input standard editable field. This enables native browser validation tooltips and submit-blocking.
504
+ ```html
505
+ <ngxsmk-datepicker [allowTyping]="true" required ...></ngxsmk-datepicker>
506
+ ```
507
+
508
+ 2. **Custom Validation Logic:**
509
+ If you prefer the readonly behavior, ensure your form submission handler explicitly checks `form.invalid` before proceeding, as the browser won't stop the submit button click.
510
+
511
+
491
512
  ## **⚙️ API Reference**
492
513
 
493
514
  ### **Inputs**
@@ -506,6 +527,8 @@ export class PlainFormComponent {
506
527
  | minuteInterval | number | 1 | Interval for minute dropdown options. |
507
528
  | showTime | boolean | false | Enables the hour/minute/AM/PM selection section. |
508
529
  | timeOnly | boolean | false | Display time picker only (no calendar). Automatically enables `showTime`. Perfect for time selection scenarios. |
530
+ | allowTyping | boolean | false | Enable manual typing in the input field. Required for native validation. | `[allowTyping]="true"` |
531
+ | displayFormat | string | null | Custom date format string (e.g., 'MM/DD/YYYY'). | `displayFormat="DD.MM.YYYY"` |
509
532
  | showCalendarButton | boolean | false | Show/hide the calendar icon button. When `false`, users can still open calendar by clicking the input field. |
510
533
  | value | DatepickerValue | null | Programmatic value setting. Set the datepicker value from code (useful for server-side API data). |
511
534
  | startAt | DateInput | null | The date to initially center the calendar view on. |
package/docs/API.md CHANGED
@@ -55,6 +55,8 @@ import { NgxsmkDatepickerComponent } from 'ngxsmk-datepicker';
55
55
  | `inline` | `boolean \| 'always' \| 'auto'` | `false` | Stable | Inline display mode | `[inline]="true"` or `inline="auto"` |
56
56
  | `showTime` | `boolean` | `false` | Stable | Show time selection | `[showTime]="true"` |
57
57
  | `timeOnly` | `boolean` | `false` | Stable | Display time picker only (no calendar). Automatically enables `showTime`. | `[timeOnly]="true"` |
58
+ | `allowTyping` | `boolean` | `false` | Stable | Enable manual typing in the input field. Required for native validation. | `[allowTyping]="true"` |
59
+ | `displayFormat` | `string` | `null` | Stable | Custom date format string (e.g., 'MM/DD/YYYY'). | `displayFormat="DD.MM.YYYY"` |
58
60
  | `showCalendarButton` | `boolean` | `true` | Stable | Show/hide the calendar icon button. When `false`, users can still open calendar by clicking the input field. | `[showCalendarButton]="false"` |
59
61
  | `minuteInterval` | `number` | `1` | Stable | Minute selection interval | `[minuteInterval]="15"` |
60
62
  | `showRanges` | `boolean` | `true` | Stable | Show predefined ranges (range mode) | `[showRanges]="true"` |
@@ -2180,7 +2182,7 @@ type DateInput =
2180
2182
  ```
2181
2183
 
2182
2184
 
2183
- ### SignalFormField (v2.0.3+)
2185
+ ### SignalFormField (v2.0.5+)
2184
2186
 
2185
2187
  **Status**: Stable
2186
2188
 
@@ -2190,7 +2192,7 @@ Type representing a signal-based form field.
2190
2192
  type SignalFormField = any; // Compatible with Angular 21 FieldTree
2191
2193
  ```
2192
2194
 
2193
- ### SignalFormFieldConfig (v2.0.3+)
2195
+ ### SignalFormFieldConfig (v2.0.5+)
2194
2196
 
2195
2197
  **Status**: Stable
2196
2198
 
@@ -113,7 +113,7 @@ export class TwoWayComponent {
113
113
  }
114
114
  ```
115
115
 
116
- ### Signal Field Resolution (v2.0.3+)
116
+ ### Signal Field Resolution (v2.0.5+)
117
117
 
118
118
  The datepicker includes a robust resolution mechanism for signal-based fields. It can handle:
119
119
  - **Direct Signals**: A signal that contains the field configuration.
@@ -136,7 +136,7 @@ const config: SignalFormFieldConfig = {
136
136
  };
137
137
  ```
138
138
 
139
- **TypeScript Compatibility (v2.0.3+):**
139
+ **TypeScript Compatibility (v2.0.5+):**
140
140
 
141
141
  The datepicker is fully compatible with Angular 21+ `FieldTree<string | Date | null, string>` structure. The types accept:
142
142
  - `WritableSignal<Date | null>` for date values
@@ -321,6 +321,13 @@ export class ValidatedFormComponent {
321
321
  }
322
322
  ```
323
323
 
324
+ ### Note on Native Validation
325
+ By default, the datepicker input is `readonly`. Browsers do not validate `readonly` fields. To enable native browser validation (e.g., blocking submit on empty required fields), set `[allowTyping]="true"`.
326
+
327
+ ```html
328
+ <ngxsmk-datepicker [field]="myForm.date" [allowTyping]="true" required ...></ngxsmk-datepicker>
329
+ ```
330
+
324
331
  ## Date Range Forms
325
332
 
326
333
  For date range selection:
@@ -7233,7 +7233,31 @@ class NgxsmkDatepickerComponent {
7233
7233
  }
7234
7234
  const dayTime = getStartOfDay(day).getTime();
7235
7235
  const startTime = this.startDate ? getStartOfDay(this.startDate).getTime() : null;
7236
- if (!this.startDate || (this.startDate && this.endDate)) {
7236
+ const endTime = this.endDate ? getStartOfDay(this.endDate).getTime() : null;
7237
+ if (this.startDate && this.endDate && dayTime === startTime) {
7238
+ this.endDate = null;
7239
+ this.hoveredDate = null;
7240
+ this._invalidateMemoCache();
7241
+ this.emitValue({ start: this.startDate, end: null });
7242
+ this.scheduleChangeDetection();
7243
+ }
7244
+ else if (this.startDate && this.endDate && dayTime === endTime) {
7245
+ this.startDate = this.applyTimeIfNeeded(day);
7246
+ this.endDate = null;
7247
+ this.hoveredDate = null;
7248
+ this._invalidateMemoCache();
7249
+ this.emitValue({ start: this.startDate, end: null });
7250
+ this.scheduleChangeDetection();
7251
+ }
7252
+ else if (this.startDate && this.endDate && dayTime > startTime && dayTime < endTime) {
7253
+ this.startDate = this.applyTimeIfNeeded(day);
7254
+ this.endDate = null;
7255
+ this.hoveredDate = null;
7256
+ this._invalidateMemoCache();
7257
+ this.emitValue({ start: this.startDate, end: null });
7258
+ this.scheduleChangeDetection();
7259
+ }
7260
+ else if (!this.startDate || (this.startDate && this.endDate)) {
7237
7261
  this.startDate = this.applyTimeIfNeeded(day);
7238
7262
  this.endDate = null;
7239
7263
  this.hoveredDate = null;
@@ -7249,7 +7273,7 @@ class NgxsmkDatepickerComponent {
7249
7273
  this.scheduleChangeDetection();
7250
7274
  }
7251
7275
  else if (dayTime === startTime) {
7252
- // No action needed when dayTime equals startTime
7276
+ // No action needed when dayTime equals startTime (start date clicked again, no end date selected yet)
7253
7277
  }
7254
7278
  else {
7255
7279
  const potentialEndDate = this.applyTimeIfNeeded(day);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngxsmk-datepicker",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "author": {
5
5
  "name": "Sachin Dilshan",
6
6
  "url": "https://www.linkedin.com/in/sachindilshan/"