@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, 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 { HlmInput } from '@egose/shadcn-theme-ng/input';
8
8
  import { hlm } from '@egose/shadcn-theme-ng/utils';
@@ -17,6 +17,7 @@ function injectEgFormTextInputConfig() {
17
17
 
18
18
  class EgFormTextInput {
19
19
  formGroupDirective = inject(FormGroupDirective);
20
+ _errorMessages = injectEgFormErrorMessages();
20
21
  generatedId = inject(HlmFormIdGenerator).generate('eg-form-text-input');
21
22
  _config = injectEgFormTextInputConfig();
22
23
  label = input(undefined, /* @ts-ignore */
@@ -27,6 +28,13 @@ class EgFormTextInput {
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
  // HTML/input attributes
@@ -64,13 +72,34 @@ class EgFormTextInput {
64
72
  ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
65
73
  hintId = computed(() => `${this.effectiveId()}-hint`, /* @ts-ignore */
66
74
  ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
67
- describedBy() {
75
+ /**
76
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
77
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
78
+ * computed): `ValidationErrors` is not a signal, so the control must be read
79
+ * fresh on every change-detection pass.
80
+ */
81
+ resolvedError() {
82
+ const explicit = this.error();
83
+ if (explicit)
84
+ return explicit;
85
+ if (!this.autoError())
86
+ return undefined;
87
+ const control = this.formGroupDirective.form.get(this.controlName());
88
+ return resolveEgFormError(control?.errors ?? null, this.label(), this._errorMessages);
89
+ }
90
+ /**
91
+ * Whether the error is surfaced: message present + control invalid +
92
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
93
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
94
+ */
95
+ showError() {
68
96
  const control = this.formGroupDirective.form.get(this.controlName());
69
- return this.error() && control?.invalid && (control.dirty || control.touched)
70
- ? this.errorId()
71
- : this.hint()
72
- ? this.hintId()
73
- : null;
97
+ return (!!this.resolvedError() &&
98
+ !!control?.invalid &&
99
+ (control.dirty || control.touched || this.formGroupDirective.submitted));
100
+ }
101
+ describedBy() {
102
+ return this.showError() ? this.errorId() : this.hint() ? this.hintId() : null;
74
103
  }
75
104
  effectiveDisabled() {
76
105
  return this.disabled() || !!this.formGroupDirective.form.get(this.controlName())?.disabled;
@@ -97,7 +126,7 @@ class EgFormTextInput {
97
126
  $hintClass = computed(() => hlm("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: EgFormTextInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
100
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormTextInput, isStandalone: true, selector: "eg-form-text-input", 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 }, type: { classPropertyName: "type", publicName: "type", 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 }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", 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 }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", 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: "\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 [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <input\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$inputClass()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [max]=\"max()\"\n [min]=\"min()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [pattern]=\"pattern()\"\n [autocomplete]=\"autocomplete()\"\n [autofocus]=\"autofocus()\"\n [required]=\"rqrd\"\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.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { 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.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { 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: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }] });
129
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormTextInput, isStandalone: true, selector: "eg-form-text-input", 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 }, type: { classPropertyName: "type", publicName: "type", 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 }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", 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 }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", 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: "\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 [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <input\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$inputClass()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [max]=\"max()\"\n [min]=\"min()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [pattern]=\"pattern()\"\n [autocomplete]=\"autocomplete()\"\n [autofocus]=\"autofocus()\"\n [required]=\"rqrd\"\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.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { 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.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { 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: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }] });
101
130
  }
102
131
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormTextInput, decorators: [{
103
132
  type: Component,
@@ -109,9 +138,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
109
138
  },
110
139
  imports: [ReactiveFormsModule, HlmFormField, HlmError, HlmHint, HlmLabel, HlmInput],
111
140
  providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }],
112
- 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 [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <input\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$inputClass()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [max]=\"max()\"\n [min]=\"min()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [pattern]=\"pattern()\"\n [autocomplete]=\"autocomplete()\"\n [autofocus]=\"autofocus()\"\n [required]=\"rqrd\"\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 ",
141
+ 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 [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <input\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$inputClass()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [max]=\"max()\"\n [min]=\"min()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [pattern]=\"pattern()\"\n [autocomplete]=\"autocomplete()\"\n [autofocus]=\"autofocus()\"\n [required]=\"rqrd\"\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 ",
113
142
  }]
114
- }], 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 }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", 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 }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], minlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minlength", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", 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 }] }] } });
143
+ }], 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 }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", 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 }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], minlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minlength", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", 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 }] }] } });
115
144
 
116
145
  /*
117
146
  * Public API Surface of form-text-input
@@ -4,12 +4,19 @@ import { ClassValue } from 'clsx';
4
4
 
5
5
  declare class EgFormTextInput {
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
  name: _angular_core.InputSignal<string | undefined>;
@@ -28,6 +35,19 @@ declare class EgFormTextInput {
28
35
  readonly effectiveId: _angular_core.Signal<string>;
29
36
  readonly errorId: _angular_core.Signal<string>;
30
37
  readonly hintId: _angular_core.Signal<string>;
38
+ /**
39
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
40
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
41
+ * computed): `ValidationErrors` is not a signal, so the control must be read
42
+ * fresh on every change-detection pass.
43
+ */
44
+ protected resolvedError(): string | undefined;
45
+ /**
46
+ * Whether the error is surfaced: message present + control invalid +
47
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
48
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
49
+ */
50
+ protected showError(): boolean;
31
51
  describedBy(): string | null;
32
52
  effectiveDisabled(): boolean;
33
53
  userClass: _angular_core.InputSignal<ClassValue>;
@@ -41,7 +61,7 @@ declare class EgFormTextInput {
41
61
  $errorClass: _angular_core.Signal<string>;
42
62
  $hintClass: _angular_core.Signal<string>;
43
63
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgFormTextInput, never>;
44
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormTextInput, "eg-form-text-input", 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; }; "type": { "alias": "type"; "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; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "minlength": { "alias": "minlength"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "pattern": { "alias": "pattern"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "autofocus": { "alias": "autofocus"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "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>;
64
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormTextInput, "eg-form-text-input", 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; }; "type": { "alias": "type"; "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; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "minlength": { "alias": "minlength"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "pattern": { "alias": "pattern"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "autofocus": { "alias": "autofocus"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "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>;
45
65
  }
46
66
 
47
67
  interface EgFormTextInputConfig {
@@ -75,28 +75,29 @@ Real selectors: `eg-form-textarea`, `hlm-form-field`, `label[hlmLabel]`, `textar
75
75
 
76
76
  ### `eg-form-textarea` — `EgFormTextarea`
77
77
 
78
- | Input | Type | Default | Description |
79
- | --------------------- | ------------------------------- | ----------- | ------------------------------------------------------------------------------------------------ |
80
- | `label` | `string \| undefined` | `undefined` | Field label rendered as `<label hlmLabel>` bound to the textarea 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-textarea-…`. |
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
- | `placeholder` | `string` | `''` | Placeholder text. |
88
- | `readonly` | `boolean` | `false` | Native `readonly` attribute. |
89
- | `disabled` | `boolean` | `false` | Wrapper-level disable (OR-ed with the reactive disabled state — see `effectiveDisabled()`). |
90
- | `maxlength` | `string \| number \| null` | `null` | Native `maxlength`. |
91
- | `minlength` | `string \| number \| null` | `null` | Native `minlength`. |
92
- | `required` | `boolean` | `false` | Native `required` + red `*` on the label. |
93
- | `rows` | `string \| number \| undefined` | `3` | Native `rows` (visible height). |
94
- | `cols` | `string \| number \| undefined` | `undefined` | Native `cols` (visible width). |
95
- | `class` (`userClass`) | `ClassValue` | `''` | Extra host classes (merged over `tw:w-full`). |
96
- | `labelClass` | `string` | `''` | Extra label classes (merged over `tw:mb-1 tw:gap-0`). |
97
- | `textareaClass` | `string` | `''` | Extra textarea classes (merged over `tw:mb-1`). |
98
- | `errorClass` | `string` | `''` | Extra error classes (merged over `tw:mt-0`). |
99
- | `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 textarea 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-textarea-…`. |
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
+ | `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
+ | `required` | `boolean` | `false` | Native `required` + red `*` on the label. |
94
+ | `rows` | `string \| number \| undefined` | `3` | Native `rows` (visible height). |
95
+ | `cols` | `string \| number \| undefined` | `undefined` | Native `cols` (visible width). |
96
+ | `class` (`userClass`) | `ClassValue` | `''` | Extra host classes (merged over `tw:w-full`). |
97
+ | `labelClass` | `string` | `''` | Extra label classes (merged over `tw:mb-1 tw:gap-0`). |
98
+ | `textareaClass` | `string` | `''` | Extra textarea classes (merged over `tw:mb-1`). |
99
+ | `errorClass` | `string` | `''` | Extra error classes (merged over `tw:mt-0`). |
100
+ | `hintClass` | `string` | `''` | Extra hint classes (merged over `tw:mt-0`). |
100
101
 
101
102
  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). Readonly computeds: `effectiveId()`, `errorId()`, `hintId()`.
102
103
 
@@ -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/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 { HlmInput } from '@egose/shadcn-theme-ng/input';
8
8
  import { hlm } from '@egose/shadcn-theme-ng/utils';
@@ -17,6 +17,7 @@ function injectEgFormTextareaConfig() {
17
17
 
18
18
  class EgFormTextarea {
19
19
  formGroupDirective = inject(FormGroupDirective);
20
+ _errorMessages = injectEgFormErrorMessages();
20
21
  generatedId = inject(HlmFormIdGenerator).generate('eg-form-textarea');
21
22
  _config = injectEgFormTextareaConfig();
22
23
  // General props
@@ -28,6 +29,13 @@ class EgFormTextarea {
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
  // HTML/textarea attributes
@@ -57,13 +65,34 @@ class EgFormTextarea {
57
65
  ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
58
66
  hintId = computed(() => `${this.effectiveId()}-hint`, /* @ts-ignore */
59
67
  ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
60
- describedBy() {
68
+ /**
69
+ * Displayed message: explicit `error()` wins; otherwise (when `autoError()`)
70
+ * auto-resolved from the control's `ValidationErrors`. Plain method (not a
71
+ * computed): `ValidationErrors` is not a signal, so the control must be read
72
+ * fresh on every change-detection pass.
73
+ */
74
+ resolvedError() {
75
+ const explicit = this.error();
76
+ if (explicit)
77
+ return explicit;
78
+ if (!this.autoError())
79
+ return undefined;
80
+ const control = this.formGroupDirective.form.get(this.controlName());
81
+ return resolveEgFormError(control?.errors ?? null, this.label(), this._errorMessages);
82
+ }
83
+ /**
84
+ * Whether the error is surfaced: message present + control invalid +
85
+ * touched/dirty/submitted. Gates the visual `<hlm-error>` (and
86
+ * `describedBy()`, where present) so sighted and screen-reader output agree.
87
+ */
88
+ showError() {
61
89
  const control = this.formGroupDirective.form.get(this.controlName());
62
- return this.error() && control?.invalid && (control.dirty || control.touched)
63
- ? this.errorId()
64
- : this.hint()
65
- ? this.hintId()
66
- : null;
90
+ return (!!this.resolvedError() &&
91
+ !!control?.invalid &&
92
+ (control.dirty || control.touched || this.formGroupDirective.submitted));
93
+ }
94
+ describedBy() {
95
+ return this.showError() ? this.errorId() : this.hint() ? this.hintId() : null;
67
96
  }
68
97
  effectiveDisabled() {
69
98
  return this.disabled() || !!this.formGroupDirective.form.get(this.controlName())?.disabled;
@@ -90,7 +119,7 @@ class EgFormTextarea {
90
119
  $hintClass = computed(() => hlm("mt-0", this._config.hintClass, this.hintClass()), /* @ts-ignore */
91
120
  ...(ngDevMode ? [{ debugName: "$hintClass" }] : /* istanbul ignore next */ []));
92
121
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
93
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormTextarea, isStandalone: true, selector: "eg-form-textarea", 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 }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, cols: { classPropertyName: "cols", publicName: "cols", 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 }, textareaClass: { classPropertyName: "textareaClass", publicName: "textareaClass", 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 [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <textarea\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$textareaClass()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [required]=\"rqrd\"\n [rows]=\"rows()\"\n [cols]=\"cols()\"\n ></textarea>\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.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { 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.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { 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: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }] });
122
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormTextarea, isStandalone: true, selector: "eg-form-textarea", 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 }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, cols: { classPropertyName: "cols", publicName: "cols", 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 }, textareaClass: { classPropertyName: "textareaClass", publicName: "textareaClass", 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 [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <textarea\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$textareaClass()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [required]=\"rqrd\"\n [rows]=\"rows()\"\n [cols]=\"cols()\"\n ></textarea>\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.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { 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.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { 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: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }] });
94
123
  }
95
124
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormTextarea, decorators: [{
96
125
  type: Component,
@@ -102,9 +131,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
102
131
  },
103
132
  imports: [ReactiveFormsModule, HlmFormField, HlmError, HlmHint, HlmLabel, HlmInput],
104
133
  providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }],
105
- 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 [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <textarea\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$textareaClass()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [required]=\"rqrd\"\n [rows]=\"rows()\"\n [cols]=\"cols()\"\n ></textarea>\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 ",
134
+ 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 [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <textarea\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$textareaClass()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [required]=\"rqrd\"\n [rows]=\"rows()\"\n [cols]=\"cols()\"\n ></textarea>\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 ",
106
135
  }]
107
- }], 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 }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], minlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minlength", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], cols: [{ type: i0.Input, args: [{ isSignal: true, alias: "cols", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], textareaClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "textareaClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
136
+ }], 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 }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], minlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minlength", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], cols: [{ type: i0.Input, args: [{ isSignal: true, alias: "cols", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], textareaClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "textareaClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
108
137
 
109
138
  /*
110
139
  * Public API Surface of form-textarea
@@ -4,12 +4,19 @@ import { ClassValue } from 'clsx';
4
4
 
5
5
  declare class EgFormTextarea {
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
  name: _angular_core.InputSignal<string | undefined>;
@@ -24,6 +31,19 @@ declare class EgFormTextarea {
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
  effectiveDisabled(): boolean;
29
49
  userClass: _angular_core.InputSignal<ClassValue>;
@@ -37,7 +57,7 @@ declare class EgFormTextarea {
37
57
  $errorClass: _angular_core.Signal<string>;
38
58
  $hintClass: _angular_core.Signal<string>;
39
59
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgFormTextarea, never>;
40
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormTextarea, "eg-form-textarea", 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; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "minlength": { "alias": "minlength"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "cols": { "alias": "cols"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "textareaClass": { "alias": "textareaClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
60
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormTextarea, "eg-form-textarea", 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; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "minlength": { "alias": "minlength"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "cols": { "alias": "cols"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "textareaClass": { "alias": "textareaClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
41
61
  }
42
62
 
43
63
  interface EgFormTextareaConfig {
@@ -77,22 +77,23 @@ Selector (from source): `eg-form-toggle` (standalone component, host `tw:w-full`
77
77
 
78
78
  Bind `formControlName` on the element; there is no `controlName` input.
79
79
 
80
- | Input | Type | Default | Description |
81
- | ------------- | --------------------------- | ----------- | --------------------------------------------------- |
82
- | `label` | `string \| undefined` | — | Label text beside the toggle (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
- | `disabled` | `boolean` | `false` | Locks interaction (form control stays enabled). |
88
- | `required` | `boolean` | `false` | Shows a red `*` next to the label. |
89
- | `variant` | `'default' \| 'outline'` | `'default'` | Toggle variant forwarded to `hlmToggle`. |
90
- | `size` | `'default' \| 'sm' \| 'lg'` | `'default'` | Toggle size forwarded to `hlmToggle`. |
91
- | `class` | `ClassValue` | `''` | Extra host classes (base `tw:w-full`). |
92
- | `toggleClass` | `string` | `''` | Extra toggle-button classes. |
93
- | `labelClass` | `string` | `''` | Extra label classes. |
94
- | `errorClass` | `string` | `''` | Extra error classes (base `tw:mt-0`). |
95
- | `hintClass` | `string` | `''` | Extra hint classes (base `tw:mt-0`). |
80
+ | Input | Type | Default | Description |
81
+ | ------------- | --------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
82
+ | `label` | `string \| undefined` | — | Label text beside the toggle (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
+ | `disabled` | `boolean` | `false` | Locks interaction (form control stays enabled). |
89
+ | `required` | `boolean` | `false` | Shows a red `*` next to the label. |
90
+ | `variant` | `'default' \| 'outline'` | `'default'` | Toggle variant forwarded to `hlmToggle`. |
91
+ | `size` | `'default' \| 'sm' \| 'lg'` | `'default'` | Toggle size forwarded to `hlmToggle`. |
92
+ | `class` | `ClassValue` | `''` | Extra host classes (base `tw:w-full`). |
93
+ | `toggleClass` | `string` | `''` | Extra toggle-button classes. |
94
+ | `labelClass` | `string` | `''` | Extra label 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
  | -------------------- | ------------------------------------------------------------------------------ |