@egose/shadcn-theme-ng-tw 0.6.0 → 0.6.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.
Files changed (50) hide show
  1. package/README.md +119 -1
  2. package/autocomplete/fesm2022/autocomplete.mjs +14 -4
  3. package/autocomplete/types/autocomplete.d.ts +4 -1
  4. package/checkbox/README.md +6 -2
  5. package/checkbox/fesm2022/checkbox.mjs +15 -9
  6. package/checkbox/types/checkbox.d.ts +6 -4
  7. package/combobox/fesm2022/combobox.mjs +22 -6
  8. package/combobox/types/combobox.d.ts +8 -2
  9. package/data-table/README.md +10 -0
  10. package/data-table/fesm2022/data-table.mjs +48 -12
  11. package/data-table/types/data-table.d.ts +16 -4
  12. package/date-picker/README.md +41 -9
  13. package/date-picker/fesm2022/date-picker.mjs +265 -59
  14. package/date-picker/types/date-picker.d.ts +58 -27
  15. package/form-autocomplete/README.md +4 -2
  16. package/form-autocomplete/fesm2022/form-autocomplete.mjs +33 -8
  17. package/form-autocomplete/types/form-autocomplete.d.ts +9 -3
  18. package/form-combobox/README.md +4 -2
  19. package/form-combobox/fesm2022/form-combobox.mjs +65 -14
  20. package/form-combobox/types/form-combobox.d.ts +10 -3
  21. package/form-input-otp/README.md +7 -5
  22. package/form-input-otp/fesm2022/form-input-otp.mjs +28 -14
  23. package/form-input-otp/types/form-input-otp.d.ts +9 -3
  24. package/form-searchable-multiselect/README.md +15 -1
  25. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +23 -3
  26. package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +9 -1
  27. package/form-slider/README.md +3 -1
  28. package/form-slider/fesm2022/form-slider.mjs +21 -6
  29. package/form-slider/types/form-slider.d.ts +9 -3
  30. package/form-toggle/README.md +22 -18
  31. package/form-toggle/fesm2022/form-toggle.mjs +25 -8
  32. package/form-toggle/types/form-toggle.d.ts +6 -2
  33. package/input-otp/README.md +33 -9
  34. package/input-otp/fesm2022/input-otp.mjs +127 -11
  35. package/input-otp/types/input-otp.d.ts +24 -4
  36. package/package.json +1 -1
  37. package/pagination/README.md +21 -12
  38. package/pagination/fesm2022/pagination.mjs +83 -75
  39. package/pagination/types/pagination.d.ts +21 -8
  40. package/phone-input/README.md +16 -0
  41. package/phone-input/fesm2022/phone-input.mjs +41 -3
  42. package/phone-input/types/phone-input.d.ts +5 -2
  43. package/searchable-multiselect/README.md +62 -40
  44. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +97 -36
  45. package/searchable-multiselect/types/searchable-multiselect.d.ts +23 -6
  46. package/slider/fesm2022/slider.mjs +15 -5
  47. package/slider/types/slider.d.ts +6 -2
  48. package/stepper/README.md +39 -19
  49. package/stepper/fesm2022/stepper.mjs +71 -17
  50. package/stepper/types/stepper.d.ts +12 -1
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, input, booleanAttribute, computed, ChangeDetectionStrategy, Component, forwardRef, viewChild, contentChild, linkedSignal, signal, output, ElementRef, effect, Directive, numberAttribute, untracked, NgModule } from '@angular/core';
2
+ import { InjectionToken, inject, signal, Injectable, linkedSignal, Directive, input, booleanAttribute, computed, ChangeDetectionStrategy, Component, forwardRef, viewChild, contentChild, output, ElementRef, effect, numberAttribute, untracked, NgModule } from '@angular/core';
3
3
  import { NgIcon, provideIcons } from '@ng-icons/core';
4
4
  import { lucideX, lucideCalendar, lucideChevronDown } from '@ng-icons/lucide';
5
5
  import { BrnDateInput, provideBrnDatePickerTrigger, BrnDatePickerTriggerToken, provideBrnDatePicker, injectBrnDatePicker } from '@spartan-ng/brain/date-picker';
@@ -10,6 +10,8 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms';
10
10
  import * as i1$1 from '@spartan-ng/brain/field';
11
11
  import { provideBrnLabelable, BrnFieldControl, BrnFieldControlDescribedBy } from '@spartan-ng/brain/field';
12
12
  import { BrnPopover } from '@spartan-ng/brain/popover';
13
+ import { injectDateAdapter } from '@spartan-ng/brain/date-time';
14
+ import { BrnCalendar, BrnCalendarMulti, BrnCalendarRange } from '@spartan-ng/brain/calendar';
13
15
  import * as i3 from '@egose/shadcn-theme-ng-tw/calendar';
14
16
  import { HlmCalendar, HlmCalendarMulti, HlmCalendarRange, HlmCalendarImports } from '@egose/shadcn-theme-ng-tw/calendar';
15
17
  import * as i2 from '@egose/shadcn-theme-ng-tw/popover';
@@ -68,7 +70,100 @@ function injectHlmDatePickerMultiConfig() {
68
70
  return injectedConfig ? injectedConfig : getDefaultConfig$3();
69
71
  }
70
72
 
71
- class HlmDateMultiInput extends BrnDateInput {
73
+ /** Internal synchronization for explicit writes, including writes of the same value. */
74
+ class HlmDatePickerCommitState {
75
+ revision = signal(0, /* @ts-ignore */
76
+ ...(ngDevMode ? [{ debugName: "revision" }] : /* istanbul ignore next */ []));
77
+ changed() {
78
+ this.revision.update((revision) => revision + 1);
79
+ }
80
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerCommitState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
81
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerCommitState });
82
+ }
83
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerCommitState, decorators: [{
84
+ type: Injectable
85
+ }] });
86
+ /** Match the calendar's inclusive whole-day bounds with the configured adapter. */
87
+ function isSelectableDate(adapter, value, min, max) {
88
+ return (value != null &&
89
+ Number.isFinite(adapter.getTime(value)) &&
90
+ (min == null || !adapter.isBefore(value, adapter.startOfDay(min))) &&
91
+ (max == null || !adapter.isAfter(value, adapter.endOfDay(max))));
92
+ }
93
+
94
+ /** Internal input lifecycle shared by the single, range and multi pickers. */
95
+ class HlmConstrainedDateInput extends BrnDateInput {
96
+ _commitState = inject(HlmDatePickerCommitState);
97
+ _inputValue = linkedSignal({ ...(ngDevMode ? { debugName: "_inputValue" } : /* istanbul ignore next */ {}), source: () => ({
98
+ revision: this._commitState.revision(),
99
+ formatted: this._datePicker.formattedDate(),
100
+ value: this._datePicker.value?.(),
101
+ inputValue: this.inputValue(),
102
+ }),
103
+ computation: (source, previous) => {
104
+ if (!previous)
105
+ return source.formatted ?? source.inputValue;
106
+ if (source.revision !== previous.source.revision ||
107
+ source.value !== previous.source.value ||
108
+ source.formatted !== previous.source.formatted)
109
+ return source.formatted ?? '';
110
+ if (source.inputValue !== previous.source.inputValue)
111
+ return source.inputValue;
112
+ return previous.value;
113
+ } });
114
+ /** Rejected text stays invalid until a successful commit, clear, or external value write. */
115
+ inputInvalid = linkedSignal(() => {
116
+ this._commitState.revision();
117
+ this._datePicker.value?.();
118
+ this.inputValue();
119
+ return false;
120
+ }, /* @ts-ignore */
121
+ ...(ngDevMode ? [{ debugName: "inputInvalid" }] : /* istanbul ignore next */ []));
122
+ _commitDate() {
123
+ if (this._disabled() || this.readonly())
124
+ return;
125
+ const text = this._inputValue();
126
+ const parsed = text ? this.parseValue(text) : null;
127
+ const picker = this._datePicker;
128
+ const accepted = (!text || parsed != null) && picker.updateDate(parsed);
129
+ this.inputInvalid.set(!accepted);
130
+ this._datePicker.touched?.();
131
+ }
132
+ _handleBlur() {
133
+ if (this._disabled() || this.readonly())
134
+ return;
135
+ this._commitDate();
136
+ if (!this.inputInvalid())
137
+ this._inputValue.set(this._datePicker.formattedDate() ?? '');
138
+ }
139
+ _handleEnter(event) {
140
+ event.preventDefault();
141
+ if (this._disabled() || this.readonly())
142
+ return;
143
+ this._commitDate();
144
+ if (!this.inputInvalid()) {
145
+ this._popover().close();
146
+ this._handleFocus();
147
+ }
148
+ }
149
+ _handleFocus() {
150
+ if (!this.inputInvalid())
151
+ super._handleFocus();
152
+ }
153
+ _clear() {
154
+ if (this._disabled() || this.readonly())
155
+ return;
156
+ this._inputValue.set('');
157
+ this._commitDate();
158
+ }
159
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmConstrainedDateInput, deps: null, target: i0.ɵɵFactoryTarget.Directive });
160
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmConstrainedDateInput, isStandalone: true, usesInheritance: true, ngImport: i0 });
161
+ }
162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmConstrainedDateInput, decorators: [{
163
+ type: Directive
164
+ }] });
165
+
166
+ class HlmDateMultiInput extends HlmConstrainedDateInput {
72
167
  _config = injectHlmDatePickerMultiConfig();
73
168
  /** Native `name` attribute forwarded to the inner `<input>`. */
74
169
  name = input(undefined, /* @ts-ignore */
@@ -91,9 +186,9 @@ class HlmDateMultiInput extends BrnDateInput {
91
186
  classes(() => [this.userClass()]);
92
187
  }
93
188
  /**
94
- * Parses input text into dates. Return `null` for invalid input - the
95
- * picker's dates are cleared while the text is preserved so the user can
96
- * fix it.
189
+ * Parses input text into dates. Return `null` for invalid input. Rejected
190
+ * text stays editable and aria-invalid; the committed value is preserved.
191
+ * Empty text explicitly clears on blur/Enter.
97
192
  *
98
193
  * Defaults to `parseDate` from `HlmDatePickerMultiConfig`.
99
194
  */
@@ -126,7 +221,8 @@ class HlmDateMultiInput extends BrnDateInput {
126
221
  [placeholder]="placeholder()"
127
222
  [readonly]="readonly()"
128
223
  [disabled]="_disabled()"
129
- [forceInvalid]="forceInvalid()"
224
+ [attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
225
+ [attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
130
226
  [class]="$inputClass()"
131
227
  (click)="_handleClick()"
132
228
  (keydown.arrowDown)="_open()"
@@ -180,7 +276,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
180
276
  [placeholder]="placeholder()"
181
277
  [readonly]="readonly()"
182
278
  [disabled]="_disabled()"
183
- [forceInvalid]="forceInvalid()"
279
+ [attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
280
+ [attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
184
281
  [class]="$inputClass()"
185
282
  (click)="_handleClick()"
186
283
  (keydown.arrowDown)="_open()"
@@ -244,6 +341,11 @@ const HLM_DATE_PICKER_VALUE_ACCESSOR = {
244
341
  };
245
342
  class HlmDatePicker {
246
343
  _config = injectHlmDatePickerConfig();
344
+ _dateAdapter = injectDateAdapter();
345
+ _commitState = inject(HlmDatePickerCommitState);
346
+ _calendar = viewChild((BrnCalendar), /* @ts-ignore */
347
+ ...(ngDevMode ? [{ debugName: "_calendar" }] : /* istanbul ignore next */ []));
348
+ _restoringCalendar = false;
247
349
  popover = viewChild.required(BrnPopover, /* @ts-ignore */
248
350
  ...(ngDevMode ? [{ debugName: "popover" }] : /* istanbul ignore next */ []));
249
351
  _trigger = contentChild(BrnDatePickerTriggerToken, /* @ts-ignore */
@@ -305,30 +407,46 @@ class HlmDatePicker {
305
407
  this._onTouched?.();
306
408
  }
307
409
  _handleChange(value) {
308
- if (this.disabledState())
410
+ if (this._restoringCalendar)
309
411
  return;
310
- this.updateDate(value ?? null);
412
+ if (!this.updateDate(value ?? null)) {
413
+ // Brain model signals have already changed before their output fires.
414
+ this._restoringCalendar = true;
415
+ try {
416
+ this._calendar()?.date.set(this._mutableDate());
417
+ }
418
+ finally {
419
+ this._restoringCalendar = false;
420
+ }
421
+ return;
422
+ }
311
423
  if (this.autoCloseOnSelect()) {
312
424
  this._popoverState.set('closed');
313
425
  }
314
426
  }
315
427
  /**
316
- * Commit a date to the picker. Updates the internal model, notifies form
317
- * controls, and emits `dateChange`. Unlike `_handleChange`, this does not
318
- * close the popover - it's intended to be called from a text input that
319
- * is parsing user-entered values while typing.
428
+ * Commit a user value (null clears). Returns false without changing/emitting
429
+ * the model when disabled or when the raw/transformed date is invalid or
430
+ * outside the adapter's inclusive whole-day min/max bounds.
320
431
  */
321
432
  updateDate(value) {
322
433
  if (this.disabledState())
323
- return;
434
+ return false;
435
+ if (value != null && !isSelectableDate(this._dateAdapter, value, this.min(), this.max()))
436
+ return false;
324
437
  const transformedDate = value != null ? this.transformDate()(value) : undefined;
438
+ if (value != null && !isSelectableDate(this._dateAdapter, transformedDate, this.min(), this.max()))
439
+ return false;
325
440
  this._mutableDate.set(transformedDate);
441
+ this._commitState.changed();
326
442
  this._onChange?.(transformedDate ?? null);
327
443
  this.dateChange.emit(transformedDate ?? null);
444
+ return true;
328
445
  }
329
- /** CONTROL VALUE ACCESSOR */
446
+ /** Programmatic CVA write: transforms without enforcing user constraints or emitting. Clears rejected text. */
330
447
  writeValue(value) {
331
- this._mutableDate.set(value ? this.transformDate()(value) : undefined);
448
+ this._mutableDate.set(value != null ? this.transformDate()(value) : undefined);
449
+ this._commitState.changed();
332
450
  }
333
451
  registerOnChange(fn) {
334
452
  this._onChange = fn;
@@ -350,11 +468,17 @@ class HlmDatePicker {
350
468
  }
351
469
  reset() {
352
470
  this._mutableDate.set(undefined);
471
+ this._commitState.changed();
353
472
  this._onChange?.(null);
354
473
  this.dateChange.emit(null);
355
474
  }
356
475
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
357
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmDatePicker, isStandalone: true, selector: "hlm-date-picker", inputs: { captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, wrapperDisabled: { classPropertyName: "wrapperDisabled", publicName: "wrapperDisabled", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, defaultFocusedDate: { classPropertyName: "defaultFocusedDate", publicName: "defaultFocusedDate", isSignal: true, isRequired: false, transformFunction: null }, autoCloseOnSelect: { classPropertyName: "autoCloseOnSelect", publicName: "autoCloseOnSelect", isSignal: true, isRequired: false, transformFunction: null }, formatDate: { classPropertyName: "formatDate", publicName: "formatDate", isSignal: true, isRequired: false, transformFunction: null }, transformDate: { classPropertyName: "transformDate", publicName: "transformDate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, host: { classAttribute: "tw:block tw:w-full tw:min-w-0 tw:max-w-full" }, providers: [HLM_DATE_PICKER_VALUE_ACCESSOR, provideBrnDatePicker(HlmDatePicker), provideBrnLabelable(HlmDatePicker)], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: `
476
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmDatePicker, isStandalone: true, selector: "hlm-date-picker", inputs: { captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, wrapperDisabled: { classPropertyName: "wrapperDisabled", publicName: "wrapperDisabled", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, defaultFocusedDate: { classPropertyName: "defaultFocusedDate", publicName: "defaultFocusedDate", isSignal: true, isRequired: false, transformFunction: null }, autoCloseOnSelect: { classPropertyName: "autoCloseOnSelect", publicName: "autoCloseOnSelect", isSignal: true, isRequired: false, transformFunction: null }, formatDate: { classPropertyName: "formatDate", publicName: "formatDate", isSignal: true, isRequired: false, transformFunction: null }, transformDate: { classPropertyName: "transformDate", publicName: "transformDate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, host: { classAttribute: "tw:block tw:w-full tw:min-w-0 tw:max-w-full" }, providers: [
477
+ HlmDatePickerCommitState,
478
+ HLM_DATE_PICKER_VALUE_ACCESSOR,
479
+ provideBrnDatePicker(HlmDatePicker),
480
+ provideBrnLabelable(HlmDatePicker),
481
+ ], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_calendar", first: true, predicate: (BrnCalendar), descendants: true, isSignal: true }, { propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: `
358
482
  <hlm-popover sideOffset="5" [state]="_popoverState()" (stateChanged)="_onStateChange($event)">
359
483
  <ng-content />
360
484
 
@@ -380,7 +504,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
380
504
  args: [{
381
505
  selector: 'hlm-date-picker',
382
506
  imports: [HlmPopoverImports, HlmCalendar],
383
- providers: [HLM_DATE_PICKER_VALUE_ACCESSOR, provideBrnDatePicker(HlmDatePicker), provideBrnLabelable(HlmDatePicker)],
507
+ providers: [
508
+ HlmDatePickerCommitState,
509
+ HLM_DATE_PICKER_VALUE_ACCESSOR,
510
+ provideBrnDatePicker(HlmDatePicker),
511
+ provideBrnLabelable(HlmDatePicker),
512
+ ],
384
513
  changeDetection: ChangeDetectionStrategy.OnPush,
385
514
  hostDirectives: [BrnFieldControl],
386
515
  host: { class: 'tw:block tw:w-full tw:min-w-0 tw:max-w-full' },
@@ -405,7 +534,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
405
534
  </hlm-popover>
406
535
  `,
407
536
  }]
408
- }], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], wrapperDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrapperDisabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], defaultFocusedDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultFocusedDate", required: false }] }], autoCloseOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnSelect", required: false }] }], formatDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDate", required: false }] }], transformDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDate", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
537
+ }], propDecorators: { _calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnCalendar), { isSignal: true }] }], popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], wrapperDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrapperDisabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], defaultFocusedDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultFocusedDate", required: false }] }], autoCloseOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnSelect", required: false }] }], formatDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDate", required: false }] }], transformDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDate", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
409
538
 
410
539
  class HlmDatePickerAnchor {
411
540
  _host = inject(ElementRef, { host: true });
@@ -427,7 +556,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
427
556
  args: [{ selector: '[hlmDatePickerAnchor]' }]
428
557
  }], ctorParameters: () => [], propDecorators: { hlmDatePickerAnchorForInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "hlmDatePickerAnchorFor", required: false }] }] } });
429
558
 
430
- class HlmDatePickerInput extends BrnDateInput {
559
+ class HlmDatePickerInput extends HlmConstrainedDateInput {
431
560
  _config = injectHlmDatePickerConfig();
432
561
  ariaLabel = input(undefined, /* @ts-ignore */
433
562
  ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
@@ -451,8 +580,8 @@ class HlmDatePickerInput extends BrnDateInput {
451
580
  }
452
581
  /**
453
582
  * Parses input text into a date value. Return `null` for invalid
454
- * input - the picker's date is cleared while the text is preserved so
455
- * the user can fix it.
583
+ * input. Rejected text stays editable and aria-invalid; the committed value
584
+ * is preserved. Empty text explicitly clears on blur/Enter.
456
585
  *
457
586
  * Defaults to `parseDate` from `HlmDatePickerConfig`.
458
587
  */
@@ -485,7 +614,8 @@ class HlmDatePickerInput extends BrnDateInput {
485
614
  [placeholder]="placeholder()"
486
615
  [readonly]="readonly()"
487
616
  [disabled]="_disabled()"
488
- [forceInvalid]="forceInvalid()"
617
+ [attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
618
+ [attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
489
619
  [class]="$inputClass()"
490
620
  (click)="_handleClick()"
491
621
  (keydown.arrowDown)="_open()"
@@ -539,7 +669,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
539
669
  [placeholder]="placeholder()"
540
670
  [readonly]="readonly()"
541
671
  [disabled]="_disabled()"
542
- [forceInvalid]="forceInvalid()"
672
+ [attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
673
+ [attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
543
674
  [class]="$inputClass()"
544
675
  (click)="_handleClick()"
545
676
  (keydown.arrowDown)="_open()"
@@ -582,6 +713,11 @@ const HLM_DATE_PICKER_MUTLI_VALUE_ACCESSOR = {
582
713
  };
583
714
  class HlmDatePickerMulti {
584
715
  _config = injectHlmDatePickerMultiConfig();
716
+ _dateAdapter = injectDateAdapter();
717
+ _commitState = inject(HlmDatePickerCommitState);
718
+ _calendar = viewChild((BrnCalendarMulti), /* @ts-ignore */
719
+ ...(ngDevMode ? [{ debugName: "_calendar" }] : /* istanbul ignore next */ []));
720
+ _restoringCalendar = false;
585
721
  popover = viewChild.required(BrnPopover, /* @ts-ignore */
586
722
  ...(ngDevMode ? [{ debugName: "popover" }] : /* istanbul ignore next */ []));
587
723
  _trigger = contentChild(BrnDatePickerTriggerToken, /* @ts-ignore */
@@ -595,7 +731,7 @@ class HlmDatePickerMulti {
595
731
  /** The maximum date that can be selected. */
596
732
  max = input(/* @ts-ignore */
597
733
  ...(ngDevMode ? [undefined, { debugName: "max" }] : /* istanbul ignore next */ []));
598
- /** The minimum selectable dates. */
734
+ /** Deselection floor; selection can grow from empty below this count. Explicit clear is allowed. */
599
735
  minSelection = input(undefined, { ...(ngDevMode ? { debugName: "minSelection" } : /* istanbul ignore next */ {}), transform: numberAttribute });
600
736
  /** The maximum selectable dates. */
601
737
  maxSelection = input(undefined, { ...(ngDevMode ? { debugName: "maxSelection" } : /* istanbul ignore next */ {}), transform: numberAttribute });
@@ -643,37 +779,58 @@ class HlmDatePickerMulti {
643
779
  this._onTouched?.();
644
780
  }
645
781
  _handleChange(value) {
646
- if (value === undefined)
782
+ if (this._restoringCalendar || value === undefined)
647
783
  return;
648
- if (this._disabled())
784
+ if (!this.updateDate(value)) {
785
+ // Restore the calendar's already-mutated model without a second user commit.
786
+ this._restoringCalendar = true;
787
+ try {
788
+ this._calendar()?.date.set(this._mutableDate());
789
+ }
790
+ finally {
791
+ this._restoringCalendar = false;
792
+ }
649
793
  return;
650
- const transformedDate = value !== undefined ? this.transformDates()(value) : value;
651
- this._mutableDate.set(transformedDate);
652
- this._onChange?.(transformedDate);
653
- this.dateChange.emit(transformedDate);
794
+ }
654
795
  if (this.autoCloseOnMaxSelection() && this._mutableDate()?.length === this.maxSelection()) {
655
796
  this._popoverState.set('closed');
656
797
  }
657
798
  }
658
799
  /**
659
- * Commit dates to the picker. Updates the internal model, notifies form
660
- * controls, and emits `dateChange`. Intended to be called from a text input
661
- * that parses user-entered values. Pass `null` to clear the selection.
800
+ * Commit user dates, validating raw and transformed dates/counts. Returns
801
+ * false without changing/emitting on rejection. Min selection prevents
802
+ * reductions below the floor, but permits growth from empty. Null explicitly
803
+ * clears (emits []), bypassing the selection floor and transform.
662
804
  */
663
805
  updateDate(value) {
664
806
  if (this._disabled())
665
- return;
807
+ return false;
808
+ if (value && !this._isSelectionAllowed(value))
809
+ return false;
666
810
  const transformedDate = value ? this.transformDates()(value) : undefined;
811
+ if (value && (!transformedDate || !this._isSelectionAllowed(transformedDate)))
812
+ return false;
667
813
  this._mutableDate.set(transformedDate);
814
+ this._commitState.changed();
668
815
  this._onChange?.(transformedDate ?? []);
669
816
  this.dateChange.emit(transformedDate ?? []);
817
+ return true;
818
+ }
819
+ _isSelectionAllowed(dates) {
820
+ const min = this.minSelection();
821
+ const max = this.maxSelection();
822
+ const currentCount = this._mutableDate()?.length ?? 0;
823
+ return (!(max != null && dates.length > max) &&
824
+ !(min != null && dates.length < min && dates.length < currentCount) &&
825
+ dates.every((date) => isSelectableDate(this._dateAdapter, date, this.min(), this.max())));
670
826
  }
671
827
  touched() {
672
828
  this._onTouched?.();
673
829
  }
674
- /** CONTROL VALUE ACCESSOR */
830
+ /** Programmatic CVA write: transforms without enforcing user constraints or emitting. Clears rejected text. */
675
831
  writeValue(value) {
676
832
  this._mutableDate.set(value ? this.transformDates()(value) : undefined);
833
+ this._commitState.changed();
677
834
  }
678
835
  registerOnChange(fn) {
679
836
  this._onChange = fn;
@@ -692,15 +849,17 @@ class HlmDatePickerMulti {
692
849
  }
693
850
  reset() {
694
851
  this._mutableDate.set(undefined);
852
+ this._commitState.changed();
695
853
  this._onChange?.([]);
696
854
  this.dateChange.emit([]);
697
855
  }
698
856
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerMulti, deps: [], target: i0.ɵɵFactoryTarget.Component });
699
857
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmDatePickerMulti, isStandalone: true, selector: "hlm-date-picker-multi", inputs: { captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, minSelection: { classPropertyName: "minSelection", publicName: "minSelection", isSignal: true, isRequired: false, transformFunction: null }, maxSelection: { classPropertyName: "maxSelection", publicName: "maxSelection", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, autoCloseOnMaxSelection: { classPropertyName: "autoCloseOnMaxSelection", publicName: "autoCloseOnMaxSelection", isSignal: true, isRequired: false, transformFunction: null }, formatDates: { classPropertyName: "formatDates", publicName: "formatDates", isSignal: true, isRequired: false, transformFunction: null }, transformDates: { classPropertyName: "transformDates", publicName: "transformDates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, host: { classAttribute: "block" }, providers: [
858
+ HlmDatePickerCommitState,
700
859
  HLM_DATE_PICKER_MUTLI_VALUE_ACCESSOR,
701
860
  provideBrnDatePicker(HlmDatePickerMulti),
702
861
  provideBrnLabelable(HlmDatePickerMulti),
703
- ], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: `
862
+ ], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_calendar", first: true, predicate: (BrnCalendarMulti), descendants: true, isSignal: true }, { propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: `
704
863
  <hlm-popover sideOffset="5" [state]="_popoverState()" (stateChanged)="_onStateChange($event)">
705
864
  <ng-content />
706
865
 
@@ -728,6 +887,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
728
887
  selector: 'hlm-date-picker-multi',
729
888
  imports: [HlmPopoverImports, HlmCalendarMulti],
730
889
  providers: [
890
+ HlmDatePickerCommitState,
731
891
  HLM_DATE_PICKER_MUTLI_VALUE_ACCESSOR,
732
892
  provideBrnDatePicker(HlmDatePickerMulti),
733
893
  provideBrnLabelable(HlmDatePickerMulti),
@@ -757,7 +917,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
757
917
  </hlm-popover>
758
918
  `,
759
919
  }]
760
- }], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], minSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelection", required: false }] }], maxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelection", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], autoCloseOnMaxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnMaxSelection", required: false }] }], formatDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDates", required: false }] }], transformDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDates", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
920
+ }], propDecorators: { _calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnCalendarMulti), { isSignal: true }] }], popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], minSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelection", required: false }] }], maxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelection", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], autoCloseOnMaxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnMaxSelection", required: false }] }], formatDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDates", required: false }] }], transformDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDates", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
761
921
 
762
922
  class HlmDatePickerTrigger {
763
923
  static _nextId = 0;
@@ -885,7 +1045,7 @@ function getDefaultConfig$1() {
885
1045
  if (isNaN(start.getTime()))
886
1046
  return null;
887
1047
  const end = parts.length === 2 ? new Date(parts[1]) : start;
888
- return [start, isNaN(end.getTime()) ? start : end];
1048
+ return isNaN(end.getTime()) ? null : [start, end];
889
1049
  },
890
1050
  };
891
1051
  }
@@ -898,7 +1058,7 @@ function injectHlmDateRangePickerConfig() {
898
1058
  return injectedConfig ? injectedConfig : getDefaultConfig$1();
899
1059
  }
900
1060
 
901
- class HlmDateRangeInput extends BrnDateInput {
1061
+ class HlmDateRangeInput extends HlmConstrainedDateInput {
902
1062
  _config = injectHlmDateRangePickerConfig();
903
1063
  /** Native `name` attribute forwarded to the inner `<input>`. */
904
1064
  name = input(undefined, /* @ts-ignore */
@@ -922,8 +1082,8 @@ class HlmDateRangeInput extends BrnDateInput {
922
1082
  }
923
1083
  /**
924
1084
  * Parses input text into a date range. Return `null` for invalid
925
- * input - the picker's range is cleared while the text is preserved so
926
- * the user can fix it.
1085
+ * input. Rejected text stays editable and aria-invalid; the committed value
1086
+ * is preserved. Empty text explicitly clears on blur/Enter.
927
1087
  *
928
1088
  * Defaults to `parseDate` from `HlmDateRangePickerConfig`.
929
1089
  */
@@ -956,7 +1116,8 @@ class HlmDateRangeInput extends BrnDateInput {
956
1116
  [placeholder]="placeholder()"
957
1117
  [readonly]="readonly()"
958
1118
  [disabled]="_disabled()"
959
- [forceInvalid]="forceInvalid()"
1119
+ [attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
1120
+ [attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
960
1121
  [class]="$inputClass()"
961
1122
  (click)="_handleClick()"
962
1123
  (keydown.arrowDown)="_open()"
@@ -1010,7 +1171,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
1010
1171
  [placeholder]="placeholder()"
1011
1172
  [readonly]="readonly()"
1012
1173
  [disabled]="_disabled()"
1013
- [forceInvalid]="forceInvalid()"
1174
+ [attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
1175
+ [attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
1014
1176
  [class]="$inputClass()"
1015
1177
  (click)="_handleClick()"
1016
1178
  (keydown.arrowDown)="_open()"
@@ -1053,6 +1215,11 @@ const HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR = {
1053
1215
  };
1054
1216
  class HlmDateRangePicker {
1055
1217
  _config = injectHlmDateRangePickerConfig();
1218
+ _dateAdapter = injectDateAdapter();
1219
+ _commitState = inject(HlmDatePickerCommitState);
1220
+ _calendar = viewChild((BrnCalendarRange), /* @ts-ignore */
1221
+ ...(ngDevMode ? [{ debugName: "_calendar" }] : /* istanbul ignore next */ []));
1222
+ _restoringCalendar = false;
1056
1223
  popover = viewChild.required(BrnPopover, /* @ts-ignore */
1057
1224
  ...(ngDevMode ? [{ debugName: "popover" }] : /* istanbul ignore next */ []));
1058
1225
  _trigger = contentChild(BrnDatePickerTriggerToken, /* @ts-ignore */
@@ -1117,50 +1284,85 @@ class HlmDateRangePicker {
1117
1284
  }
1118
1285
  }
1119
1286
  _handleStartDayChange(value) {
1287
+ if (this._restoringCalendar)
1288
+ return;
1289
+ if (this._disabled() || (value != null && !isSelectableDate(this._dateAdapter, value, this.min(), this.max()))) {
1290
+ this._restoreCalendar();
1291
+ return;
1292
+ }
1120
1293
  this._start.set(value);
1121
1294
  }
1122
1295
  _handleEndDateChange(value) {
1123
- this._end.set(value);
1124
- if (this._disabled())
1296
+ if (this._restoringCalendar)
1125
1297
  return;
1298
+ if (this._disabled()) {
1299
+ this._restoreCalendar();
1300
+ return;
1301
+ }
1302
+ if (value == null) {
1303
+ this._end.set(undefined);
1304
+ return;
1305
+ }
1126
1306
  const start = this._start();
1127
- if (start && value) {
1128
- const transformedDates = this.transformDates()([start, value]);
1129
- this._mutableDate.set(transformedDates);
1130
- this.dateChange.emit(transformedDates);
1131
- this._onChange?.(transformedDates);
1307
+ if (start != null) {
1308
+ if (!this.updateDate([start, value])) {
1309
+ this._restoreCalendar();
1310
+ return;
1311
+ }
1132
1312
  if (this.autoCloseOnEndSelection()) {
1133
1313
  this._popoverState.set('closed');
1134
1314
  }
1135
1315
  }
1136
1316
  }
1317
+ _restoreCalendar() {
1318
+ this._start.set(this._mutableDate()?.[0]);
1319
+ this._end.set(this._mutableDate()?.[1]);
1320
+ this._restoringCalendar = true;
1321
+ try {
1322
+ this._calendar()?.startDate.set(this._start());
1323
+ this._calendar()?.endDate.set(this._end());
1324
+ }
1325
+ finally {
1326
+ this._restoringCalendar = false;
1327
+ }
1328
+ }
1137
1329
  /**
1138
- * Commit a range to the picker. Updates the internal model, notifies form
1139
- * controls, and emits `dateChange`. Intended to be called from a text input
1140
- * that parses user-entered values. Pass `null` to clear the range.
1330
+ * Commit a user range (null clears). Both raw/transformed endpoints must
1331
+ * satisfy adapter whole-day bounds; the transformed range must be ordered.
1332
+ * Returns false without changing/emitting the model on rejection or disabled.
1141
1333
  */
1142
1334
  updateDate(value) {
1143
1335
  if (this._disabled())
1144
- return;
1336
+ return false;
1145
1337
  if (!value) {
1146
1338
  this._mutableDate.set(undefined);
1147
1339
  this._start.set(undefined);
1148
1340
  this._end.set(undefined);
1341
+ this._commitState.changed();
1149
1342
  this._onChange?.(null);
1150
1343
  this.dateChange.emit(null);
1151
- return;
1344
+ return true;
1152
1345
  }
1346
+ if (!this._isRangeAllowed(value))
1347
+ return false;
1153
1348
  const transformedDates = this.transformDates()(value);
1349
+ if (!this._isRangeAllowed(transformedDates) || this._dateAdapter.isAfter(transformedDates[0], transformedDates[1]))
1350
+ return false;
1154
1351
  this._mutableDate.set(transformedDates);
1155
1352
  this._start.set(transformedDates[0]);
1156
1353
  this._end.set(transformedDates[1]);
1354
+ this._commitState.changed();
1157
1355
  this._onChange?.(transformedDates);
1158
1356
  this.dateChange.emit(transformedDates);
1357
+ return true;
1358
+ }
1359
+ _isRangeAllowed(dates) {
1360
+ return (dates?.length === 2 && dates.every((date) => isSelectableDate(this._dateAdapter, date, this.min(), this.max())));
1159
1361
  }
1160
1362
  touched() {
1161
1363
  this._onTouched?.();
1162
1364
  }
1163
- /** CONTROL VALUE ACCESSOR */
1365
+ /** Programmatic CVA write: transforms without enforcing user constraints or emitting. Clears rejected text. */
1164
1366
  writeValue(value) {
1165
1367
  untracked(() => {
1166
1368
  if (!value) {
@@ -1169,6 +1371,7 @@ class HlmDateRangePicker {
1169
1371
  else {
1170
1372
  this._mutableDate.set(this.transformDates()(value));
1171
1373
  }
1374
+ this._commitState.changed();
1172
1375
  });
1173
1376
  }
1174
1377
  registerOnChange(fn) {
@@ -1190,6 +1393,7 @@ class HlmDateRangePicker {
1190
1393
  this._mutableDate.set(undefined);
1191
1394
  this._start.set(undefined);
1192
1395
  this._end.set(undefined);
1396
+ this._commitState.changed();
1193
1397
  this._onChange?.(null);
1194
1398
  this.dateChange.emit(null);
1195
1399
  }
@@ -1202,10 +1406,11 @@ class HlmDateRangePicker {
1202
1406
  }
1203
1407
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDateRangePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
1204
1408
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmDateRangePicker, isStandalone: true, selector: "hlm-date-range-picker", inputs: { captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, autoCloseOnEndSelection: { classPropertyName: "autoCloseOnEndSelection", publicName: "autoCloseOnEndSelection", isSignal: true, isRequired: false, transformFunction: null }, formatDates: { classPropertyName: "formatDates", publicName: "formatDates", isSignal: true, isRequired: false, transformFunction: null }, transformDates: { classPropertyName: "transformDates", publicName: "transformDates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, host: { classAttribute: "block" }, providers: [
1409
+ HlmDatePickerCommitState,
1205
1410
  HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR,
1206
1411
  provideBrnDatePicker(HlmDateRangePicker),
1207
1412
  provideBrnLabelable(HlmDateRangePicker),
1208
- ], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: `
1413
+ ], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_calendar", first: true, predicate: (BrnCalendarRange), descendants: true, isSignal: true }, { propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: `
1209
1414
  <hlm-popover sideOffset="5" [state]="_popoverState()" (stateChanged)="_onStateChange($event)">
1210
1415
  <ng-content />
1211
1416
 
@@ -1233,6 +1438,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
1233
1438
  selector: 'hlm-date-range-picker',
1234
1439
  imports: [HlmPopoverImports, HlmCalendarRange],
1235
1440
  providers: [
1441
+ HlmDatePickerCommitState,
1236
1442
  HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR,
1237
1443
  provideBrnDatePicker(HlmDateRangePicker),
1238
1444
  provideBrnLabelable(HlmDateRangePicker),
@@ -1262,7 +1468,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
1262
1468
  </hlm-popover>
1263
1469
  `,
1264
1470
  }]
1265
- }], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], autoCloseOnEndSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnEndSelection", required: false }] }], formatDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDates", required: false }] }], transformDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDates", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
1471
+ }], propDecorators: { _calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnCalendarRange), { isSignal: true }] }], popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], autoCloseOnEndSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnEndSelection", required: false }] }], formatDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDates", required: false }] }], transformDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDates", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
1266
1472
 
1267
1473
  const mmYYYY = (date) => {
1268
1474
  if (!(date instanceof Date))