@egose/shadcn-theme-ng-tw 0.3.0 → 0.4.0

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 (63) hide show
  1. package/form-autocomplete/README.md +20 -19
  2. package/form-autocomplete/fesm2022/form-autocomplete.mjs +41 -9
  3. package/form-autocomplete/types/form-autocomplete.d.ts +21 -1
  4. package/form-checkbox/README.md +18 -17
  5. package/form-checkbox/fesm2022/form-checkbox.mjs +42 -15
  6. package/form-checkbox/types/form-checkbox.d.ts +21 -1
  7. package/form-combobox/README.md +21 -20
  8. package/form-combobox/fesm2022/form-combobox.mjs +41 -9
  9. package/form-combobox/types/form-combobox.d.ts +21 -1
  10. package/form-date-picker/README.md +28 -27
  11. package/form-date-picker/fesm2022/form-date-picker.mjs +42 -15
  12. package/form-date-picker/types/form-date-picker.d.ts +21 -1
  13. package/form-date-picker-multi/README.md +28 -27
  14. package/form-date-picker-multi/fesm2022/form-date-picker-multi.mjs +42 -15
  15. package/form-date-picker-multi/types/form-date-picker-multi.d.ts +21 -1
  16. package/form-date-range-picker/README.md +28 -27
  17. package/form-date-range-picker/fesm2022/form-date-range-picker.mjs +42 -15
  18. package/form-date-range-picker/types/form-date-range-picker.d.ts +21 -1
  19. package/form-field/README.md +9 -0
  20. package/form-field/fesm2022/form-field.mjs +80 -5
  21. package/form-field/types/form-field.d.ts +50 -2
  22. package/form-field-simple/fesm2022/form-field-simple.mjs +15 -1
  23. package/form-field-simple/types/form-field-simple.d.ts +9 -2
  24. package/form-input-otp/README.md +17 -16
  25. package/form-input-otp/fesm2022/form-input-otp.mjs +41 -9
  26. package/form-input-otp/types/form-input-otp.d.ts +21 -1
  27. package/form-month-year-picker/README.md +26 -25
  28. package/form-month-year-picker/fesm2022/form-month-year-picker.mjs +42 -15
  29. package/form-month-year-picker/types/form-month-year-picker.d.ts +21 -1
  30. package/form-native-select/README.md +18 -17
  31. package/form-native-select/fesm2022/form-native-select.mjs +56 -17
  32. package/form-native-select/types/form-native-select.d.ts +21 -1
  33. package/form-phone-input/README.md +23 -22
  34. package/form-phone-input/fesm2022/form-phone-input.mjs +42 -15
  35. package/form-phone-input/types/form-phone-input.d.ts +21 -1
  36. package/form-radio-group/README.md +18 -17
  37. package/form-radio-group/fesm2022/form-radio-group.mjs +42 -15
  38. package/form-radio-group/types/form-radio-group.d.ts +21 -1
  39. package/form-searchable-multiselect/README.md +18 -17
  40. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +42 -15
  41. package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +21 -1
  42. package/form-select/README.md +20 -19
  43. package/form-select/fesm2022/form-select.mjs +42 -15
  44. package/form-select/types/form-select.d.ts +21 -1
  45. package/form-slider/README.md +19 -18
  46. package/form-slider/fesm2022/form-slider.mjs +41 -9
  47. package/form-slider/types/form-slider.d.ts +21 -1
  48. package/form-switch/README.md +16 -15
  49. package/form-switch/fesm2022/form-switch.mjs +42 -15
  50. package/form-switch/types/form-switch.d.ts +21 -1
  51. package/form-text-input/README.md +27 -26
  52. package/form-text-input/fesm2022/form-text-input.mjs +42 -15
  53. package/form-text-input/types/form-text-input.d.ts +21 -1
  54. package/form-textarea/README.md +23 -22
  55. package/form-textarea/fesm2022/form-textarea.mjs +42 -15
  56. package/form-textarea/types/form-textarea.d.ts +21 -1
  57. package/form-toggle/README.md +17 -16
  58. package/form-toggle/fesm2022/form-toggle.mjs +41 -7
  59. package/form-toggle/types/form-toggle.d.ts +21 -3
  60. package/form-toggle-group/README.md +20 -19
  61. package/form-toggle-group/fesm2022/form-toggle-group.mjs +42 -15
  62. package/form-toggle-group/types/form-toggle-group.d.ts +21 -1
  63. package/package.json +1 -1
@@ -2,13 +2,14 @@ import * as i0 from '@angular/core';
2
2
  import { inject, input, computed, Component } from '@angular/core';
3
3
  import * as i1 from '@angular/forms';
4
4
  import { FormGroupDirective, ReactiveFormsModule, ControlContainer } from '@angular/forms';
5
- import { HlmFormIdGenerator, HlmFormField, HlmError, HlmHint } from '@egose/shadcn-theme-ng-tw/form-field';
5
+ import { injectEgFormErrorMessages, HlmFormIdGenerator, resolveEgFormError, HlmFormField, HlmError, HlmHint } from '@egose/shadcn-theme-ng-tw/form-field';
6
6
  import { HlmLabel } from '@egose/shadcn-theme-ng-tw/label';
7
7
  import { injectHlmMonthYearPickerConfig, HlmMonthYearPicker, HlmMonthYearInput } from '@egose/shadcn-theme-ng-tw/date-picker';
8
8
  import { hlm } from '@egose/shadcn-theme-ng-tw/utils';
9
9
 
10
10
  class EgFormMonthYearPicker {
11
11
  formGroupDirective = inject(FormGroupDirective);
12
+ _errorMessages = injectEgFormErrorMessages();
12
13
  generatedId = inject(HlmFormIdGenerator).generate('eg-form-month-year-picker');
13
14
  _config = injectHlmMonthYearPickerConfig();
14
15
  label = input(undefined, /* @ts-ignore */
@@ -19,6 +20,13 @@ class EgFormMonthYearPicker {
19
20
  ...(ngDevMode ? [{ debugName: "controlName" }] : /* istanbul ignore next */ []));
20
21
  error = input(undefined, /* @ts-ignore */
21
22
  ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
23
+ /**
24
+ * Auto-resolve the displayed message from the control's `ValidationErrors`
25
+ * when `error()` is unset. Explicit `error()` always wins. Set to `false`
26
+ * for manual-only messages.
27
+ */
28
+ autoError = input(true, /* @ts-ignore */
29
+ ...(ngDevMode ? [{ debugName: "autoError" }] : /* istanbul ignore next */ []));
22
30
  hint = input(undefined, /* @ts-ignore */
23
31
  ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
24
32
  id = input(undefined, /* @ts-ignore */
@@ -54,6 +62,32 @@ class EgFormMonthYearPicker {
54
62
  ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
55
63
  hintId = computed(() => `${this.effectiveId()}-hint`, /* @ts-ignore */
56
64
  ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
65
+ /**
66
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
67
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
68
+ * computed): `ValidationErrors` is not a signal, so the control must be read
69
+ * fresh on every change-detection pass.
70
+ */
71
+ resolvedError() {
72
+ const explicit = this.error();
73
+ if (explicit)
74
+ return explicit;
75
+ if (!this.autoError())
76
+ return undefined;
77
+ const control = this.formGroupDirective.form.get(this.controlName());
78
+ return resolveEgFormError(control?.errors ?? null, this.label(), this._errorMessages);
79
+ }
80
+ /**
81
+ * Whether the error is surfaced: message present + control invalid +
82
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
83
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
84
+ */
85
+ showError() {
86
+ const control = this.formGroupDirective.form.get(this.controlName());
87
+ return (!!this.resolvedError() &&
88
+ !!control?.invalid &&
89
+ (control.dirty || control.touched || this.formGroupDirective.submitted));
90
+ }
57
91
  /**
58
92
  * Bounds projected onto the picker's `Date` model. The cast keeps the
59
93
  * template's generic inference on `Date` while passing runtime values
@@ -64,12 +98,7 @@ class EgFormMonthYearPicker {
64
98
  $max = computed(() => this.max(), /* @ts-ignore */
65
99
  ...(ngDevMode ? [{ debugName: "$max" }] : /* istanbul ignore next */ []));
66
100
  describedBy() {
67
- const control = this.formGroupDirective.form.get(this.controlName());
68
- return this.error() && control?.invalid && (control.dirty || control.touched)
69
- ? this.errorId()
70
- : this.hint()
71
- ? this.hintId()
72
- : null;
101
+ return this.showError() ? this.errorId() : this.hint() ? this.hintId() : null;
73
102
  }
74
103
  // Styling
75
104
  userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
@@ -97,10 +126,9 @@ class EgFormMonthYearPicker {
97
126
  $hintClass = computed(() => hlm('tw:mt-0', this._config.hintClass, this.hintClass()), /* @ts-ignore */
98
127
  ...(ngDevMode ? [{ debugName: "$hintClass" }] : /* istanbul ignore next */ []));
99
128
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormMonthYearPicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
100
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormMonthYearPicker, isStandalone: true, selector: "eg-form-month-year-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", 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 }, 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 }, parseDate: { classPropertyName: "parseDate", publicName: "parseDate", isSignal: true, isRequired: false, transformFunction: null }, formatInputDate: { classPropertyName: "formatInputDate", publicName: "formatInputDate", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", isSignal: true, isRequired: false, transformFunction: null }, pickerClass: { classPropertyName: "pickerClass", publicName: "pickerClass", isSignal: true, isRequired: false, transformFunction: null }, inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null }, errorClass: { classPropertyName: "errorClass", publicName: "errorClass", isSignal: true, isRequired: false, transformFunction: null }, hintClass: { classPropertyName: "hintClass", publicName: "hintClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "$userClass()" } }, providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }], ngImport: i0, template: `
129
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormMonthYearPicker, isStandalone: true, selector: "eg-form-month-year-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, autoError: { classPropertyName: "autoError", publicName: "autoError", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", 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 }, 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 }, parseDate: { classPropertyName: "parseDate", publicName: "parseDate", isSignal: true, isRequired: false, transformFunction: null }, formatInputDate: { classPropertyName: "formatInputDate", publicName: "formatInputDate", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", isSignal: true, isRequired: false, transformFunction: null }, pickerClass: { classPropertyName: "pickerClass", publicName: "pickerClass", isSignal: true, isRequired: false, transformFunction: null }, inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null }, errorClass: { classPropertyName: "errorClass", publicName: "errorClass", isSignal: true, isRequired: false, transformFunction: null }, hintClass: { classPropertyName: "hintClass", publicName: "hintClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "$userClass()" } }, providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }], ngImport: i0, template: `
101
130
  @let lbl = label();
102
131
  @let cnm = controlName();
103
- @let err = error();
104
132
  @let hnt = hint();
105
133
  @let rqrd = required();
106
134
 
@@ -137,9 +165,9 @@ class EgFormMonthYearPicker {
137
165
  />
138
166
  </hlm-month-year-picker>
139
167
 
140
- @if (err) {
168
+ @if (showError()) {
141
169
  <hlm-error [id]="errorId()" [class]="$errorClass()">
142
- {{ err }}
170
+ {{ resolvedError() }}
143
171
  </hlm-error>
144
172
  }
145
173
 
@@ -164,7 +192,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
164
192
  template: `
165
193
  @let lbl = label();
166
194
  @let cnm = controlName();
167
- @let err = error();
168
195
  @let hnt = hint();
169
196
  @let rqrd = required();
170
197
 
@@ -201,9 +228,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
201
228
  />
202
229
  </hlm-month-year-picker>
203
230
 
204
- @if (err) {
231
+ @if (showError()) {
205
232
  <hlm-error [id]="errorId()" [class]="$errorClass()">
206
- {{ err }}
233
+ {{ resolvedError() }}
207
234
  </hlm-error>
208
235
  }
209
236
 
@@ -215,7 +242,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
215
242
  </hlm-form-field>
216
243
  `,
217
244
  }]
218
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], controlId: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlId", required: false }] }], controlName: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlName", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", 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 }] }], parseDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "parseDate", required: false }] }], formatInputDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatInputDate", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], pickerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickerClass", required: false }] }], inputClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
245
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], controlId: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlId", required: false }] }], controlName: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlName", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], autoError: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoError", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", 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 }] }], parseDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "parseDate", required: false }] }], formatInputDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatInputDate", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], pickerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickerClass", required: false }] }], inputClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
219
246
 
220
247
  /*
221
248
  * Public API Surface of form-month-year-picker
@@ -3,12 +3,19 @@ import { ClassValue } from 'clsx';
3
3
 
4
4
  declare class EgFormMonthYearPicker {
5
5
  private readonly formGroupDirective;
6
+ private readonly _errorMessages;
6
7
  private readonly generatedId;
7
8
  private readonly _config;
8
9
  label: _angular_core.InputSignal<string | undefined>;
9
10
  controlId: _angular_core.InputSignal<string | undefined>;
10
11
  controlName: _angular_core.InputSignal<string>;
11
12
  error: _angular_core.InputSignal<string | undefined>;
13
+ /**
14
+ * Auto-resolve the displayed message from the control's `ValidationErrors`
15
+ * when `error()` is unset. Explicit `error()` always wins. Set to `false`
16
+ * for manual-only messages.
17
+ */
18
+ autoError: _angular_core.InputSignal<boolean>;
12
19
  hint: _angular_core.InputSignal<string | undefined>;
13
20
  id: _angular_core.InputSignal<string | undefined>;
14
21
  name: _angular_core.InputSignal<string | undefined>;
@@ -26,6 +33,19 @@ declare class EgFormMonthYearPicker {
26
33
  readonly effectiveId: _angular_core.Signal<string>;
27
34
  readonly errorId: _angular_core.Signal<string>;
28
35
  readonly hintId: _angular_core.Signal<string>;
36
+ /**
37
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
38
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
39
+ * computed): `ValidationErrors` is not a signal, so the control must be read
40
+ * fresh on every change-detection pass.
41
+ */
42
+ protected resolvedError(): string | undefined;
43
+ /**
44
+ * Whether the error is surfaced: message present + control invalid +
45
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
46
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
47
+ */
48
+ protected showError(): boolean;
29
49
  /**
30
50
  * Bounds projected onto the picker's `Date` model. The cast keeps the
31
51
  * template's generic inference on `Date` while passing runtime values
@@ -47,7 +67,7 @@ declare class EgFormMonthYearPicker {
47
67
  $errorClass: _angular_core.Signal<string>;
48
68
  $hintClass: _angular_core.Signal<string>;
49
69
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgFormMonthYearPicker, never>;
50
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormMonthYearPicker, "eg-form-month-year-picker", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; "controlName": { "alias": "controlName"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "autoCloseOnSelect": { "alias": "autoCloseOnSelect"; "required": false; "isSignal": true; }; "formatDate": { "alias": "formatDate"; "required": false; "isSignal": true; }; "transformDate": { "alias": "transformDate"; "required": false; "isSignal": true; }; "parseDate": { "alias": "parseDate"; "required": false; "isSignal": true; }; "formatInputDate": { "alias": "formatInputDate"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "pickerClass": { "alias": "pickerClass"; "required": false; "isSignal": true; }; "inputClass": { "alias": "inputClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
70
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormMonthYearPicker, "eg-form-month-year-picker", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; "controlName": { "alias": "controlName"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "autoError": { "alias": "autoError"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "autoCloseOnSelect": { "alias": "autoCloseOnSelect"; "required": false; "isSignal": true; }; "formatDate": { "alias": "formatDate"; "required": false; "isSignal": true; }; "transformDate": { "alias": "transformDate"; "required": false; "isSignal": true; }; "parseDate": { "alias": "parseDate"; "required": false; "isSignal": true; }; "formatInputDate": { "alias": "formatInputDate"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "pickerClass": { "alias": "pickerClass"; "required": false; "isSignal": true; }; "inputClass": { "alias": "inputClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
51
71
  }
52
72
 
53
73
  export { EgFormMonthYearPicker };
@@ -76,23 +76,24 @@ Selector (from source): `eg-form-native-select` (standalone component, host `tw:
76
76
 
77
77
  ### `EgFormNativeSelect` — `eg-form-native-select`
78
78
 
79
- | Input | Type | Default | Description |
80
- | ------------- | ------------------------------- | ------- | ---------------------------------------------------------------------- |
81
- | `controlName` | `string` | `''` | `formControlName` key inside the parent `FormGroup`. **Required.** |
82
- | `label` | `string \| undefined` | — | Label text (hidden when omitted). |
83
- | `error` | `string \| undefined` | — | Error text shown when invalid. |
84
- | `hint` | `string \| undefined` | — | Hint text shown otherwise. |
85
- | `controlId` | `string \| undefined` | — | Explicit id (first priority for `effectiveId`). |
86
- | `id` | `string \| undefined` | — | Fallback id (second priority). |
87
- | `name` | `string \| undefined` | — | Native `name` forwarded to the inner `<select>` (`controlName` wins). |
88
- | `disabled` | `boolean` | `false` | Locks interaction (form control stays enabled). |
89
- | `required` | `boolean` | `false` | Shows a red `*` next to the label. |
90
- | `options` | `{ value, label, disabled? }[]` | `[]` | Rendered as native `<option>` elements. |
91
- | `class` | `ClassValue` | `''` | Extra host classes (base `tw:w-full`). |
92
- | `labelClass` | `string` | `''` | Extra label classes (base `tw:mb-1 tw:gap-0`). |
93
- | `selectClass` | `string` | `''` | Extra inner-select classes, merged into `HlmNativeSelect.selectClass`. |
94
- | `errorClass` | `string` | `''` | Extra error classes (base `tw:mt-0`). |
95
- | `hintClass` | `string` | `''` | Extra hint classes (base `tw:mt-0`). |
79
+ | Input | Type | Default | Description |
80
+ | ------------- | ------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
81
+ | `controlName` | `string` | `''` | `formControlName` key inside the parent `FormGroup`. **Required.** |
82
+ | `label` | `string \| undefined` | — | Label text (hidden when omitted). |
83
+ | `error` | `string \| undefined` | — | Error text shown when invalid. |
84
+ | `autoError` | `boolean` | `true` | Auto-resolve the message from the control's `ValidationErrors` when `error` is unset. Explicit `error` always wins; `error=""` counts as unset. Global wording via `provideEgFormErrorMessages`. |
85
+ | `hint` | `string \| undefined` | — | Hint text shown otherwise. |
86
+ | `controlId` | `string \| undefined` | — | Explicit id (first priority for `effectiveId`). |
87
+ | `id` | `string \| undefined` | — | Fallback id (second priority). |
88
+ | `name` | `string \| undefined` | — | Native `name` forwarded to the inner `<select>` (`controlName` wins). |
89
+ | `disabled` | `boolean` | `false` | Locks interaction (form control stays enabled). |
90
+ | `required` | `boolean` | `false` | Shows a red `*` next to the label. |
91
+ | `options` | `{ value, label, disabled? }[]` | `[]` | Rendered as native `<option>` elements. |
92
+ | `class` | `ClassValue` | `''` | Extra host classes (base `tw:w-full`). |
93
+ | `labelClass` | `string` | `''` | Extra label classes (base `tw:mb-1 tw:gap-0`). |
94
+ | `selectClass` | `string` | `''` | Extra inner-select classes, merged into `HlmNativeSelect.selectClass`. |
95
+ | `errorClass` | `string` | `''` | Extra error classes (base `tw:mt-0`). |
96
+ | `hintClass` | `string` | `''` | Extra hint classes (base `tw:mt-0`). |
96
97
 
97
98
  | Member | Description |
98
99
  | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, input, computed, Component } from '@angular/core';
3
3
  import * as i1 from '@angular/forms';
4
4
  import { FormGroupDirective, ReactiveFormsModule, ControlContainer } from '@angular/forms';
5
- import { HlmFormIdGenerator, HlmFormField, HlmError, HlmHint } from '@egose/shadcn-theme-ng-tw/form-field';
5
+ import { injectEgFormErrorMessages, HlmFormIdGenerator, resolveEgFormError, HlmFormField, HlmError, HlmHint } from '@egose/shadcn-theme-ng-tw/form-field';
6
6
  import { HlmLabel } from '@egose/shadcn-theme-ng-tw/label';
7
7
  import { HlmNativeSelect } from '@egose/shadcn-theme-ng-tw/native-select';
8
8
  import { hlm } from '@egose/shadcn-theme-ng-tw/utils';
@@ -17,6 +17,7 @@ function injectEgFormNativeSelectConfig() {
17
17
 
18
18
  class EgFormNativeSelect {
19
19
  formGroupDirective = inject(FormGroupDirective);
20
+ _errorMessages = injectEgFormErrorMessages();
20
21
  generatedId = inject(HlmFormIdGenerator).generate('eg-form-native-select');
21
22
  _config = injectEgFormNativeSelectConfig();
22
23
  label = input(undefined, /* @ts-ignore */
@@ -27,6 +28,13 @@ class EgFormNativeSelect {
27
28
  ...(ngDevMode ? [{ debugName: "controlName" }] : /* istanbul ignore next */ []));
28
29
  error = input(undefined, /* @ts-ignore */
29
30
  ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
31
+ /**
32
+ * Auto-resolve the displayed message from the control's `ValidationErrors`
33
+ * when `error()` is unset. Explicit `error()` always wins. Set to `false`
34
+ * for manual-only messages.
35
+ */
36
+ autoError = input(true, /* @ts-ignore */
37
+ ...(ngDevMode ? [{ debugName: "autoError" }] : /* istanbul ignore next */ []));
30
38
  hint = input(undefined, /* @ts-ignore */
31
39
  ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
32
40
  id = input(undefined, /* @ts-ignore */
@@ -45,13 +53,34 @@ class EgFormNativeSelect {
45
53
  ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
46
54
  hintId = computed(() => `${this.effectiveId()}-hint`, /* @ts-ignore */
47
55
  ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
48
- describedBy() {
56
+ /**
57
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
58
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
59
+ * computed): `ValidationErrors` is not a signal, so the control must be read
60
+ * fresh on every change-detection pass.
61
+ */
62
+ resolvedError() {
63
+ const explicit = this.error();
64
+ if (explicit)
65
+ return explicit;
66
+ if (!this.autoError())
67
+ return undefined;
68
+ const control = this.formGroupDirective.form.get(this.controlName());
69
+ return resolveEgFormError(control?.errors ?? null, this.label(), this._errorMessages);
70
+ }
71
+ /**
72
+ * Whether the error is surfaced: message present + control invalid +
73
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
74
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
75
+ */
76
+ showError() {
49
77
  const control = this.formGroupDirective.form.get(this.controlName());
50
- return this.error() && control?.invalid && (control.dirty || control.touched)
51
- ? this.errorId()
52
- : this.hint()
53
- ? this.hintId()
54
- : null;
78
+ return (!!this.resolvedError() &&
79
+ !!control?.invalid &&
80
+ (control.dirty || control.touched || this.formGroupDirective.submitted));
81
+ }
82
+ describedBy() {
83
+ return this.showError() ? this.errorId() : this.hint() ? this.hintId() : null;
55
84
  }
56
85
  // Styling
57
86
  userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
@@ -75,10 +104,9 @@ class EgFormNativeSelect {
75
104
  $hintClass = computed(() => hlm('tw:mt-0', this._config.hintClass, this.hintClass()), /* @ts-ignore */
76
105
  ...(ngDevMode ? [{ debugName: "$hintClass" }] : /* istanbul ignore next */ []));
77
106
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormNativeSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
78
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormNativeSelect, isStandalone: true, selector: "eg-form-native-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", isSignal: true, isRequired: false, transformFunction: null }, selectClass: { classPropertyName: "selectClass", publicName: "selectClass", isSignal: true, isRequired: false, transformFunction: null }, errorClass: { classPropertyName: "errorClass", publicName: "errorClass", isSignal: true, isRequired: false, transformFunction: null }, hintClass: { classPropertyName: "hintClass", publicName: "hintClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "$userClass()" } }, providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }], ngImport: i0, template: `
107
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormNativeSelect, isStandalone: true, selector: "eg-form-native-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, autoError: { classPropertyName: "autoError", publicName: "autoError", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", isSignal: true, isRequired: false, transformFunction: null }, selectClass: { classPropertyName: "selectClass", publicName: "selectClass", isSignal: true, isRequired: false, transformFunction: null }, errorClass: { classPropertyName: "errorClass", publicName: "errorClass", isSignal: true, isRequired: false, transformFunction: null }, hintClass: { classPropertyName: "hintClass", publicName: "hintClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "$userClass()" } }, providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }], ngImport: i0, template: `
79
108
  @let lbl = label();
80
109
  @let cnm = controlName();
81
- @let err = error();
82
110
  @let hnt = hint();
83
111
  @let rqrd = required();
84
112
 
@@ -101,13 +129,19 @@ class EgFormNativeSelect {
101
129
  [selectClass]="$selectClass()"
102
130
  >
103
131
  @for (option of options(); track option.value) {
104
- <option class="tw:bg-[Canvas] tw:text-[CanvasText]" [value]="option.value" [disabled]="option.disabled ?? false">{{ option.label }}</option>
132
+ <option
133
+ class="tw:bg-[Canvas] tw:text-[CanvasText]"
134
+ [value]="option.value"
135
+ [disabled]="option.disabled ?? false"
136
+ >
137
+ {{ option.label }}
138
+ </option>
105
139
  }
106
140
  </hlm-native-select>
107
141
 
108
- @if (err) {
142
+ @if (showError()) {
109
143
  <hlm-error [id]="errorId()" [class]="$errorClass()">
110
- {{ err }}
144
+ {{ resolvedError() }}
111
145
  </hlm-error>
112
146
  }
113
147
 
@@ -132,7 +166,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
132
166
  template: `
133
167
  @let lbl = label();
134
168
  @let cnm = controlName();
135
- @let err = error();
136
169
  @let hnt = hint();
137
170
  @let rqrd = required();
138
171
 
@@ -155,13 +188,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
155
188
  [selectClass]="$selectClass()"
156
189
  >
157
190
  @for (option of options(); track option.value) {
158
- <option class="tw:bg-[Canvas] tw:text-[CanvasText]" [value]="option.value" [disabled]="option.disabled ?? false">{{ option.label }}</option>
191
+ <option
192
+ class="tw:bg-[Canvas] tw:text-[CanvasText]"
193
+ [value]="option.value"
194
+ [disabled]="option.disabled ?? false"
195
+ >
196
+ {{ option.label }}
197
+ </option>
159
198
  }
160
199
  </hlm-native-select>
161
200
 
162
- @if (err) {
201
+ @if (showError()) {
163
202
  <hlm-error [id]="errorId()" [class]="$errorClass()">
164
- {{ err }}
203
+ {{ resolvedError() }}
165
204
  </hlm-error>
166
205
  }
167
206
 
@@ -173,7 +212,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
173
212
  </hlm-form-field>
174
213
  `,
175
214
  }]
176
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], controlId: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlId", required: false }] }], controlName: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlName", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], selectClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
215
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], controlId: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlId", required: false }] }], controlName: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlName", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], autoError: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoError", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], selectClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
177
216
 
178
217
  /*
179
218
  * Public API Surface of form-native-select
@@ -9,12 +9,19 @@ interface NativeSelectOption {
9
9
  }
10
10
  declare class EgFormNativeSelect {
11
11
  private readonly formGroupDirective;
12
+ private readonly _errorMessages;
12
13
  private readonly generatedId;
13
14
  private readonly _config;
14
15
  label: _angular_core.InputSignal<string | undefined>;
15
16
  controlId: _angular_core.InputSignal<string | undefined>;
16
17
  controlName: _angular_core.InputSignal<string>;
17
18
  error: _angular_core.InputSignal<string | undefined>;
19
+ /**
20
+ * Auto-resolve the displayed message from the control's `ValidationErrors`
21
+ * when `error()` is unset. Explicit `error()` always wins. Set to `false`
22
+ * for manual-only messages.
23
+ */
24
+ autoError: _angular_core.InputSignal<boolean>;
18
25
  hint: _angular_core.InputSignal<string | undefined>;
19
26
  id: _angular_core.InputSignal<string | undefined>;
20
27
  name: _angular_core.InputSignal<string | undefined>;
@@ -24,6 +31,19 @@ declare class EgFormNativeSelect {
24
31
  readonly effectiveId: _angular_core.Signal<string>;
25
32
  readonly errorId: _angular_core.Signal<string>;
26
33
  readonly hintId: _angular_core.Signal<string>;
34
+ /**
35
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
36
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
37
+ * computed): `ValidationErrors` is not a signal, so the control must be read
38
+ * fresh on every change-detection pass.
39
+ */
40
+ protected resolvedError(): string | undefined;
41
+ /**
42
+ * Whether the error is surfaced: message present + control invalid +
43
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
44
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
45
+ */
46
+ protected showError(): boolean;
27
47
  describedBy(): string | null;
28
48
  userClass: _angular_core.InputSignal<ClassValue>;
29
49
  labelClass: _angular_core.InputSignal<string>;
@@ -36,7 +56,7 @@ declare class EgFormNativeSelect {
36
56
  $errorClass: _angular_core.Signal<string>;
37
57
  $hintClass: _angular_core.Signal<string>;
38
58
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgFormNativeSelect, never>;
39
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormNativeSelect, "eg-form-native-select", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; "controlName": { "alias": "controlName"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "selectClass": { "alias": "selectClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
59
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormNativeSelect, "eg-form-native-select", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; "controlName": { "alias": "controlName"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "autoError": { "alias": "autoError"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "selectClass": { "alias": "selectClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
40
60
  }
41
61
 
42
62
  interface EgFormNativeSelectConfig {
@@ -71,28 +71,29 @@ Selector (from source): `eg-form-phone-input` (standalone component, host `tw:w-
71
71
 
72
72
  ### `EgFormPhoneInput` — `eg-form-phone-input`
73
73
 
74
- | Input | Type | Default | Description |
75
- | ------------------- | ---------------------------- | ----------------------- | ------------------------------------------------------------------ |
76
- | `controlName` | `string` | `''` | `formControlName` key inside the parent `FormGroup`. **Required.** |
77
- | `label` | `string \| undefined` | — | Label text (hidden when omitted). |
78
- | `error` | `string \| undefined` | — | Error text shown when invalid. |
79
- | `hint` | `string \| undefined` | — | Hint text shown otherwise. |
80
- | `controlId` | `string \| undefined` | — | Explicit id (first priority for `effectiveId`). |
81
- | `id` | `string \| undefined` | — | Fallback id (second priority). |
82
- | `name` | `string \| undefined` | — | Native `name` forwarded to the inner input (`controlName` wins). |
83
- | `placeholder` | `string` | `'(555) 123-4567'` | Input placeholder. |
84
- | `autocomplete` | `string` | `'tel'` | Native autocomplete token. |
85
- | `readonly` | `boolean` | `false` | Native `readonly` forwarded to the inner input. |
86
- | `disabled` | `boolean` | `false` | Locks interaction (form control stays enabled). |
87
- | `required` | `boolean` | `false` | Shows a red `*` next to the label. |
88
- | `maxDigits` | `number` | `10` | Maximum digit count kept in the model. |
89
- | `modelFormat` | `'digits' \| 'formatted'` | `'digits'` | Model shape: raw digits or formatted display text. |
90
- | `formatPhoneNumber` | `(digits: string) => string` | `formatNanpPhoneNumber` | Display formatter forwarded to the input. |
91
- | `class` | `ClassValue` | `''` | Extra host classes (base `tw:w-full`). |
92
- | `labelClass` | `string` | `''` | Extra label classes (base `tw:mb-1 tw:gap-0`). |
93
- | `inputClass` | `string` | `''` | Extra inner-input classes. |
94
- | `errorClass` | `string` | `''` | Extra error classes (base `tw:mt-0`). |
95
- | `hintClass` | `string` | `''` | Extra hint classes (base `tw:mt-0`). |
74
+ | Input | Type | Default | Description |
75
+ | ------------------- | ---------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
76
+ | `controlName` | `string` | `''` | `formControlName` key inside the parent `FormGroup`. **Required.** |
77
+ | `label` | `string \| undefined` | — | Label text (hidden when omitted). |
78
+ | `error` | `string \| undefined` | — | Error text shown when invalid. |
79
+ | `autoError` | `boolean` | `true` | Auto-resolve the message from the control's `ValidationErrors` when `error` is unset. Explicit `error` always wins; `error=""` counts as unset. Global wording via `provideEgFormErrorMessages`. |
80
+ | `hint` | `string \| undefined` | — | Hint text shown otherwise. |
81
+ | `controlId` | `string \| undefined` | — | Explicit id (first priority for `effectiveId`). |
82
+ | `id` | `string \| undefined` | — | Fallback id (second priority). |
83
+ | `name` | `string \| undefined` | — | Native `name` forwarded to the inner input (`controlName` wins). |
84
+ | `placeholder` | `string` | `'(555) 123-4567'` | Input placeholder. |
85
+ | `autocomplete` | `string` | `'tel'` | Native autocomplete token. |
86
+ | `readonly` | `boolean` | `false` | Native `readonly` forwarded to the inner input. |
87
+ | `disabled` | `boolean` | `false` | Locks interaction (form control stays enabled). |
88
+ | `required` | `boolean` | `false` | Shows a red `*` next to the label. |
89
+ | `maxDigits` | `number` | `10` | Maximum digit count kept in the model. |
90
+ | `modelFormat` | `'digits' \| 'formatted'` | `'digits'` | Model shape: raw digits or formatted display text. |
91
+ | `formatPhoneNumber` | `(digits: string) => string` | `formatNanpPhoneNumber` | Display formatter forwarded to the input. |
92
+ | `class` | `ClassValue` | `''` | Extra host classes (base `tw:w-full`). |
93
+ | `labelClass` | `string` | `''` | Extra label classes (base `tw:mb-1 tw:gap-0`). |
94
+ | `inputClass` | `string` | `''` | Extra inner-input classes. |
95
+ | `errorClass` | `string` | `''` | Extra error classes (base `tw:mt-0`). |
96
+ | `hintClass` | `string` | `''` | Extra hint classes (base `tw:mt-0`). |
96
97
 
97
98
  | Member | Description |
98
99
  | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |