@egose/shadcn-theme-ng 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 +38 -4
  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 +39 -10
  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 +38 -4
  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 +39 -10
  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 +39 -10
  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 +39 -10
  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 +38 -4
  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 +39 -10
  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 +39 -10
  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 +39 -10
  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 +39 -10
  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 +39 -10
  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 +39 -10
  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 +38 -4
  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 +39 -10
  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 +39 -10
  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 +39 -10
  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 +40 -6
  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 +39 -10
  62. package/form-toggle-group/types/form-toggle-group.d.ts +21 -1
  63. package/package.json +1 -1
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, input, numberAttribute, 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/form-field';
5
+ import { injectEgFormErrorMessages, HlmFormIdGenerator, resolveEgFormError, HlmFormField, HlmError, HlmHint } from '@egose/shadcn-theme-ng/form-field';
6
6
  import { HlmLabel } from '@egose/shadcn-theme-ng/label';
7
7
  import { HlmSlider } from '@egose/shadcn-theme-ng/slider';
8
8
  import { hlm } from '@egose/shadcn-theme-ng/utils';
@@ -17,6 +17,7 @@ function injectEgFormSliderConfig() {
17
17
 
18
18
  class EgFormSlider {
19
19
  formGroupDirective = inject(FormGroupDirective);
20
+ _errorMessages = injectEgFormErrorMessages();
20
21
  generatedId = inject(HlmFormIdGenerator).generate('eg-form-slider');
21
22
  _config = injectEgFormSliderConfig();
22
23
  label = input(undefined, /* @ts-ignore */
@@ -27,6 +28,13 @@ class EgFormSlider {
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 */
@@ -46,6 +54,32 @@ class EgFormSlider {
46
54
  ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
47
55
  hintId = computed(() => `${this.effectiveId()}-hint`, /* @ts-ignore */
48
56
  ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
57
+ /**
58
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
59
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
60
+ * computed): `ValidationErrors` is not a signal, so the control must be read
61
+ * fresh on every change-detection pass.
62
+ */
63
+ resolvedError() {
64
+ const explicit = this.error();
65
+ if (explicit)
66
+ return explicit;
67
+ if (!this.autoError())
68
+ return undefined;
69
+ const control = this.formGroupDirective.form.get(this.controlName());
70
+ return resolveEgFormError(control?.errors ?? null, this.label(), this._errorMessages);
71
+ }
72
+ /**
73
+ * Whether the error is surfaced: message present + control invalid +
74
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
75
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
76
+ */
77
+ showError() {
78
+ const control = this.formGroupDirective.form.get(this.controlName());
79
+ return (!!this.resolvedError() &&
80
+ !!control?.invalid &&
81
+ (control.dirty || control.touched || this.formGroupDirective.submitted));
82
+ }
49
83
  /**
50
84
  * Combined lock for the brain `linkedSignal`-based disabled state: the raw
51
85
  * input write always carries the resolved value, so a same-pass
@@ -78,7 +112,7 @@ class EgFormSlider {
78
112
  $hintClass = computed(() => hlm("mt-0", this._config.hintClass, this.hintClass()), /* @ts-ignore */
79
113
  ...(ngDevMode ? [{ debugName: "$hintClass" }] : /* istanbul ignore next */ []));
80
114
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormSlider, deps: [], target: i0.ɵɵFactoryTarget.Component });
81
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormSlider, isStandalone: true, selector: "eg-form-slider", 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 }, 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 }, step: { classPropertyName: "step", publicName: "step", 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 }, sliderClass: { classPropertyName: "sliderClass", publicName: "sliderClass", 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: "\n @let lbl = label();\n @let cnm = controlName();\n @let err = error();\n @let hnt = hint();\n @let rqrd = required();\n\n <hlm-form-field>\n @if (lbl) {\n <label hlmLabel [id]=\"labelId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <hlm-slider\n [id]=\"effectiveId()\"\n [formControlName]=\"cnm\"\n [min]=\"min()\"\n [max]=\"max()\"\n [step]=\"step()\"\n [disabled]=\"effectiveDisabled()\"\n [aria-labelledby]=\"lbl ? labelId() : null\"\n [class]=\"$sliderClass()\"\n />\n\n @if (err) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ err }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </hlm-form-field>\n ", isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: HlmFormField, selector: "hlm-form-field", inputs: ["class"] }, { kind: "directive", type: HlmError, selector: "hlm-error", inputs: ["class"] }, { kind: "directive", type: HlmHint, selector: "hlm-hint", inputs: ["class"] }, { kind: "directive", type: HlmLabel, selector: "[hlmLabel]", inputs: ["class"] }, { kind: "component", type: HlmSlider, selector: "hlm-slider, brn-slider [hlm]" }] });
115
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormSlider, isStandalone: true, selector: "eg-form-slider", 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 }, 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 }, step: { classPropertyName: "step", publicName: "step", 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 }, sliderClass: { classPropertyName: "sliderClass", publicName: "sliderClass", 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: "\n @let lbl = label();\n @let cnm = controlName();\n @let hnt = hint();\n @let rqrd = required();\n\n <hlm-form-field>\n @if (lbl) {\n <label hlmLabel [id]=\"labelId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <hlm-slider\n [id]=\"effectiveId()\"\n [formControlName]=\"cnm\"\n [min]=\"min()\"\n [max]=\"max()\"\n [step]=\"step()\"\n [disabled]=\"effectiveDisabled()\"\n [aria-labelledby]=\"lbl ? labelId() : null\"\n [class]=\"$sliderClass()\"\n />\n\n @if (showError()) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ resolvedError() }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </hlm-form-field>\n ", isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: HlmFormField, selector: "hlm-form-field", inputs: ["class"] }, { kind: "directive", type: HlmError, selector: "hlm-error", inputs: ["class"] }, { kind: "directive", type: HlmHint, selector: "hlm-hint", inputs: ["class"] }, { kind: "directive", type: HlmLabel, selector: "[hlmLabel]", inputs: ["class"] }, { kind: "component", type: HlmSlider, selector: "hlm-slider, brn-slider [hlm]" }] });
82
116
  }
83
117
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormSlider, decorators: [{
84
118
  type: Component,
@@ -90,9 +124,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
90
124
  },
91
125
  imports: [ReactiveFormsModule, HlmFormField, HlmError, HlmHint, HlmLabel, HlmSlider],
92
126
  providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }],
93
- template: "\n @let lbl = label();\n @let cnm = controlName();\n @let err = error();\n @let hnt = hint();\n @let rqrd = required();\n\n <hlm-form-field>\n @if (lbl) {\n <label hlmLabel [id]=\"labelId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <hlm-slider\n [id]=\"effectiveId()\"\n [formControlName]=\"cnm\"\n [min]=\"min()\"\n [max]=\"max()\"\n [step]=\"step()\"\n [disabled]=\"effectiveDisabled()\"\n [aria-labelledby]=\"lbl ? labelId() : null\"\n [class]=\"$sliderClass()\"\n />\n\n @if (err) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ err }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </hlm-form-field>\n ",
127
+ template: "\n @let lbl = label();\n @let cnm = controlName();\n @let hnt = hint();\n @let rqrd = required();\n\n <hlm-form-field>\n @if (lbl) {\n <label hlmLabel [id]=\"labelId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <hlm-slider\n [id]=\"effectiveId()\"\n [formControlName]=\"cnm\"\n [min]=\"min()\"\n [max]=\"max()\"\n [step]=\"step()\"\n [disabled]=\"effectiveDisabled()\"\n [aria-labelledby]=\"lbl ? labelId() : null\"\n [class]=\"$sliderClass()\"\n />\n\n @if (showError()) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ resolvedError() }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </hlm-form-field>\n ",
94
128
  }]
95
- }], 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 }] }], 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 }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], sliderClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "sliderClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
129
+ }], 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 }] }], 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 }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], sliderClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "sliderClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
96
130
 
97
131
  /*
98
132
  * Public API Surface of form-slider
@@ -5,12 +5,19 @@ import { NumberInput } from '@angular/cdk/coercion';
5
5
 
6
6
  declare class EgFormSlider {
7
7
  private readonly formGroupDirective;
8
+ private readonly _errorMessages;
8
9
  private readonly generatedId;
9
10
  private readonly _config;
10
11
  label: _angular_core.InputSignal<string | undefined>;
11
12
  controlId: _angular_core.InputSignal<string | undefined>;
12
13
  controlName: _angular_core.InputSignal<string>;
13
14
  error: _angular_core.InputSignal<string | undefined>;
15
+ /**
16
+ * Auto-resolve the displayed message from the control's `ValidationErrors`
17
+ * when `error()` is unset. Explicit `error()` always wins. Set to `false`
18
+ * for manual-only messages.
19
+ */
20
+ autoError: _angular_core.InputSignal<boolean>;
14
21
  hint: _angular_core.InputSignal<string | undefined>;
15
22
  id: _angular_core.InputSignal<string | undefined>;
16
23
  disabled: _angular_core.InputSignal<boolean>;
@@ -22,6 +29,19 @@ declare class EgFormSlider {
22
29
  readonly labelId: _angular_core.Signal<string>;
23
30
  readonly errorId: _angular_core.Signal<string>;
24
31
  readonly hintId: _angular_core.Signal<string>;
32
+ /**
33
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
34
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
35
+ * computed): `ValidationErrors` is not a signal, so the control must be read
36
+ * fresh on every change-detection pass.
37
+ */
38
+ protected resolvedError(): string | undefined;
39
+ /**
40
+ * Whether the error is surfaced: message present + control invalid +
41
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
42
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
43
+ */
44
+ protected showError(): boolean;
25
45
  /**
26
46
  * Combined lock for the brain `linkedSignal`-based disabled state: the raw
27
47
  * input write always carries the resolved value, so a same-pass
@@ -39,7 +59,7 @@ declare class EgFormSlider {
39
59
  $errorClass: _angular_core.Signal<string>;
40
60
  $hintClass: _angular_core.Signal<string>;
41
61
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgFormSlider, never>;
42
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormSlider, "eg-form-slider", 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; }; "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; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "sliderClass": { "alias": "sliderClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
62
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormSlider, "eg-form-slider", 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; }; "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; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "sliderClass": { "alias": "sliderClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
43
63
  }
44
64
 
45
65
  interface EgFormSliderConfig {
@@ -70,21 +70,22 @@ Selector (from source): `eg-form-switch` (standalone component, host `tw:w-full`
70
70
 
71
71
  ### `EgFormSwitch` — `eg-form-switch`
72
72
 
73
- | Input | Type | Default | Description |
74
- | ------------- | --------------------- | ------- | ------------------------------------------------------------------ |
75
- | `controlName` | `string` | `''` | `formControlName` key inside the parent `FormGroup`. **Required.** |
76
- | `label` | `string \| undefined` | — | Label text beside the switch (hidden when omitted). |
77
- | `error` | `string \| undefined` | — | Error text shown when invalid. |
78
- | `hint` | `string \| undefined` | — | Hint text shown otherwise. |
79
- | `controlId` | `string \| undefined` | — | Explicit id (first priority for `effectiveId`). |
80
- | `id` | `string \| undefined` | — | Fallback id (second priority). |
81
- | `disabled` | `boolean` | `false` | Locks interaction (form control stays enabled). |
82
- | `required` | `boolean` | `false` | Shows a red `*` next to the label; forwarded to the switch. |
83
- | `class` | `ClassValue` | `''` | Extra host classes (base `tw:w-full`). |
84
- | `switchClass` | `string` | `''` | Extra switch classes, merged into `HlmSwitch.userClass`. |
85
- | `labelClass` | `string` | `''` | Extra label classes. |
86
- | `errorClass` | `string` | `''` | Extra error classes (base `tw:mt-0`). |
87
- | `hintClass` | `string` | `''` | Extra hint classes (base `tw:mt-0`). |
73
+ | Input | Type | Default | Description |
74
+ | ------------- | --------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
75
+ | `controlName` | `string` | `''` | `formControlName` key inside the parent `FormGroup`. **Required.** |
76
+ | `label` | `string \| undefined` | — | Label text beside the switch (hidden when omitted). |
77
+ | `error` | `string \| undefined` | — | Error text shown when invalid. |
78
+ | `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`. |
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
+ | `disabled` | `boolean` | `false` | Locks interaction (form control stays enabled). |
83
+ | `required` | `boolean` | `false` | Shows a red `*` next to the label; forwarded to the switch. |
84
+ | `class` | `ClassValue` | `''` | Extra host classes (base `tw:w-full`). |
85
+ | `switchClass` | `string` | `''` | Extra switch classes, merged into `HlmSwitch.userClass`. |
86
+ | `labelClass` | `string` | `''` | Extra label classes. |
87
+ | `errorClass` | `string` | `''` | Extra error classes (base `tw:mt-0`). |
88
+ | `hintClass` | `string` | `''` | Extra hint classes (base `tw:mt-0`). |
88
89
 
89
90
  | Member | Description |
90
91
  | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -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, HlmError, HlmHint } from '@egose/shadcn-theme-ng/form-field';
5
+ import { injectEgFormErrorMessages, HlmFormIdGenerator, resolveEgFormError, HlmError, HlmHint } from '@egose/shadcn-theme-ng/form-field';
6
6
  import { EgFormField } from '@egose/shadcn-theme-ng/form-field-simple';
7
7
  import { HlmLabel } from '@egose/shadcn-theme-ng/label';
8
8
  import { HlmSwitch } from '@egose/shadcn-theme-ng/switch';
@@ -18,6 +18,7 @@ function injectEgFormSwitchConfig() {
18
18
 
19
19
  class EgFormSwitch {
20
20
  formGroupDirective = inject(FormGroupDirective);
21
+ _errorMessages = injectEgFormErrorMessages();
21
22
  generatedId = inject(HlmFormIdGenerator).generate('eg-form-switch');
22
23
  _config = injectEgFormSwitchConfig();
23
24
  label = input(undefined, /* @ts-ignore */
@@ -28,6 +29,13 @@ class EgFormSwitch {
28
29
  ...(ngDevMode ? [{ debugName: "controlName" }] : /* istanbul ignore next */ []));
29
30
  error = input(undefined, /* @ts-ignore */
30
31
  ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
32
+ /**
33
+ * Auto-resolve the displayed message from the control's `ValidationErrors`
34
+ * when `error()` is unset. Explicit `error()` always wins. Set to `false`
35
+ * for manual-only messages.
36
+ */
37
+ autoError = input(true, /* @ts-ignore */
38
+ ...(ngDevMode ? [{ debugName: "autoError" }] : /* istanbul ignore next */ []));
31
39
  hint = input(undefined, /* @ts-ignore */
32
40
  ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
33
41
  id = input(undefined, /* @ts-ignore */
@@ -42,13 +50,34 @@ class EgFormSwitch {
42
50
  ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
43
51
  hintId = computed(() => `${this.effectiveId()}-hint`, /* @ts-ignore */
44
52
  ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
45
- describedBy() {
53
+ /**
54
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
55
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
56
+ * computed): `ValidationErrors` is not a signal, so the control must be read
57
+ * fresh on every change-detection pass.
58
+ */
59
+ resolvedError() {
60
+ const explicit = this.error();
61
+ if (explicit)
62
+ return explicit;
63
+ if (!this.autoError())
64
+ return undefined;
65
+ const control = this.formGroupDirective.form.get(this.controlName());
66
+ return resolveEgFormError(control?.errors ?? null, this.label(), this._errorMessages);
67
+ }
68
+ /**
69
+ * Whether the error is surfaced: message present + control invalid +
70
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
71
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
72
+ */
73
+ showError() {
46
74
  const control = this.formGroupDirective.form.get(this.controlName());
47
- return this.error() && control?.invalid && (control.dirty || control.touched)
48
- ? this.errorId()
49
- : this.hint()
50
- ? this.hintId()
51
- : null;
75
+ return (!!this.resolvedError() &&
76
+ !!control?.invalid &&
77
+ (control.dirty || control.touched || this.formGroupDirective.submitted));
78
+ }
79
+ describedBy() {
80
+ return this.showError() ? this.errorId() : this.hint() ? this.hintId() : null;
52
81
  }
53
82
  // Styling
54
83
  userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
@@ -72,7 +101,7 @@ class EgFormSwitch {
72
101
  $hintClass = computed(() => hlm("mt-0", this._config.hintClass, this.hintClass()), /* @ts-ignore */
73
102
  ...(ngDevMode ? [{ debugName: "$hintClass" }] : /* istanbul ignore next */ []));
74
103
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
75
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormSwitch, isStandalone: true, selector: "eg-form-switch", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, switchClass: { classPropertyName: "switchClass", publicName: "switchClass", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", 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: "\n @let lbl = label();\n @let cnm = controlName();\n @let err = error();\n @let hnt = hint();\n @let rqrd = required();\n\n <eg-form-field>\n <div class=\"flex items-center gap-1\">\n <hlm-switch\n [id]=\"effectiveId()\"\n [formControlName]=\"cnm\"\n [required]=\"rqrd\"\n [disabled]=\"disabled()\"\n [aria-describedby]=\"describedBy()\"\n [class]=\"$switchClass()\"\n />\n @if (lbl) {\n <label hlmLabel [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n </div>\n\n @if (err) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ err }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </eg-form-field>\n ", isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: HlmError, selector: "hlm-error", inputs: ["class"] }, { kind: "directive", type: HlmHint, selector: "hlm-hint", inputs: ["class"] }, { kind: "directive", type: HlmLabel, selector: "[hlmLabel]", inputs: ["class"] }, { kind: "component", type: HlmSwitch, selector: "hlm-switch", inputs: ["class", "checked", "disabled", "id", "aria-label", "aria-labelledby", "aria-describedby"], outputs: ["checkedChange", "changed"] }, { kind: "component", type: EgFormField, selector: "eg-form-field", inputs: ["class"] }] });
104
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormSwitch, isStandalone: true, selector: "eg-form-switch", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, switchClass: { classPropertyName: "switchClass", publicName: "switchClass", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", 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: "\n @let lbl = label();\n @let cnm = controlName();\n @let hnt = hint();\n @let rqrd = required();\n\n <eg-form-field>\n <div class=\"flex items-center gap-1\">\n <hlm-switch\n [id]=\"effectiveId()\"\n [formControlName]=\"cnm\"\n [required]=\"rqrd\"\n [disabled]=\"disabled()\"\n [aria-describedby]=\"describedBy()\"\n [class]=\"$switchClass()\"\n />\n @if (lbl) {\n <label hlmLabel [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n </div>\n\n @if (showError()) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ resolvedError() }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </eg-form-field>\n ", isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: HlmError, selector: "hlm-error", inputs: ["class"] }, { kind: "directive", type: HlmHint, selector: "hlm-hint", inputs: ["class"] }, { kind: "directive", type: HlmLabel, selector: "[hlmLabel]", inputs: ["class"] }, { kind: "component", type: HlmSwitch, selector: "hlm-switch", inputs: ["class", "checked", "disabled", "id", "aria-label", "aria-labelledby", "aria-describedby"], outputs: ["checkedChange", "changed"] }, { kind: "component", type: EgFormField, selector: "eg-form-field", inputs: ["class"] }] });
76
105
  }
77
106
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormSwitch, decorators: [{
78
107
  type: Component,
@@ -84,9 +113,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
84
113
  },
85
114
  imports: [ReactiveFormsModule, HlmError, HlmHint, HlmLabel, HlmSwitch, EgFormField],
86
115
  providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }],
87
- template: "\n @let lbl = label();\n @let cnm = controlName();\n @let err = error();\n @let hnt = hint();\n @let rqrd = required();\n\n <eg-form-field>\n <div class=\"flex items-center gap-1\">\n <hlm-switch\n [id]=\"effectiveId()\"\n [formControlName]=\"cnm\"\n [required]=\"rqrd\"\n [disabled]=\"disabled()\"\n [aria-describedby]=\"describedBy()\"\n [class]=\"$switchClass()\"\n />\n @if (lbl) {\n <label hlmLabel [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n </div>\n\n @if (err) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ err }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </eg-form-field>\n ",
116
+ template: "\n @let lbl = label();\n @let cnm = controlName();\n @let hnt = hint();\n @let rqrd = required();\n\n <eg-form-field>\n <div class=\"flex items-center gap-1\">\n <hlm-switch\n [id]=\"effectiveId()\"\n [formControlName]=\"cnm\"\n [required]=\"rqrd\"\n [disabled]=\"disabled()\"\n [aria-describedby]=\"describedBy()\"\n [class]=\"$switchClass()\"\n />\n @if (lbl) {\n <label hlmLabel [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n </div>\n\n @if (showError()) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ resolvedError() }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </eg-form-field>\n ",
88
117
  }]
89
- }], 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 }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], switchClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "switchClass", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
118
+ }], 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 }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], switchClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "switchClass", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
90
119
 
91
120
  /*
92
121
  * Public API Surface of form-switch
@@ -4,12 +4,19 @@ import { ClassValue } from 'clsx';
4
4
 
5
5
  declare class EgFormSwitch {
6
6
  private readonly formGroupDirective;
7
+ private readonly _errorMessages;
7
8
  private readonly generatedId;
8
9
  private readonly _config;
9
10
  label: _angular_core.InputSignal<string | undefined>;
10
11
  controlId: _angular_core.InputSignal<string | undefined>;
11
12
  controlName: _angular_core.InputSignal<string>;
12
13
  error: _angular_core.InputSignal<string | undefined>;
14
+ /**
15
+ * Auto-resolve the displayed message from the control's `ValidationErrors`
16
+ * when `error()` is unset. Explicit `error()` always wins. Set to `false`
17
+ * for manual-only messages.
18
+ */
19
+ autoError: _angular_core.InputSignal<boolean>;
13
20
  hint: _angular_core.InputSignal<string | undefined>;
14
21
  id: _angular_core.InputSignal<string | undefined>;
15
22
  disabled: _angular_core.InputSignal<boolean>;
@@ -17,6 +24,19 @@ declare class EgFormSwitch {
17
24
  readonly effectiveId: _angular_core.Signal<string>;
18
25
  readonly errorId: _angular_core.Signal<string>;
19
26
  readonly hintId: _angular_core.Signal<string>;
27
+ /**
28
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
29
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
30
+ * computed): `ValidationErrors` is not a signal, so the control must be read
31
+ * fresh on every change-detection pass.
32
+ */
33
+ protected resolvedError(): string | undefined;
34
+ /**
35
+ * Whether the error is surfaced: message present + control invalid +
36
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
37
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
38
+ */
39
+ protected showError(): boolean;
20
40
  describedBy(): string | null;
21
41
  userClass: _angular_core.InputSignal<ClassValue>;
22
42
  switchClass: _angular_core.InputSignal<string>;
@@ -29,7 +49,7 @@ declare class EgFormSwitch {
29
49
  $errorClass: _angular_core.Signal<string>;
30
50
  $hintClass: _angular_core.Signal<string>;
31
51
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgFormSwitch, never>;
32
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormSwitch, "eg-form-switch", 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; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "switchClass": { "alias": "switchClass"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
52
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormSwitch, "eg-form-switch", 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; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "switchClass": { "alias": "switchClass"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
33
53
  }
34
54
 
35
55
  interface EgFormSwitchConfig {
@@ -75,32 +75,33 @@ Real selectors: `eg-form-text-input`, `hlm-form-field`, `label[hlmLabel]`, `inpu
75
75
 
76
76
  ### `eg-form-text-input` — `EgFormTextInput`
77
77
 
78
- | Input | Type | Default | Description |
79
- | --------------------- | -------------------------- | ----------- | ------------------------------------------------------------------------------------------------ |
80
- | `label` | `string \| undefined` | `undefined` | Field label rendered as `<label hlmLabel>` bound to the input id. |
81
- | `controlName` | `string` | `''` | **Required.** Control name in the parent `FormGroup`; forwarded as `formControlName` and `name`. |
82
- | `controlId` | `string \| undefined` | `undefined` | Explicit id; falls back to `id`, then generated `eg-form-text-input-…`. |
83
- | `id` | `string \| undefined` | `undefined` | Alias for an explicit id (same fallback chain). |
84
- | `error` | `string \| undefined` | `undefined` | Error text rendered in `<hlm-error>`. |
85
- | `hint` | `string \| undefined` | `undefined` | Hint text rendered in `<hlm-hint>`. |
86
- | `name` | `string \| undefined` | `undefined` | `name` attribute fallback when `controlName` is empty. |
87
- | `type` | `string` | `'text'` | Native input `type` (`text`, `email`, `password`, `number`, `tel`, `url`, …). |
88
- | `placeholder` | `string` | `''` | Placeholder text. |
89
- | `readonly` | `boolean` | `false` | Native `readonly` attribute. |
90
- | `disabled` | `boolean` | `false` | Wrapper-level disable (OR-ed with the reactive disabled state — see `effectiveDisabled()`). |
91
- | `maxlength` | `string \| number \| null` | `null` | Native `maxlength`. |
92
- | `minlength` | `string \| number \| null` | `null` | Native `minlength`. |
93
- | `max` | `string \| number \| null` | `null` | Native `max` (number/date inputs). |
94
- | `min` | `string \| number \| null` | `null` | Native `min` (number/date inputs). |
95
- | `pattern` | `string \| RegExp` | `''` | Native `pattern` attribute. |
96
- | `autocomplete` | `string \| undefined` | `undefined` | Native `autocomplete` (e.g. `email`, `current-password`). |
97
- | `autofocus` | `boolean` | `false` | Native `autofocus`. |
98
- | `required` | `boolean` | `false` | Native `required` + red `*` on the label. |
99
- | `class` (`userClass`) | `ClassValue` | `''` | Extra host classes (merged over `tw:flex tw:flex-col`). |
100
- | `labelClass` | `string` | `''` | Extra label classes (merged over `tw:mb-1 tw:gap-0`). |
101
- | `inputClass` | `string` | `''` | Extra input classes (merged over `tw:mb-1`). |
102
- | `errorClass` | `string` | `''` | Extra error classes (merged over `tw:mt-0`). |
103
- | `hintClass` | `string` | `''` | Extra hint classes (merged over `tw:mt-0`). |
78
+ | Input | Type | Default | Description |
79
+ | --------------------- | -------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
80
+ | `label` | `string \| undefined` | `undefined` | Field label rendered as `<label hlmLabel>` bound to the input id. |
81
+ | `controlName` | `string` | `''` | **Required.** Control name in the parent `FormGroup`; forwarded as `formControlName` and `name`. |
82
+ | `controlId` | `string \| undefined` | `undefined` | Explicit id; falls back to `id`, then generated `eg-form-text-input-…`. |
83
+ | `id` | `string \| undefined` | `undefined` | Alias for an explicit id (same fallback chain). |
84
+ | `error` | `string \| undefined` | `undefined` | Error text rendered in `<hlm-error>`. |
85
+ | `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`. |
86
+ | `hint` | `string \| undefined` | `undefined` | Hint text rendered in `<hlm-hint>`. |
87
+ | `name` | `string \| undefined` | `undefined` | `name` attribute fallback when `controlName` is empty. |
88
+ | `type` | `string` | `'text'` | Native input `type` (`text`, `email`, `password`, `number`, `tel`, `url`, …). |
89
+ | `placeholder` | `string` | `''` | Placeholder text. |
90
+ | `readonly` | `boolean` | `false` | Native `readonly` attribute. |
91
+ | `disabled` | `boolean` | `false` | Wrapper-level disable (OR-ed with the reactive disabled state — see `effectiveDisabled()`). |
92
+ | `maxlength` | `string \| number \| null` | `null` | Native `maxlength`. |
93
+ | `minlength` | `string \| number \| null` | `null` | Native `minlength`. |
94
+ | `max` | `string \| number \| null` | `null` | Native `max` (number/date inputs). |
95
+ | `min` | `string \| number \| null` | `null` | Native `min` (number/date inputs). |
96
+ | `pattern` | `string \| RegExp` | `''` | Native `pattern` attribute. |
97
+ | `autocomplete` | `string \| undefined` | `undefined` | Native `autocomplete` (e.g. `email`, `current-password`). |
98
+ | `autofocus` | `boolean` | `false` | Native `autofocus`. |
99
+ | `required` | `boolean` | `false` | Native `required` + red `*` on the label. |
100
+ | `class` (`userClass`) | `ClassValue` | `''` | Extra host classes (merged over `tw:flex tw:flex-col`). |
101
+ | `labelClass` | `string` | `''` | Extra label classes (merged over `tw:mb-1 tw:gap-0`). |
102
+ | `inputClass` | `string` | `''` | Extra input classes (merged over `tw:mb-1`). |
103
+ | `errorClass` | `string` | `''` | Extra error classes (merged over `tw:mt-0`). |
104
+ | `hintClass` | `string` | `''` | Extra hint classes (merged over `tw:mt-0`). |
104
105
 
105
106
  No outputs. Methods: `describedBy(): string | null` (error id when invalid + dirty/touched, else hint id, else `null`); `effectiveDisabled(): boolean` (`disabled()` OR the control's reactive disabled state — bound as the native `disabled` attribute). Readonly computeds: `effectiveId()`, `errorId()`, `hintId()`.
106
107