@vsn-ux/ngx-gaia 0.12.1 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,6 +24,7 @@ Input directive for datepicker integration. Implements ControlValueAccessor and
24
24
  - `disabled: boolean` - Disabled state (default: false)
25
25
  - `min: any` - Minimum date constraint (default: null)
26
26
  - `max: any` - Maximum date constraint (default: null)
27
+ - `preserveRawValue: boolean` - Push raw string to model on invalid input instead of null; useful with signal forms where schema-based validators need to distinguish empty fields from format errors (default: false)
27
28
 
28
29
  ### Outputs
29
30
 
@@ -111,6 +112,7 @@ interface GaDatepickerStruct {
111
112
  - `provideGaDatepickerI18n(value)` - Configure i18n (accepts class, object, or factory)
112
113
  - `provideGaDatepickerParserFormatter(value)` - Configure parser/formatter (accepts class or factory)
113
114
  - `provideGaDatepickerValueAdapter<T>(value)` - Configure value adapter (accepts class)
115
+ - `provideGaDatepickerInputOptions(options)` - Configure datepicker input options globally (e.g. `{ preserveRawValue: true }`)
114
116
  - `extendGaDateParserFormatter(formats)` - Extend default date formats for additional locales
115
117
 
116
118
  ## Examples
@@ -146,6 +148,17 @@ Using native Date adapter:
146
148
  providers: [provideGaDatepickerValueAdapter(GaDatepickerNativeUtcValueAdapter)];
147
149
  ```
148
150
 
151
+ Preserve raw value for signal forms validation:
152
+
153
+ ```html
154
+ <input gaInput gaDatepickerInput [(ngModel)]="date" preserveRawValue />
155
+ ```
156
+
157
+ ```typescript
158
+ // Or enable globally
159
+ providers: [provideGaDatepickerInputOptions({ preserveRawValue: true })];
160
+ ```
161
+
149
162
  Custom i18n labels:
150
163
 
151
164
  ```typescript
@@ -1677,10 +1677,28 @@ function provideGaDatepickerParserFormatter(value) {
1677
1677
  : { provide: GaDatepickerParserFormatter, useValue: value };
1678
1678
  }
1679
1679
 
1680
+ const GA_DEFAULT_DATEPICKER_INPUT_OPTIONS = {
1681
+ preserveRawValue: false,
1682
+ };
1683
+ const GA_DATEPICKER_INPUT_OPTIONS = new InjectionToken('GA_DATEPICKER_INPUT_OPTIONS', {
1684
+ providedIn: 'root',
1685
+ factory: () => GA_DEFAULT_DATEPICKER_INPUT_OPTIONS,
1686
+ });
1687
+ function provideGaDatepickerInputOptions(options) {
1688
+ return {
1689
+ provide: GA_DATEPICKER_INPUT_OPTIONS,
1690
+ useValue: { ...GA_DEFAULT_DATEPICKER_INPUT_OPTIONS, ...options },
1691
+ };
1692
+ }
1693
+
1680
1694
  class GaDatepickerInputDirective {
1681
1695
  inputElRef = inject(ElementRef, { self: true });
1682
1696
  parserFormatter = inject(GaDatepickerParserFormatter);
1683
1697
  valueAdapter = inject(GaDatepickerValueAdapter);
1698
+ globalOptions = inject(GA_DATEPICKER_INPUT_OPTIONS);
1699
+ preserveRawValueInput = input(undefined, { ...(ngDevMode ? { debugName: "preserveRawValueInput" } : {}), alias: 'preserveRawValue',
1700
+ transform: booleanAttribute });
1701
+ preserveRawValue = computed(() => this.preserveRawValueInput() ?? this.globalOptions.preserveRawValue, ...(ngDevMode ? [{ debugName: "preserveRawValue" }] : []));
1684
1702
  // Native value control (alternative to Angular forms)
1685
1703
  valueInput = input(null, { ...(ngDevMode ? { debugName: "valueInput" } : {}), alias: 'value' });
1686
1704
  disabledInput = input(null, { ...(ngDevMode ? { debugName: "disabledInput" } : {}), alias: 'disabled',
@@ -1702,7 +1720,7 @@ class GaDatepickerInputDirective {
1702
1720
  this.valueInput(); // explicit call to track value input changes
1703
1721
  this.lastValueValid.set(true);
1704
1722
  untracked(() => {
1705
- this.lastDateChangeEmittedValue.set(this.dateStruct());
1723
+ this.lastDateChangeEmittedValue.set(this.value());
1706
1724
  this.formatValue();
1707
1725
  });
1708
1726
  });
@@ -1714,35 +1732,54 @@ class GaDatepickerInputDirective {
1714
1732
  const target = event.target;
1715
1733
  // Parse the input value
1716
1734
  const parsedStruct = this.parserFormatter.parse(target.value);
1717
- const newValue = this.valueAdapter.fromStruct(parsedStruct);
1718
- this.lastValueValid.set(!target.value || parsedStruct !== null);
1719
- // Only update if the parsed value is different from current value
1720
- if (compareStructs(parsedStruct, this.dateStruct()) !== 0) {
1721
- this.value.set(newValue);
1722
- this.dateInput.emit(newValue);
1735
+ const isValid = !target.value || parsedStruct !== null;
1736
+ this.lastValueValid.set(isValid);
1737
+ if (isValid || !this.preserveRawValue()) {
1738
+ // Existing behavior: convert struct to external value
1739
+ const newValue = this.valueAdapter.fromStruct(parsedStruct);
1740
+ if (compareStructs(parsedStruct, this.dateStruct()) !== 0) {
1741
+ this.value.set(newValue);
1742
+ this.dateInput.emit(newValue);
1743
+ }
1744
+ this.onNgChangeFn?.(newValue);
1745
+ }
1746
+ else {
1747
+ // preserveRawValue ON + invalid input: push raw string
1748
+ this.value.set(target.value);
1749
+ this.dateInput.emit(target.value);
1750
+ this.onNgChangeFn?.(target.value);
1723
1751
  }
1724
- this.onNgChangeFn?.(newValue);
1725
1752
  }
1726
1753
  onBlur() {
1727
1754
  this.focused = false;
1728
- if (this.dateStruct()) {
1755
+ if (this.lastValueValid() && this.dateStruct()) {
1729
1756
  this.formatValue();
1730
1757
  }
1731
- if (compareStructs(this.dateStruct(), this.lastDateChangeEmittedValue()) !== 0) {
1758
+ const changed = this.preserveRawValue() && !this.lastValueValid()
1759
+ ? this.value() !== this.lastDateChangeEmittedValue()
1760
+ : compareStructs(this.dateStruct(), this.valueAdapter.toStruct(this.lastDateChangeEmittedValue())) !== 0;
1761
+ if (changed) {
1732
1762
  this.dateChange.emit(this.value());
1733
- this.lastDateChangeEmittedValue.set(this.dateStruct());
1763
+ this.lastDateChangeEmittedValue.set(this.value());
1734
1764
  }
1735
1765
  this.onNgTouchedFn?.();
1736
1766
  }
1737
1767
  formatValue() {
1738
- const value = this.dateStruct();
1739
- const formattedValue = this.parserFormatter.format(value);
1740
- this.inputElRef.nativeElement.value = formattedValue;
1768
+ const struct = this.dateStruct();
1769
+ if (struct) {
1770
+ this.inputElRef.nativeElement.value = this.parserFormatter.format(struct);
1771
+ }
1772
+ else if (this.preserveRawValue() && typeof this.value() === 'string') {
1773
+ this.inputElRef.nativeElement.value = this.value();
1774
+ }
1775
+ else {
1776
+ this.inputElRef.nativeElement.value = this.parserFormatter.format(null);
1777
+ }
1741
1778
  }
1742
1779
  updateValue(value, { updateView, emitToNgModel, } = {}) {
1743
1780
  this.value.set(value);
1744
1781
  this.lastValueValid.set(true);
1745
- this.lastDateChangeEmittedValue.set(this.dateStruct());
1782
+ this.lastDateChangeEmittedValue.set(value);
1746
1783
  if (updateView) {
1747
1784
  this.formatValue();
1748
1785
  }
@@ -1791,7 +1828,7 @@ class GaDatepickerInputDirective {
1791
1828
  return null;
1792
1829
  }
1793
1830
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: GaDatepickerInputDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1794
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.0", type: GaDatepickerInputDirective, isStandalone: true, selector: "input[gaDatepickerInput]", inputs: { valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", 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 } }, outputs: { dateInput: "dateInput", dateChange: "dateChange" }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()", "input": "onInput($event)" }, properties: { "disabled": "disabled()" } }, providers: [
1831
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.0", type: GaDatepickerInputDirective, isStandalone: true, selector: "input[gaDatepickerInput]", inputs: { preserveRawValueInput: { classPropertyName: "preserveRawValueInput", publicName: "preserveRawValue", isSignal: true, isRequired: false, transformFunction: null }, valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", 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 } }, outputs: { dateInput: "dateInput", dateChange: "dateChange" }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()", "input": "onInput($event)" }, properties: { "disabled": "disabled()" } }, providers: [
1795
1832
  {
1796
1833
  provide: NG_VALUE_ACCESSOR,
1797
1834
  useExisting: forwardRef(() => GaDatepickerInputDirective),
@@ -1828,7 +1865,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
1828
1865
  '(input)': 'onInput($event)',
1829
1866
  },
1830
1867
  }]
1831
- }], ctorParameters: () => [], propDecorators: { valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateInput: [{ type: i0.Output, args: ["dateInput"] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
1868
+ }], ctorParameters: () => [], propDecorators: { preserveRawValueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "preserveRawValue", required: false }] }], valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateInput: [{ type: i0.Output, args: ["dateInput"] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
1832
1869
 
1833
1870
  class GaDatepickerModule {
1834
1871
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: GaDatepickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -1862,7 +1899,7 @@ class GaDatepickerNativeUtcValueAdapter extends GaDatepickerValueAdapter {
1862
1899
  * Uses UTC to avoid timezone issues and normalizes to midnight
1863
1900
  */
1864
1901
  toStruct(value) {
1865
- if (!value)
1902
+ if (!value || !(value instanceof Date))
1866
1903
  return null;
1867
1904
  // Create UTC date at midnight to avoid timezone issues
1868
1905
  const utcDate = new Date(Date.UTC(value.getFullYear(), value.getMonth(), value.getDate()));
@@ -1894,8 +1931,9 @@ class GaDatepickerNativeUtcIsoValueAdapter extends GaDatepickerValueAdapter {
1894
1931
  * Converts ISO Date to internal struct representation
1895
1932
  * Uses UTC to avoid timezone issues and normalizes to midnight
1896
1933
  */
1934
+ isoDatePattern = /^\d{4}-\d{2}-\d{2}/;
1897
1935
  toStruct(value) {
1898
- if (!value)
1936
+ if (!value || !this.isoDatePattern.test(value))
1899
1937
  return null;
1900
1938
  const date = new Date(value);
1901
1939
  if (isNaN(date.getTime())) {
@@ -6498,5 +6536,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
6498
6536
  * Generated bundle index. Do not edit.
6499
6537
  */
6500
6538
 
6501
- export { CHECKBOX_CONTROL_VALUE_ACCESSOR, DEFAULT_MODAL_OPTIONS, GA_ALERT_I18N_FACTORY, GA_BASE_FONT_SIZE, GA_BUTTON_I18N_FACTORY, GA_CHECKBOX_REQUIRED_VALIDATOR, GA_DATA_SELECT_I18N_FACTORY, GA_DATA_SELECT_REQUIRED_VALIDATOR, GA_DATEPICKER_I18N_FACTORY, GA_DATEPICKER_PARSER_FORMATTER_FACTORY, GA_DATEPICKER_VALUE_ADAPTER_FACTORY, GA_DATE_PARSER_FORMATTER_CONFIG, GA_DEFAULT_DATEPICKER_FORMATS, GA_DEFAULT_TOAST_OPTIONS, GA_FORM_CONTROL_ADAPTER, GA_FORM_ERRORS, GA_ICON_DEFAULT_SIZE, GA_MODAL_DATA, GA_MODAL_I18N_FACTORY, GA_SELECT_I18N_FACTORY, GA_SELECT_REQUIRED_VALIDATOR, GA_TABS_I18N_FACTORY, GA_TOAST_OPTIONS, GA_TOOLTIP_DEFAULT_OFFSET, GaAlertComponent, GaAlertI18n, GaAlertI18nDefault, GaAlertModule, GaAlertTitleActionsComponent, GaAlertTitleComponent, GaBadgeComponent, GaBadgeModule, GaButtonDirective, GaButtonI18n, GaButtonI18nDefault, GaButtonModule, GaCardComponent, GaCardModule, GaCheckboxComponent, GaCheckboxModule, GaCheckboxRequiredValidator, GaChipComponent, GaChipListboxComponent, GaChipModule, GaDataSelectComponent, GaDataSelectI18n, GaDataSelectI18nDefault, GaDataSelectModule, GaDataSelectOptgroupLabelDirective, GaDataSelectOptionLabelDirective, GaDataSelectRequiredValidator, GaDataSelectValueDirective, GaDatepickerComponent, GaDatepickerI18n, GaDatepickerI18nDefault, GaDatepickerInputDirective, GaDatepickerModule, GaDatepickerNativeUtcIsoValueAdapter, GaDatepickerNativeUtcValueAdapter, GaDatepickerParserFormatter, GaDatepickerParserFormatterDefault, GaDatepickerStructValueAdapter, GaDatepickerToggleComponent, GaDatepickerValueAdapter, GaFieldErrorDirective, GaFieldInfoComponent, GaFieldLabelComponent, GaFormControlDirective, GaFormControlErrorsDirective, GaFormFieldComponent, GaFormFieldConnector, GaFormFieldModule, GaIconButtonDirective, GaIconComponent, GaIconModule, GaInputComponent, GaInputDirective, GaInputModule, GaLabelledByFormFieldDirective, GaLinkDirective, GaLinkModule, GaMenuComponent, GaMenuItemComponent, GaMenuModule, GaMenuSeparatorComponent, GaMenuTitleComponent, GaMenuTriggerDirective, GaMenuTriggerIconComponent, GaModalActionsComponent, GaModalCloseDirective, GaModalComponent, GaModalContentComponent, GaModalDescriptionComponent, GaModalDescriptionDirective, GaModalHeaderComponent, GaModalI18n, GaModalI18nDefault, GaModalLabelDirective, GaModalModule, GaModalOptions, GaModalRef, GaModalService, GaModalTitleDirective, GaOptgroupComponent, GaOptionComponent, GaRadioButtonComponent, GaRadioGroupComponent, GaRadioModule, GaSegmentedControlButtonDirective, GaSegmentedControlComponent, GaSegmentedControlIconButtonComponent, GaSegmentedControlModule, GaSegmentedControlTextButtonComponent, GaSelectComponent, GaSelectDropdownComponent, GaSelectDropdownSpinnerComponent, GaSelectI18n, GaSelectI18nDefault, GaSelectModule, GaSelectRequiredValidator, GaSelectValueComponent, GaSpinnerComponent, GaSpinnerModule, GaStepComponent, GaStepperComponent, GaStepperModule, GaStepperPanelDirective, GaSwitchComponent, GaSwitchModule, GaTabComponent, GaTabContentDirective, GaTabsComponent, GaTabsI18n, GaTabsI18nDefault, GaTabsModule, GaTextAreaDirective, GaTextAreaModule, GaToastComponent, GaToaster, GaTooltipComponent, GaTooltipDirective, GaTooltipModule, GaTooltipTitleComponent, RADIO_CONTROL_VALUE_ACCESSOR, SWITCH_CONTROL_VALUE_ACCESSOR, compareStructs, extendGaDateParserFormatter, injectNgControlState, provideGaAlertI18n, provideGaBaseFontSize, provideGaButtonI18n, provideGaDataSelectI18n, provideGaDatepickerI18n, provideGaDatepickerParserFormatter, provideGaDatepickerValueAdapter, provideGaFormErrors, provideGaModalI18n, provideGaModalOptions, provideGaSelectI18n, provideGaTabsI18n, provideGaToastOptions };
6539
+ export { CHECKBOX_CONTROL_VALUE_ACCESSOR, DEFAULT_MODAL_OPTIONS, GA_ALERT_I18N_FACTORY, GA_BASE_FONT_SIZE, GA_BUTTON_I18N_FACTORY, GA_CHECKBOX_REQUIRED_VALIDATOR, GA_DATA_SELECT_I18N_FACTORY, GA_DATA_SELECT_REQUIRED_VALIDATOR, GA_DATEPICKER_I18N_FACTORY, GA_DATEPICKER_INPUT_OPTIONS, GA_DATEPICKER_PARSER_FORMATTER_FACTORY, GA_DATEPICKER_VALUE_ADAPTER_FACTORY, GA_DATE_PARSER_FORMATTER_CONFIG, GA_DEFAULT_DATEPICKER_FORMATS, GA_DEFAULT_DATEPICKER_INPUT_OPTIONS, GA_DEFAULT_TOAST_OPTIONS, GA_FORM_CONTROL_ADAPTER, GA_FORM_ERRORS, GA_ICON_DEFAULT_SIZE, GA_MODAL_DATA, GA_MODAL_I18N_FACTORY, GA_SELECT_I18N_FACTORY, GA_SELECT_REQUIRED_VALIDATOR, GA_TABS_I18N_FACTORY, GA_TOAST_OPTIONS, GA_TOOLTIP_DEFAULT_OFFSET, GaAlertComponent, GaAlertI18n, GaAlertI18nDefault, GaAlertModule, GaAlertTitleActionsComponent, GaAlertTitleComponent, GaBadgeComponent, GaBadgeModule, GaButtonDirective, GaButtonI18n, GaButtonI18nDefault, GaButtonModule, GaCardComponent, GaCardModule, GaCheckboxComponent, GaCheckboxModule, GaCheckboxRequiredValidator, GaChipComponent, GaChipListboxComponent, GaChipModule, GaDataSelectComponent, GaDataSelectI18n, GaDataSelectI18nDefault, GaDataSelectModule, GaDataSelectOptgroupLabelDirective, GaDataSelectOptionLabelDirective, GaDataSelectRequiredValidator, GaDataSelectValueDirective, GaDatepickerComponent, GaDatepickerI18n, GaDatepickerI18nDefault, GaDatepickerInputDirective, GaDatepickerModule, GaDatepickerNativeUtcIsoValueAdapter, GaDatepickerNativeUtcValueAdapter, GaDatepickerParserFormatter, GaDatepickerParserFormatterDefault, GaDatepickerStructValueAdapter, GaDatepickerToggleComponent, GaDatepickerValueAdapter, GaFieldErrorDirective, GaFieldInfoComponent, GaFieldLabelComponent, GaFormControlDirective, GaFormControlErrorsDirective, GaFormFieldComponent, GaFormFieldConnector, GaFormFieldModule, GaIconButtonDirective, GaIconComponent, GaIconModule, GaInputComponent, GaInputDirective, GaInputModule, GaLabelledByFormFieldDirective, GaLinkDirective, GaLinkModule, GaMenuComponent, GaMenuItemComponent, GaMenuModule, GaMenuSeparatorComponent, GaMenuTitleComponent, GaMenuTriggerDirective, GaMenuTriggerIconComponent, GaModalActionsComponent, GaModalCloseDirective, GaModalComponent, GaModalContentComponent, GaModalDescriptionComponent, GaModalDescriptionDirective, GaModalHeaderComponent, GaModalI18n, GaModalI18nDefault, GaModalLabelDirective, GaModalModule, GaModalOptions, GaModalRef, GaModalService, GaModalTitleDirective, GaOptgroupComponent, GaOptionComponent, GaRadioButtonComponent, GaRadioGroupComponent, GaRadioModule, GaSegmentedControlButtonDirective, GaSegmentedControlComponent, GaSegmentedControlIconButtonComponent, GaSegmentedControlModule, GaSegmentedControlTextButtonComponent, GaSelectComponent, GaSelectDropdownComponent, GaSelectDropdownSpinnerComponent, GaSelectI18n, GaSelectI18nDefault, GaSelectModule, GaSelectRequiredValidator, GaSelectValueComponent, GaSpinnerComponent, GaSpinnerModule, GaStepComponent, GaStepperComponent, GaStepperModule, GaStepperPanelDirective, GaSwitchComponent, GaSwitchModule, GaTabComponent, GaTabContentDirective, GaTabsComponent, GaTabsI18n, GaTabsI18nDefault, GaTabsModule, GaTextAreaDirective, GaTextAreaModule, GaToastComponent, GaToaster, GaTooltipComponent, GaTooltipDirective, GaTooltipModule, GaTooltipTitleComponent, RADIO_CONTROL_VALUE_ACCESSOR, SWITCH_CONTROL_VALUE_ACCESSOR, compareStructs, extendGaDateParserFormatter, injectNgControlState, provideGaAlertI18n, provideGaBaseFontSize, provideGaButtonI18n, provideGaDataSelectI18n, provideGaDatepickerI18n, provideGaDatepickerInputOptions, provideGaDatepickerParserFormatter, provideGaDatepickerValueAdapter, provideGaFormErrors, provideGaModalI18n, provideGaModalOptions, provideGaSelectI18n, provideGaTabsI18n, provideGaToastOptions };
6502
6540
  //# sourceMappingURL=vsn-ux-ngx-gaia.mjs.map