ng-hub-ui-forms 22.30.0 → 22.32.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ng-hub-ui-forms",
3
- "version": "22.30.0",
3
+ "version": "22.32.0",
4
4
  "license": "MIT",
5
5
  "description": "Accessible, signal-based form fields for Angular (input, textarea, slider, segmented, select, datepicker, file input with drag & drop and upload progress) with automatic error display for controls, FormGroups and FormArrays. Reactive Forms today, Signal Forms ready. Part of the ng-hub-ui family.",
6
6
  "author": "Carlos Morcillo <carlos.morcillo@me.com> (https://www.carlosmorcillo.com)",
@@ -37,7 +37,7 @@
37
37
  "@angular/core": ">=21.0.0",
38
38
  "@angular/forms": ">=21.0.0",
39
39
  "@angular/platform-browser": ">=21.0.0",
40
- "ng-hub-ui-utils": ">=22.11.0"
40
+ "ng-hub-ui-utils": ">=22.12.0"
41
41
  },
42
42
  "dependencies": {
43
43
  "tslib": "^2.3.0"
@@ -47,10 +47,21 @@ hub-timepicker {
47
47
 
48
48
  // Label sits in the first column, aligned to the control row. It is capped
49
49
  // at the max width and ellipsizes when its text is longer.
50
- > .hub-field__label {
50
+ //
51
+ // Two selectors because the label is not always a direct child: with
52
+ // `formTextType="tooltip"` it shares a `__label-row` with the hint trigger.
53
+ // Whichever of the two the grid actually lays out takes the column and the cap;
54
+ // the ellipsis always belongs to the label, wrapped or not.
55
+ > .hub-field__label,
56
+ > .hub-field__label-row {
51
57
  grid-column: 1;
52
- display: block;
53
58
  max-width: var(--hub-form-label-horizontal-max-width);
59
+ }
60
+
61
+ > .hub-field__label,
62
+ > .hub-field__label-row > .hub-field__label {
63
+ display: block;
64
+ min-width: 0;
54
65
  overflow: hidden;
55
66
  white-space: nowrap;
56
67
  text-overflow: ellipsis;
@@ -77,11 +88,86 @@ hub-timepicker {
77
88
  font-weight: var(--hub-label-font-weight);
78
89
  }
79
90
 
91
+ /**
92
+ * Label row: the label at one end, the helper-text trigger at the other.
93
+ *
94
+ * Only rendered when a field asks for `formTextType="tooltip"`. The label stays a
95
+ * direct child of `.hub-field` in every other case, because that is what the
96
+ * horizontal grid and a good deal of existing markup address.
97
+ *
98
+ * The mark is pushed to the end with an auto margin rather than with
99
+ * `justify-content: space-between`, which only separates two children: a floating-label
100
+ * field puts the hint in the row on its own, and space-between would leave it hanging at
101
+ * the start. The auto margin sends it to the end either way, so a column of fields lines
102
+ * its question marks up instead of scattering them wherever each label happens to stop.
103
+ */
104
+ &__label-row {
105
+ display: flex;
106
+ align-items: center;
107
+ gap: var(--hub-form-field-gap);
108
+
109
+ > .hub-field__label {
110
+ min-width: 0;
111
+ }
112
+
113
+ > .hub-field__hint {
114
+ margin-inline-start: auto;
115
+ }
116
+ }
117
+
80
118
  &__required {
81
119
  color: var(--hub-form-required-color);
82
120
  }
83
121
 
84
- &--disabled .hub-field__label {
122
+ /**
123
+ * The helper-text trigger — a question mark in a circle.
124
+ *
125
+ * A `<button>`, and deliberately outside the `<label>`: activating a label focuses
126
+ * the control it names, so a trigger nested in one would fire the tooltip *and*
127
+ * jump the caret into the field. Its accessible name is the helper text itself, so
128
+ * a screen reader gets what a pointer gets from hovering, without waiting for a
129
+ * tooltip it cannot see.
130
+ */
131
+ &__hint {
132
+ flex: none;
133
+ display: inline-flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ inline-size: var(--hub-form-hint-size);
137
+ block-size: var(--hub-form-hint-size);
138
+ padding: 0;
139
+ color: var(--hub-form-hint-color);
140
+ background-color: var(--hub-form-hint-bg);
141
+ border: var(--hub-form-hint-border-width) solid var(--hub-form-hint-border-color);
142
+ border-radius: 50%;
143
+ font-family: inherit;
144
+ font-size: var(--hub-form-hint-font-size);
145
+ font-weight: var(--hub-form-hint-font-weight);
146
+ line-height: 1;
147
+ cursor: help;
148
+ transition: var(--hub-form-transition);
149
+
150
+ // The glyph is decorative: the button already carries the text as its name, and
151
+ // an `aria-label` overrides generated content anyway.
152
+ &::before {
153
+ content: '?';
154
+ }
155
+
156
+ &:hover {
157
+ color: var(--hub-form-hint-hover-color);
158
+ background-color: var(--hub-form-hint-hover-bg);
159
+ border-color: var(--hub-form-hint-hover-border-color);
160
+ }
161
+
162
+ &:focus-visible {
163
+ outline: 0;
164
+ color: var(--hub-form-hint-hover-color);
165
+ box-shadow: 0 0 0 var(--hub-form-focus-ring-width) var(--hub-form-focus-ring-color);
166
+ }
167
+ }
168
+
169
+ &--disabled .hub-field__label,
170
+ &--disabled .hub-field__hint {
85
171
  opacity: var(--hub-form-disabled-opacity);
86
172
  }
87
173
  }
@@ -40,6 +40,26 @@
40
40
  --hub-form-text-font-size: var(--hub-ref-font-size-sm, 0.875rem);
41
41
  --hub-form-text-margin-top: var(--hub-ref-space-1, 0.25rem);
42
42
 
43
+ // ── Helper-text tooltip trigger (`formTextType="tooltip"`) ───────────────
44
+ // The question mark that stands at the end of the label row. Drawn from these
45
+ // tokens rather than from an icon font: `ng-hub-ui-icons` is not a dependency of
46
+ // this package, and taking one on for a single glyph would make every consumer of
47
+ // a text input install an icon set.
48
+ //
49
+ // Sized in `em` of the label, not in `rem`: the mark belongs to the label it sits
50
+ // beside, so a form that scales its labels down scales the mark with them instead
51
+ // of leaving a circle that grows relative to the words next to it.
52
+ --hub-form-hint-size: 1.15em;
53
+ --hub-form-hint-font-size: var(--hub-ref-font-size-xs, 0.75rem);
54
+ --hub-form-hint-font-weight: var(--hub-ref-font-weight-bold, 700);
55
+ --hub-form-hint-color: var(--hub-sys-text-muted, #6c757d);
56
+ --hub-form-hint-bg: transparent;
57
+ --hub-form-hint-border-width: 1px;
58
+ --hub-form-hint-border-color: var(--hub-sys-border-color-default, #dee2e6);
59
+ --hub-form-hint-hover-color: var(--hub-sys-text-primary, #212529);
60
+ --hub-form-hint-hover-bg: var(--hub-sys-surface-elevated, #f8f9fa);
61
+ --hub-form-hint-hover-border-color: var(--hub-sys-border-color-default, #dee2e6);
62
+
43
63
  --hub-form-focus-ring-width: var(--hub-sys-focus-ring-width, 0.25rem);
44
64
  --hub-form-focus-ring-color: var(--hub-sys-focus-ring-color, rgba(13, 110, 253, 0.25));
45
65
 
package/styles/index.scss CHANGED
@@ -7,6 +7,13 @@
7
7
  //
8
8
  // // styles.scss
9
9
  // @use 'ng-hub-ui-forms/styles';
10
+ //
11
+ // Fields using `formTextType="tooltip"` also need the tooltip's own sheet, which
12
+ // ships with `ng-hub-ui-utils`: the tooltip element is appended to `<body>`, out of
13
+ // reach of anything declared here. Without it the mark still works and still speaks
14
+ // to a screen reader, but the label it opens is unstyled.
15
+ //
16
+ // @use 'ng-hub-ui-utils/styles/tooltip';
10
17
  // ─────────────────────────────────────────────────────────────────────────
11
18
 
12
19
  @use 'tokens';
@@ -58,6 +58,30 @@ declare abstract class HubFormControl implements OnInit, AfterContentInit, OnDes
58
58
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<HubFormControl, never, never, { "formControlName": { "alias": "formControlName"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; }, { "required": "requiredChange"; }, never, never, true, never>;
59
59
  }
60
60
 
61
+ /**
62
+ * Possible display types for form helper text.
63
+ */
64
+ type FormTextType = 'bottom' | 'tooltip';
65
+ /**
66
+ * Enum for form helper text display types.
67
+ */
68
+ declare enum FormTextTypes {
69
+ Bottom = "bottom",
70
+ Tooltip = "tooltip"
71
+ }
72
+ /**
73
+ * Possible label display types shared by the form field components.
74
+ */
75
+ type HubLabelType = 'floating' | 'stacked' | 'horizontal';
76
+ /**
77
+ * Enum for label display types.
78
+ */
79
+ declare enum HubLabelTypes {
80
+ Floating = "floating",
81
+ Stacked = "stacked",
82
+ Horizontal = "horizontal"
83
+ }
84
+
61
85
  /**
62
86
  * Marks a template as the validation error message for a specific error key.
63
87
  *
@@ -108,6 +132,17 @@ declare abstract class HubFieldControl extends HubFormControl implements Control
108
132
  readonly id: string;
109
133
  /** Query for a projected `hubFormText` helper template. */
110
134
  readonly formTextTmp: _angular_core.Signal<TemplateRef<any> | undefined>;
135
+ /** Helper text for the field. Where it is shown is {@link formTextType}'s business. */
136
+ readonly formText: _angular_core.InputSignal<string>;
137
+ /**
138
+ * Where the helper text is shown: under the control (`bottom`, the default) or behind
139
+ * a question mark at the end of the label row (`tooltip`).
140
+ *
141
+ * The rule the product settled on: one sentence goes below, where it is read without
142
+ * being asked for; anything longer goes in the tooltip, because a paragraph under
143
+ * every field turns a form into a document and pushes the next field off the screen.
144
+ */
145
+ readonly formTextType: _angular_core.InputSignal<FormTextType>;
111
146
  /** Query for projected `hubValidationError` templates. */
112
147
  readonly errorTpts: _angular_core.Signal<readonly HubValidationErrorDirective[]>;
113
148
  /** Whether the field is disabled. */
@@ -123,6 +158,16 @@ declare abstract class HubFieldControl extends HubFormControl implements Control
123
158
  readonly showValid: _angular_core.InputSignal<boolean>;
124
159
  /** Optional success message shown below the control while {@link showsValid}. */
125
160
  readonly validFeedback: _angular_core.InputSignal<string | null>;
161
+ /**
162
+ * Whether the helper text is carried by the label-row trigger instead of the block
163
+ * below the control.
164
+ *
165
+ * Gated on `formText()` having content, and that is the whole reason a projected
166
+ * `hubFormText` template still renders below in tooltip mode: the tooltip takes a
167
+ * string, so asking it to carry markup would drop the markup silently. A field with
168
+ * a template keeps its helper text where the template can actually be shown.
169
+ */
170
+ protected readonly showsFormTextTooltip: _angular_core.Signal<boolean>;
126
171
  onChange: (value: any) => void;
127
172
  onTouched: () => void;
128
173
  protected readonly _nativeErrors: _angular_core.WritableSignal<ValidationErrors | null>;
@@ -162,7 +207,7 @@ declare abstract class HubFieldControl extends HubFormControl implements Control
162
207
  */
163
208
  protected updateNativeErrors(target?: EventTarget | null): void;
164
209
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubFieldControl, never>;
165
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<HubFieldControl, never, never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalidFeedbackTemplateFn": { "alias": "invalidFeedbackTemplateFn"; "required": false; "isSignal": true; }; "showValid": { "alias": "showValid"; "required": false; "isSignal": true; }; "validFeedback": { "alias": "validFeedback"; "required": false; "isSignal": true; }; }, { "disabled": "disabledChange"; }, ["formTextTmp", "errorTpts"], never, true, never>;
210
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<HubFieldControl, never, never, { "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalidFeedbackTemplateFn": { "alias": "invalidFeedbackTemplateFn"; "required": false; "isSignal": true; }; "showValid": { "alias": "showValid"; "required": false; "isSignal": true; }; "validFeedback": { "alias": "validFeedback"; "required": false; "isSignal": true; }; }, { "disabled": "disabledChange"; }, ["formTextTmp", "errorTpts"], never, true, never>;
166
211
  }
167
212
 
168
213
  /** When a container reveals its group-level validation errors. */
@@ -651,30 +696,6 @@ declare const HUB_FILE_UPLOADER: InjectionToken<HubFileUploader>;
651
696
  */
652
697
  declare function provideHubFileUploader(uploader: HubFileUploader | Type<HubFileUploader>): EnvironmentProviders;
653
698
 
654
- /**
655
- * Possible display types for form helper text.
656
- */
657
- type FormTextType = 'bottom' | 'tooltip';
658
- /**
659
- * Enum for form helper text display types.
660
- */
661
- declare enum FormTextTypes {
662
- Bottom = "bottom",
663
- Tooltip = "tooltip"
664
- }
665
- /**
666
- * Possible label display types shared by the form field components.
667
- */
668
- type HubLabelType = 'floating' | 'stacked' | 'horizontal';
669
- /**
670
- * Enum for label display types.
671
- */
672
- declare enum HubLabelTypes {
673
- Floating = "floating",
674
- Stacked = "stacked",
675
- Horizontal = "horizontal"
676
- }
677
-
678
699
  /**
679
700
  * Projects content into the **inline-start** affix area of a `<hub-input>` (left in
680
701
  * LTR, right in RTL). Use it for a leading icon — a `<hub-icon>`, currency symbol,
@@ -743,7 +764,6 @@ declare class HubInputComponent extends HubFieldControl {
743
764
  #private;
744
765
  protected readonly _inputFormats: typeof HubInputFormats;
745
766
  protected readonly _labelTypes: typeof HubLabelTypes;
746
- protected readonly _formTextTypes: typeof FormTextTypes;
747
767
  protected readonly _value: _angular_core.WritableSignal<HubInputValue>;
748
768
  /**
749
769
  * Whether the password value is currently revealed (password format only). Two-way
@@ -809,10 +829,6 @@ declare class HubInputComponent extends HubFieldControl {
809
829
  * invisible input.
810
830
  */
811
831
  readonly plaintext: _angular_core.InputSignalWithTransform<boolean, unknown>;
812
- /** Helper text shown below the control. */
813
- readonly formText: _angular_core.InputSignal<string>;
814
- /** Helper text placement. Only `bottom` is supported. */
815
- readonly formTextType: _angular_core.InputSignal<FormTextType>;
816
832
  /** Text shown before the control as an input-group addon (text-like formats). */
817
833
  readonly prepend: _angular_core.InputSignal<string | string[]>;
818
834
  /** Text shown after the control as an input-group addon (text-like formats). */
@@ -963,7 +979,7 @@ declare class HubInputComponent extends HubFieldControl {
963
979
  /** Clears the selected file(s). */
964
980
  protected clearFile(): void;
965
981
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubInputComponent, never>;
966
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubInputComponent, "hub-input", never, { "passwordRevealed": { "alias": "passwordRevealed"; "required": false; "isSignal": true; }; "passwordToggle": { "alias": "passwordToggle"; "required": false; "isSignal": true; }; "hideOnBlur": { "alias": "hideOnBlur"; "required": false; "isSignal": true; }; "capsLockWarning": { "alias": "capsLockWarning"; "required": false; "isSignal": true; }; "passwordStrength": { "alias": "passwordStrength"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "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; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "plaintext": { "alias": "plaintext"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; "mask": { "alias": "mask"; "required": false; "isSignal": true; }; "unmaskValue": { "alias": "unmaskValue"; "required": false; "isSignal": true; }; "debounceTime": { "alias": "debounceTime"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "buttonLabel": { "alias": "buttonLabel"; "required": false; "isSignal": true; }; }, { "passwordRevealed": "passwordRevealedChange"; "labelType": "labelTypeChange"; "placeholder": "placeholderChange"; "min": "minChange"; "max": "maxChange"; "indeterminate": "indeterminateChange"; "valueChange": "valueChange"; "enter": "enter"; "search": "search"; }, ["prefixDir", "suffixDir", "_prependTpl", "_appendTpl"], ["[hubInputPrefix]", "[hubInputSuffix]"], true, never>;
982
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubInputComponent, "hub-input", never, { "passwordRevealed": { "alias": "passwordRevealed"; "required": false; "isSignal": true; }; "passwordToggle": { "alias": "passwordToggle"; "required": false; "isSignal": true; }; "hideOnBlur": { "alias": "hideOnBlur"; "required": false; "isSignal": true; }; "capsLockWarning": { "alias": "capsLockWarning"; "required": false; "isSignal": true; }; "passwordStrength": { "alias": "passwordStrength"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "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; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "plaintext": { "alias": "plaintext"; "required": false; "isSignal": true; }; "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; "mask": { "alias": "mask"; "required": false; "isSignal": true; }; "unmaskValue": { "alias": "unmaskValue"; "required": false; "isSignal": true; }; "debounceTime": { "alias": "debounceTime"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "buttonLabel": { "alias": "buttonLabel"; "required": false; "isSignal": true; }; }, { "passwordRevealed": "passwordRevealedChange"; "labelType": "labelTypeChange"; "placeholder": "placeholderChange"; "min": "minChange"; "max": "maxChange"; "indeterminate": "indeterminateChange"; "valueChange": "valueChange"; "enter": "enter"; "search": "search"; }, ["prefixDir", "suffixDir", "_prependTpl", "_appendTpl"], ["[hubInputPrefix]", "[hubInputSuffix]"], true, never>;
967
983
  }
968
984
 
969
985
  /** Character set accepted by the OTP field. */
@@ -982,7 +998,6 @@ type HubOtpMode = 'numeric' | 'alphanumeric' | 'alpha';
982
998
  declare class HubOtpInputComponent extends HubFieldControl {
983
999
  #private;
984
1000
  protected readonly _labelTypes: typeof HubLabelTypes;
985
- protected readonly _formTextTypes: typeof FormTextTypes;
986
1001
  /** Number of cells / characters in the code. */
987
1002
  readonly length: _angular_core.InputSignalWithTransform<number, unknown>;
988
1003
  /** Accepted character set. */
@@ -991,10 +1006,6 @@ declare class HubOtpInputComponent extends HubFieldControl {
991
1006
  readonly label: _angular_core.InputSignal<string>;
992
1007
  /** Label placement. */
993
1008
  readonly labelType: _angular_core.InputSignal<HubLabelType>;
994
- /** Helper text shown below the cells. */
995
- readonly formText: _angular_core.InputSignal<string>;
996
- /** Helper-text placement. */
997
- readonly formTextType: _angular_core.InputSignal<FormTextType>;
998
1009
  /** Masks the characters like a password. */
999
1010
  readonly secret: _angular_core.InputSignalWithTransform<boolean, unknown>;
1000
1011
  /** Renders the cells read-only. */
@@ -1029,7 +1040,7 @@ declare class HubOtpInputComponent extends HubFieldControl {
1029
1040
  /** Marks the field as touched when focus leaves the whole group. */
1030
1041
  protected onFocusOut(event: FocusEvent): void;
1031
1042
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubOtpInputComponent, never>;
1032
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubOtpInputComponent, "hub-otp-input", never, { "length": { "alias": "length"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "secret": { "alias": "secret"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "separatorEvery": { "alias": "separatorEvery"; "required": false; "isSignal": true; }; "separator": { "alias": "separator"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "completed": "completed"; }, never, never, true, never>;
1043
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubOtpInputComponent, "hub-otp-input", never, { "length": { "alias": "length"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "secret": { "alias": "secret"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "separatorEvery": { "alias": "separatorEvery"; "required": false; "isSignal": true; }; "separator": { "alias": "separator"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "completed": "completed"; }, never, never, true, never>;
1033
1044
  }
1034
1045
 
1035
1046
  /**
@@ -1061,7 +1072,6 @@ declare class HubTextareaComponent extends HubFieldControl {
1061
1072
  protected readonly hasPrepend: _angular_core.Signal<boolean>;
1062
1073
  protected readonly hasAppend: _angular_core.Signal<boolean>;
1063
1074
  protected readonly _labelTypes: typeof HubLabelTypes;
1064
- protected readonly _formTextTypes: typeof FormTextTypes;
1065
1075
  protected readonly _value: _angular_core.WritableSignal<string>;
1066
1076
  /** Label text. */
1067
1077
  readonly label: _angular_core.InputSignal<string>;
@@ -1090,10 +1100,6 @@ declare class HubTextareaComponent extends HubFieldControl {
1090
1100
  * selectable, and it only loses the box. Implies `readonly`.
1091
1101
  */
1092
1102
  readonly plaintext: _angular_core.InputSignalWithTransform<boolean, unknown>;
1093
- /** Helper text shown below the control. */
1094
- readonly formText: _angular_core.InputSignal<string>;
1095
- /** Helper text placement. Only `bottom` is supported in the MVP. */
1096
- readonly formTextType: _angular_core.InputSignal<FormTextType>;
1097
1103
  /** Extra CSS classes applied to the host element. */
1098
1104
  readonly classlist: _angular_core.InputSignal<string>;
1099
1105
  /** Emits whenever the value changes. */
@@ -1108,7 +1114,7 @@ declare class HubTextareaComponent extends HubFieldControl {
1108
1114
  */
1109
1115
  setValue(value: string): void;
1110
1116
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubTextareaComponent, never>;
1111
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubTextareaComponent, "hub-textarea", never, { "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "cols": { "alias": "cols"; "required": false; "isSignal": true; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "autoresize": { "alias": "autoresize"; "required": false; "isSignal": true; }; "counter": { "alias": "counter"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "plaintext": { "alias": "plaintext"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, ["_prependTpl", "_appendTpl"], never, true, never>;
1117
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubTextareaComponent, "hub-textarea", never, { "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "cols": { "alias": "cols"; "required": false; "isSignal": true; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "autoresize": { "alias": "autoresize"; "required": false; "isSignal": true; }; "counter": { "alias": "counter"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "plaintext": { "alias": "plaintext"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, ["_prependTpl", "_appendTpl"], never, true, never>;
1112
1118
  }
1113
1119
 
1114
1120
  /** Value of `<hub-slider>`: a number in single mode, a `[lower, upper]` tuple in range mode. */
@@ -1130,7 +1136,6 @@ type HubSliderValue = number | [number, number];
1130
1136
  declare class HubSliderComponent extends HubFieldControl {
1131
1137
  #private;
1132
1138
  protected readonly _labelTypes: typeof HubLabelTypes;
1133
- protected readonly _formTextTypes: typeof FormTextTypes;
1134
1139
  protected readonly _value: _angular_core.WritableSignal<HubSliderValue>;
1135
1140
  /** Label text. */
1136
1141
  readonly label: _angular_core.InputSignal<string>;
@@ -1146,10 +1151,6 @@ declare class HubSliderComponent extends HubFieldControl {
1146
1151
  readonly step: _angular_core.InputSignalWithTransform<number, string | number>;
1147
1152
  /** Whether to show the value bubble(s) above the thumb(s). */
1148
1153
  readonly showValue: _angular_core.InputSignalWithTransform<boolean, unknown>;
1149
- /** Helper text shown below the control. */
1150
- readonly formText: _angular_core.InputSignal<string>;
1151
- /** Helper text placement. Only `bottom` is supported. */
1152
- readonly formTextType: _angular_core.InputSignal<FormTextType>;
1153
1154
  /** Extra CSS classes applied to the host element. */
1154
1155
  readonly classlist: _angular_core.InputSignal<string>;
1155
1156
  /** Emits whenever the value changes. */
@@ -1186,7 +1187,7 @@ declare class HubSliderComponent extends HubFieldControl {
1186
1187
  */
1187
1188
  setUpper(value: string | number): void;
1188
1189
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubSliderComponent, never>;
1189
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubSliderComponent, "hub-slider", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "range": { "alias": "range"; "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; }; "showValue": { "alias": "showValue"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
1190
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubSliderComponent, "hub-slider", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "range": { "alias": "range"; "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; }; "showValue": { "alias": "showValue"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
1190
1191
  }
1191
1192
 
1192
1193
  /** Context handed to a projected `hubSegmentedOption` template. */
@@ -1292,8 +1293,6 @@ declare class HubSegmentedComponent extends HubFieldControl {
1292
1293
  readonly label: _angular_core.InputSignal<string>;
1293
1294
  /** Label display type (`stacked`, `horizontal`). */
1294
1295
  readonly labelType: _angular_core.InputSignal<HubLabelType>;
1295
- /** Helper text shown below the control. */
1296
- readonly formText: _angular_core.InputSignal<string>;
1297
1296
  /** When `true`, options toggle independently and the value is an array. */
1298
1297
  readonly multiple: _angular_core.InputSignalWithTransform<boolean, unknown>;
1299
1298
  /** When `true`, the segments stack vertically instead of sitting in a row. */
@@ -1337,7 +1336,7 @@ declare class HubSegmentedComponent extends HubFieldControl {
1337
1336
  */
1338
1337
  private updateIndicator;
1339
1338
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubSegmentedComponent, never>;
1340
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubSegmentedComponent, "hub-segmented", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "vertical": { "alias": "vertical"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, ["optionTpt"], never, true, never>;
1339
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubSegmentedComponent, "hub-segmented", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "vertical": { "alias": "vertical"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, ["optionTpt"], never, true, never>;
1341
1340
  }
1342
1341
 
1343
1342
  /**
@@ -1493,7 +1492,6 @@ declare class HubSelectComponent extends HubFieldControl {
1493
1492
  */
1494
1493
  protected readonly _ngSelectConfig: NgSelectConfig;
1495
1494
  protected readonly _labelTypes: typeof HubLabelTypes;
1496
- protected readonly _formTextTypes: typeof FormTextTypes;
1497
1495
  protected readonly _selectFormats: typeof HubSelectFormats;
1498
1496
  protected readonly _value: _angular_core.WritableSignal<any>;
1499
1497
  protected readonly _optionTpl: _angular_core.Signal<TemplateRef<any> | undefined>;
@@ -1644,10 +1642,6 @@ declare class HubSelectComponent extends HubFieldControl {
1644
1642
  * by id). When omitted, the vendor's built-in comparison applies.
1645
1643
  */
1646
1644
  readonly compareWith: _angular_core.InputSignal<((a: any, b: any) => boolean) | undefined>;
1647
- /** Helper text shown below the control. */
1648
- readonly formText: _angular_core.InputSignal<string>;
1649
- /** Helper text placement. Only `bottom` is supported. */
1650
- readonly formTextType: _angular_core.InputSignal<FormTextType>;
1651
1645
  /** Extra CSS classes applied to the host element. */
1652
1646
  readonly classlist: _angular_core.InputSignal<string>;
1653
1647
  /** ARIA attributes forwarded to the vendor's combobox search input. */
@@ -1754,7 +1748,7 @@ declare class HubSelectComponent extends HubFieldControl {
1754
1748
  */
1755
1749
  protected toggleItem(item: any): void;
1756
1750
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubSelectComponent, never>;
1757
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubSelectComponent, "hub-select", never, { "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "vertical": { "alias": "vertical"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "bindLabel": { "alias": "bindLabel"; "required": false; "isSignal": true; }; "bindValue": { "alias": "bindValue"; "required": false; "isSignal": true; }; "groupBy": { "alias": "groupBy"; "required": false; "isSignal": true; }; "searchFn": { "alias": "searchFn"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "closeOnSelect": { "alias": "closeOnSelect"; "required": false; "isSignal": true; }; "fixedPlaceholder": { "alias": "fixedPlaceholder"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "notFoundText": { "alias": "notFoundText"; "required": false; "isSignal": true; }; "appendTo": { "alias": "appendTo"; "required": false; "isSignal": true; }; "addTag": { "alias": "addTag"; "required": false; "isSignal": true; }; "addTagText": { "alias": "addTagText"; "required": false; "isSignal": true; }; "minTermLength": { "alias": "minTermLength"; "required": false; "isSignal": true; }; "typeahead": { "alias": "typeahead"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "onFocus": "onFocus"; "onBlur": "onBlur"; "onOpen": "onOpen"; "onClose": "onClose"; "onClear": "onClear"; "onSearch": "onSearch"; "onAdd": "onAdd"; "onRemove": "onRemove"; "scroll": "scroll"; "scrollToEnd": "scrollToEnd"; }, ["_optionTpl", "_optgroupTpl", "_labelTpl", "_multiLabelTpl", "_headerTpl", "_footerTpl", "_notFoundTpl", "_legacySuffixTpl", "_prependTpl", "_genericAppendTpl"], ["*"], true, never>;
1751
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubSelectComponent, "hub-select", never, { "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "vertical": { "alias": "vertical"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "bindLabel": { "alias": "bindLabel"; "required": false; "isSignal": true; }; "bindValue": { "alias": "bindValue"; "required": false; "isSignal": true; }; "groupBy": { "alias": "groupBy"; "required": false; "isSignal": true; }; "searchFn": { "alias": "searchFn"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "closeOnSelect": { "alias": "closeOnSelect"; "required": false; "isSignal": true; }; "fixedPlaceholder": { "alias": "fixedPlaceholder"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "notFoundText": { "alias": "notFoundText"; "required": false; "isSignal": true; }; "appendTo": { "alias": "appendTo"; "required": false; "isSignal": true; }; "addTag": { "alias": "addTag"; "required": false; "isSignal": true; }; "addTagText": { "alias": "addTagText"; "required": false; "isSignal": true; }; "minTermLength": { "alias": "minTermLength"; "required": false; "isSignal": true; }; "typeahead": { "alias": "typeahead"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "onFocus": "onFocus"; "onBlur": "onBlur"; "onOpen": "onOpen"; "onClose": "onClose"; "onClear": "onClear"; "onSearch": "onSearch"; "onAdd": "onAdd"; "onRemove": "onRemove"; "scroll": "scroll"; "scrollToEnd": "scrollToEnd"; }, ["_optionTpl", "_optgroupTpl", "_labelTpl", "_multiLabelTpl", "_headerTpl", "_footerTpl", "_notFoundTpl", "_legacySuffixTpl", "_prependTpl", "_genericAppendTpl"], ["*"], true, never>;
1758
1752
  }
1759
1753
 
1760
1754
  /** A calendar cell enriched with its selection / range / disabled / focus state. */
@@ -1818,7 +1812,6 @@ declare class HubDatepickerComponent extends HubFieldControl {
1818
1812
  private readonly _panel;
1819
1813
  constructor();
1820
1814
  protected readonly _labelTypes: typeof HubLabelTypes;
1821
- protected readonly _formTextTypes: typeof FormTextTypes;
1822
1815
  /**
1823
1816
  * The selection, as local `Date`s. This — not the serialized value — is the component's single
1824
1817
  * source of truth: keeping `Date`s means the emitted shape is derived once, on the way out, and
@@ -1925,10 +1918,6 @@ declare class HubDatepickerComponent extends HubFieldControl {
1925
1918
  readonly labels: _angular_core.InputSignal<Partial<HubDatepickerLabels>>;
1926
1919
  /** Whether the picker is read-only. */
1927
1920
  readonly readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
1928
- /** Helper text shown below the control. */
1929
- readonly formText: _angular_core.InputSignal<string>;
1930
- /** Helper text placement. Only `bottom` is supported. */
1931
- readonly formTextType: _angular_core.InputSignal<FormTextType>;
1932
1921
  /** Extra CSS classes applied to the host element. */
1933
1922
  readonly classlist: _angular_core.InputSignal<string>;
1934
1923
  /** Text shown before the control as a group addon. A string is one; an array a run. */
@@ -2095,7 +2084,7 @@ declare class HubDatepickerComponent extends HubFieldControl {
2095
2084
  /** Moves the period grid's focus without selecting. */
2096
2085
  protected onPeriodFocusMove(date: Date): void;
2097
2086
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubDatepickerComponent, never>;
2098
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubDatepickerComponent, "hub-datepicker", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "granularity": { "alias": "granularity"; "required": false; "isSignal": true; }; "valueFormat": { "alias": "valueFormat"; "required": false; "isSignal": true; }; "parse": { "alias": "parse"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "firstDayOfWeek": { "alias": "firstDayOfWeek"; "required": false; "isSignal": true; }; "weekdayFormat": { "alias": "weekdayFormat"; "required": false; "isSignal": true; }; "monthFormat": { "alias": "monthFormat"; "required": false; "isSignal": true; }; "displayFormat": { "alias": "displayFormat"; "required": false; "isSignal": true; }; "timeDisplayFormat": { "alias": "timeDisplayFormat"; "required": false; "isSignal": true; }; "minuteStep": { "alias": "minuteStep"; "required": false; "isSignal": true; }; "secondStep": { "alias": "secondStep"; "required": false; "isSignal": true; }; "hourFormat": { "alias": "hourFormat"; "required": false; "isSignal": true; }; "rangeSeparator": { "alias": "rangeSeparator"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "disabledDates": { "alias": "disabledDates"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "showToday": { "alias": "showToday"; "required": false; "isSignal": true; }; "closeOnSelect": { "alias": "closeOnSelect"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "opened": "opened"; "closed": "closed"; "viewChange": "viewChange"; "cleared": "cleared"; }, ["_prependTpl", "_appendTpl"], never, true, never>;
2087
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubDatepickerComponent, "hub-datepicker", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "granularity": { "alias": "granularity"; "required": false; "isSignal": true; }; "valueFormat": { "alias": "valueFormat"; "required": false; "isSignal": true; }; "parse": { "alias": "parse"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "firstDayOfWeek": { "alias": "firstDayOfWeek"; "required": false; "isSignal": true; }; "weekdayFormat": { "alias": "weekdayFormat"; "required": false; "isSignal": true; }; "monthFormat": { "alias": "monthFormat"; "required": false; "isSignal": true; }; "displayFormat": { "alias": "displayFormat"; "required": false; "isSignal": true; }; "timeDisplayFormat": { "alias": "timeDisplayFormat"; "required": false; "isSignal": true; }; "minuteStep": { "alias": "minuteStep"; "required": false; "isSignal": true; }; "secondStep": { "alias": "secondStep"; "required": false; "isSignal": true; }; "hourFormat": { "alias": "hourFormat"; "required": false; "isSignal": true; }; "rangeSeparator": { "alias": "rangeSeparator"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "disabledDates": { "alias": "disabledDates"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "showToday": { "alias": "showToday"; "required": false; "isSignal": true; }; "closeOnSelect": { "alias": "closeOnSelect"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "opened": "opened"; "closed": "closed"; "viewChange": "viewChange"; "cleared": "cleared"; }, ["_prependTpl", "_appendTpl"], never, true, never>;
2099
2088
  }
2100
2089
 
2101
2090
  /**
@@ -2118,7 +2107,6 @@ declare class HubDatepickerComponent extends HubFieldControl {
2118
2107
  declare class HubTimepickerComponent extends HubFieldControl {
2119
2108
  #private;
2120
2109
  protected readonly _labelTypes: typeof HubLabelTypes;
2121
- protected readonly _formTextTypes: typeof FormTextTypes;
2122
2110
  /** Extra classes forwarded to the host, as every field of the family accepts. */
2123
2111
  readonly classlist: _angular_core.InputSignal<string>;
2124
2112
  /** What the bound control holds, as `HH:MM`. */
@@ -2127,10 +2115,6 @@ declare class HubTimepickerComponent extends HubFieldControl {
2127
2115
  readonly label: _angular_core.InputSignal<string>;
2128
2116
  /** Label placement. */
2129
2117
  readonly labelType: _angular_core.InputSignal<HubLabelType>;
2130
- /** Helper text shown below the field. */
2131
- readonly formText: _angular_core.InputSignal<string>;
2132
- /** Helper-text placement. */
2133
- readonly formTextType: _angular_core.InputSignal<FormTextType>;
2134
2118
  /** Earliest time the field accepts, as `HH:MM`. */
2135
2119
  readonly min: _angular_core.InputSignal<string>;
2136
2120
  /** Latest time the field accepts, as `HH:MM`. */
@@ -2174,7 +2158,7 @@ declare class HubTimepickerComponent extends HubFieldControl {
2174
2158
  writeValue(value: unknown): void;
2175
2159
  protected onInput(event: Event): void;
2176
2160
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubTimepickerComponent, never>;
2177
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubTimepickerComponent, "hub-timepicker", never, { "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "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; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; }, {}, ["_prependTpl", "_appendTpl"], never, true, never>;
2161
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubTimepickerComponent, "hub-timepicker", never, { "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "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; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "prepend": { "alias": "prepend"; "required": false; "isSignal": true; }; "append": { "alias": "append"; "required": false; "isSignal": true; }; }, {}, ["_prependTpl", "_appendTpl"], never, true, never>;
2178
2162
  }
2179
2163
 
2180
2164
  /** Context handed to a projected `hubFileIcon` template. */
@@ -2342,7 +2326,6 @@ declare function toFileArray(value: unknown): File[];
2342
2326
  */
2343
2327
  declare class HubFileInputComponent extends HubFieldControl {
2344
2328
  #private;
2345
- protected readonly _formTextTypes: typeof FormTextTypes;
2346
2329
  protected readonly _items: _angular_core.WritableSignal<HubFileItem[]>;
2347
2330
  /** Releases every object URL and aborts every in-flight upload when the field goes away. */
2348
2331
  private readonly _cleanup;
@@ -2380,10 +2363,6 @@ declare class HubFileInputComponent extends HubFieldControl {
2380
2363
  readonly dropSubtext: _angular_core.InputSignal<string | null>;
2381
2364
  /** Overrides the auto-generated hint that summarizes the active constraints. Pass `''` to hide it. */
2382
2365
  readonly hint: _angular_core.InputSignal<string | null>;
2383
- /** Helper text shown below the control. */
2384
- readonly formText: _angular_core.InputSignal<string>;
2385
- /** Helper text placement. Only `bottom` is supported. */
2386
- readonly formTextType: _angular_core.InputSignal<FormTextType>;
2387
2366
  /** Extra CSS classes applied to the host element. */
2388
2367
  readonly classlist: _angular_core.InputSignal<string>;
2389
2368
  /** Emits the native value whenever the selection changes. */
@@ -2510,7 +2489,7 @@ declare class HubFileInputComponent extends HubFieldControl {
2510
2489
  */
2511
2490
  protected previewContext(item: HubFileItem): HubFilePreviewContext;
2512
2491
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubFileInputComponent, never>;
2513
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubFileInputComponent, "hub-file-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "maxSize": { "alias": "maxSize"; "required": false; "isSignal": true; }; "minSize": { "alias": "minSize"; "required": false; "isSignal": true; }; "maxTotalSize": { "alias": "maxTotalSize"; "required": false; "isSignal": true; }; "maxFiles": { "alias": "maxFiles"; "required": false; "isSignal": true; }; "dragDrop": { "alias": "dragDrop"; "required": false; "isSignal": true; }; "paste": { "alias": "paste"; "required": false; "isSignal": true; }; "preview": { "alias": "preview"; "required": false; "isSignal": true; }; "allowDuplicates": { "alias": "allowDuplicates"; "required": false; "isSignal": true; }; "capture": { "alias": "capture"; "required": false; "isSignal": true; }; "autoUpload": { "alias": "autoUpload"; "required": false; "isSignal": true; }; "buttonLabel": { "alias": "buttonLabel"; "required": false; "isSignal": true; }; "dropText": { "alias": "dropText"; "required": false; "isSignal": true; }; "dropSubtext": { "alias": "dropSubtext"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "rejected": "rejected"; "fileRemoved": "fileRemoved"; "uploadStateChange": "uploadStateChange"; }, ["iconTpt", "previewTpt", "noticeTpt"], never, true, never>;
2492
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubFileInputComponent, "hub-file-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "maxSize": { "alias": "maxSize"; "required": false; "isSignal": true; }; "minSize": { "alias": "minSize"; "required": false; "isSignal": true; }; "maxTotalSize": { "alias": "maxTotalSize"; "required": false; "isSignal": true; }; "maxFiles": { "alias": "maxFiles"; "required": false; "isSignal": true; }; "dragDrop": { "alias": "dragDrop"; "required": false; "isSignal": true; }; "paste": { "alias": "paste"; "required": false; "isSignal": true; }; "preview": { "alias": "preview"; "required": false; "isSignal": true; }; "allowDuplicates": { "alias": "allowDuplicates"; "required": false; "isSignal": true; }; "capture": { "alias": "capture"; "required": false; "isSignal": true; }; "autoUpload": { "alias": "autoUpload"; "required": false; "isSignal": true; }; "buttonLabel": { "alias": "buttonLabel"; "required": false; "isSignal": true; }; "dropText": { "alias": "dropText"; "required": false; "isSignal": true; }; "dropSubtext": { "alias": "dropSubtext"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "rejected": "rejected"; "fileRemoved": "fileRemoved"; "uploadStateChange": "uploadStateChange"; }, ["iconTpt", "previewTpt", "noticeTpt"], never, true, never>;
2514
2493
  }
2515
2494
 
2516
2495
  declare class NgOptionComponent implements OnInit {
@@ -2766,15 +2745,25 @@ declare class HubSelectSuffixDirective {
2766
2745
  }
2767
2746
 
2768
2747
  /**
2769
- * Inverts a HEX color, or returns the best contrasting black/white when `bw` is enabled.
2748
+ * Inverts a colour, or returns the best contrasting black/white when `bw` is enabled.
2770
2749
  */
2771
2750
  declare class HubInvertColorPipe implements PipeTransform {
2772
2751
  /**
2773
- * @param hex - HEX color (`#rgb` or `#rrggbb`).
2774
- * @param bw - When `true`, returns `#000000` or `#FFFFFF` for maximum contrast.
2775
- * @returns The inverted (or contrasting) HEX color.
2752
+ * @param color - Any CSS colour: hex (3/4/6/8 digits, `#` optional), `rgb()`, `hsl()`,
2753
+ * `oklch()`, `oklab()` or a named colour.
2754
+ * @param bw - When `true`, returns the black or white that reads best on `color`.
2755
+ * @param metric - How `bw` decides. `'lightness'` (default) matches the
2756
+ * `--hub-sys-color-*-on` design-system token; `'apca'` and `'wcag'` score the two
2757
+ * candidates instead.
2758
+ * @returns The inverted (or contrasting) colour as a hex string, or `#000000` when the
2759
+ * input is empty or is not a colour this can resolve.
2760
+ */
2761
+ transform(color: string, bw?: boolean, metric?: 'lightness' | 'apca' | 'wcag'): string;
2762
+ /**
2763
+ * Resolves the input, retrying with a `#` prefix so bare hex digits keep working — the
2764
+ * pipe has accepted `'336699'` since it shipped and consumers rely on it.
2776
2765
  */
2777
- transform(hex: string, bw?: boolean): unknown;
2766
+ private resolve;
2778
2767
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubInvertColorPipe, never>;
2779
2768
  static ɵpipe: _angular_core.ɵɵPipeDeclaration<HubInvertColorPipe, "hubInvertColor", true>;
2780
2769
  }