ng-hub-ui-forms 21.0.0 → 22.1.2

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.
Binary file
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "ng-hub-ui-forms",
3
- "version": "21.0.0",
3
+ "version": "22.1.2",
4
4
  "license": "MIT",
5
5
  "description": "Accessible, signal-based form fields for Angular (input, textarea, slider, select, datepicker) 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)",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/carlos-morcillo/ng-hub-ui-forms.git"
9
+ "url": "git+https://github.com/carlos-morcillo/ng-hub-ui-forms.git"
10
10
  },
11
11
  "homepage": "https://hubui.dev/",
12
12
  "keywords": [
@@ -101,6 +101,17 @@
101
101
  box-shadow: 0 0 0 var(--hub-form-focus-ring-width) var(--hub-form-invalid-focus-ring-color);
102
102
  }
103
103
  }
104
+
105
+ // Opt-in success state (mirror of `--invalid`); applied only when a field
106
+ // enables `showValid` and the control is touched + valid.
107
+ &--valid {
108
+ border-color: var(--hub-form-valid-border-color);
109
+
110
+ &:focus {
111
+ border-color: var(--hub-form-valid-border-color);
112
+ box-shadow: 0 0 0 var(--hub-form-focus-ring-width) var(--hub-form-valid-focus-ring-color);
113
+ }
114
+ }
104
115
  }
105
116
 
106
117
  // Helper text below the control.
@@ -129,4 +140,9 @@
129
140
  &-text {
130
141
  display: block;
131
142
  }
143
+
144
+ // Success feedback (opt-in valid state).
145
+ &--valid {
146
+ color: var(--hub-form-valid-feedback-color);
147
+ }
132
148
  }
@@ -11,12 +11,21 @@
11
11
  // ── Shared form contract (used by every field) ──────────────────────────
12
12
  --hub-form-field-gap: var(--hub-ref-space-1, 0.25rem); // label ↔ control
13
13
  --hub-form-row-gap: var(--hub-ref-space-3, 1rem); // horizontal label gutter
14
+ --hub-form-fieldset-padding-x: var(--hub-ref-space-3, 1rem);
15
+ --hub-form-fieldset-padding-y: var(--hub-ref-space-3, 1rem);
14
16
  --hub-form-label-horizontal-max-width: 12rem; // horizontal label caps here, then ellipsizes
15
17
 
16
18
  --hub-form-invalid-color: var(--hub-sys-color-danger, #dc3545);
17
19
  --hub-form-invalid-border-color: var(--hub-sys-color-danger, #dc3545);
18
20
  --hub-form-invalid-focus-ring-color: var(--hub-sys-color-danger-subtle, rgba(220, 53, 69, 0.25));
19
21
 
22
+ // Valid / success — mirror of the invalid contract, shown only when a field
23
+ // opts in via `showValid` (the success state is never automatic).
24
+ --hub-form-valid-color: var(--hub-sys-color-success, #198754);
25
+ --hub-form-valid-border-color: var(--hub-sys-color-success, #198754);
26
+ --hub-form-valid-focus-ring-color: var(--hub-sys-color-success-subtle, rgba(25, 135, 84, 0.25));
27
+ --hub-form-valid-feedback-color: var(--hub-form-valid-color);
28
+
20
29
  --hub-form-feedback-color: var(--hub-form-invalid-color);
21
30
  --hub-form-feedback-font-size: var(--hub-ref-font-size-sm, 0.875rem);
22
31
  --hub-form-feedback-margin-top: var(--hub-ref-space-1, 0.25rem);
@@ -44,7 +53,7 @@
44
53
  --hub-input-font-family: var(--hub-ref-font-family-base, system-ui, sans-serif);
45
54
  --hub-input-font-size: var(--hub-ref-font-size-base, 1rem);
46
55
  --hub-input-font-weight: var(--hub-ref-font-weight-base, 400);
47
- --hub-input-line-height: 1.5;
56
+ --hub-input-line-height: var(--hub-ref-line-height-base, 1.5);
48
57
  --hub-input-padding-y: 0.375rem;
49
58
  --hub-input-padding-x: 0.75rem;
50
59
  --hub-input-border-width: var(--hub-ref-border-width, 1px);
@@ -127,11 +136,13 @@
127
136
  --hub-select-clear-color: var(--hub-sys-text-muted, #6c757d);
128
137
  --hub-select-clear-hover-color: var(--hub-sys-color-danger, #dc3545);
129
138
  --hub-select-option-color: var(--hub-sys-text-primary, #212529);
130
- --hub-select-option-padding-x: var(--hub-ref-space-3, 0.75rem);
139
+ --hub-select-option-padding-x: var(--hub-ref-space-3, 1rem);
131
140
  --hub-select-option-padding-y: var(--hub-ref-space-2, 0.5rem);
132
- --hub-select-option-marked-bg: var(--hub-sys-surface-elevated, #f1f3f5);
141
+ --hub-select-option-marked-bg: var(--hub-sys-surface-elevated, #f8f9fa);
133
142
  --hub-select-option-selected-bg: var(--hub-sys-color-primary, #0d6efd);
134
- --hub-select-option-selected-color: #fff;
143
+ // Text on the selected option sits on the primary accent — read the derived
144
+ // contrast token so a light/custom primary keeps the label legible.
145
+ --hub-select-option-selected-color: var(--hub-sys-color-primary-on, var(--hub-ref-color-white, #fff));
135
146
  --hub-select-optgroup-color: var(--hub-sys-text-muted, #6c757d);
136
147
  --hub-select-value-bg: var(--hub-sys-surface-elevated, #f8f9fa);
137
148
  --hub-select-value-color: var(--hub-sys-text-primary, #212529);
@@ -152,17 +163,20 @@
152
163
  --hub-daterangepicker-border-color: var(--hub-sys-border-color-default, #dee2e6);
153
164
  --hub-daterangepicker-border-radius: var(--hub-ref-radius-md, 0.375rem);
154
165
  --hub-daterangepicker-box-shadow: var(--hub-sys-shadow, 0 0.5rem 1rem rgba(0, 0, 0, 0.12));
155
- --hub-daterangepicker-padding: var(--hub-ref-space-3, 1rem);
166
+ --hub-daterangepicker-padding-x: var(--hub-ref-space-3, 1rem);
167
+ --hub-daterangepicker-padding-y: var(--hub-ref-space-3, 1rem);
156
168
  --hub-daterangepicker-cell-size: 2rem;
157
169
  --hub-daterangepicker-cell-color: var(--hub-sys-text-primary, #212529);
158
170
  --hub-daterangepicker-cell-border-radius: var(--hub-ref-radius-sm, 0.25rem);
159
- --hub-daterangepicker-cell-hover-bg: var(--hub-sys-surface-elevated, #f5f5f5);
171
+ --hub-daterangepicker-cell-hover-bg: var(--hub-sys-surface-elevated, #f8f9fa);
160
172
  --hub-daterangepicker-active-bg: var(--hub-sys-color-primary, #0d6efd);
161
- --hub-daterangepicker-active-color: #fff;
162
- // Light primary tint (theme-aware): `--hub-sys-color-primary-subtle` is a *dark* navy in
163
- // this design system, so derive a soft tint from the primary instead.
164
- --hub-daterangepicker-in-range-bg: color-mix(in srgb, var(--hub-sys-color-primary, #0d6efd) 14%, transparent);
165
- --hub-daterangepicker-off-color: var(--hub-sys-text-muted, #adb5bd);
173
+ // Text on the active day sits on the primary accent — derived contrast token.
174
+ --hub-daterangepicker-active-color: var(--hub-sys-color-primary-on, var(--hub-ref-color-white, #fff));
175
+ // Soft primary tint for the in-range band. Mixed in OKLCH (perceptually even)
176
+ // rather than sRGB; kept independent of `-subtle` (which mixes over the page
177
+ // surface, not transparent) so the band reads as a translucent overlay.
178
+ --hub-daterangepicker-in-range-bg: color-mix(in oklch, var(--hub-sys-color-primary, #0d6efd) 14%, transparent);
179
+ --hub-daterangepicker-off-color: var(--hub-sys-text-muted, #6c757d);
166
180
  --hub-daterangepicker-nav-arrow-color: var(--hub-sys-text-muted, #6c757d);
167
181
  --hub-daterangepicker-nav-arrow-hover-color: var(--hub-sys-text-primary, #212529);
168
182
 
@@ -170,10 +184,11 @@
170
184
  --hub-select-button-bg: var(--hub-sys-surface-page, #fff);
171
185
  --hub-select-button-color: var(--hub-sys-text-primary, #212529);
172
186
  --hub-select-button-border-color: var(--hub-sys-border-color-default, #dee2e6);
173
- --hub-select-button-padding-x: var(--hub-ref-space-3, 0.75rem);
187
+ --hub-select-button-padding-x: var(--hub-ref-space-3, 1rem);
174
188
  --hub-select-button-padding-y: var(--hub-ref-space-2, 0.5rem);
175
189
  --hub-select-button-gap: var(--hub-ref-space-2, 0.5rem);
176
190
  --hub-select-button-selected-bg: var(--hub-sys-color-primary, #0d6efd);
177
- --hub-select-button-selected-color: #fff;
191
+ // Text on the selected button sits on the primary accent — derived contrast token.
192
+ --hub-select-button-selected-color: var(--hub-sys-color-primary-on, var(--hub-ref-color-white, #fff));
178
193
  --hub-select-button-selected-border-color: var(--hub-sys-color-primary, #0d6efd);
179
194
  }
@@ -114,6 +114,15 @@ declare abstract class HubFieldControl extends HubFormControl implements Control
114
114
  readonly disabled: _angular_core.ModelSignal<boolean>;
115
115
  /** Per-field override for the invalid-feedback message builder. */
116
116
  readonly invalidFeedbackTemplateFn: _angular_core.InputSignal<((key: string, value: any) => string) | null>;
117
+ /**
118
+ * Opt-in success state. When `true`, a touched + valid field renders the
119
+ * `--valid` styling (success border + ring). Defaults to the global
120
+ * {@link HubFormsConfig.showValid}; the success state is never automatic
121
+ * unless enabled. Has no effect while the field is invalid.
122
+ */
123
+ readonly showValid: _angular_core.InputSignal<boolean>;
124
+ /** Optional success message shown below the control while {@link showsValid}. */
125
+ readonly validFeedback: _angular_core.InputSignal<string | null>;
117
126
  onChange: (value: any) => void;
118
127
  onTouched: () => void;
119
128
  protected readonly _nativeErrors: _angular_core.WritableSignal<ValidationErrors | null>;
@@ -121,6 +130,10 @@ declare abstract class HubFieldControl extends HubFormControl implements Control
121
130
  constructor();
122
131
  /** Whether the field should display its error feedback (touched + invalid). */
123
132
  get isInvalid(): boolean;
133
+ /** Whether the field is touched and valid (independent of the opt-in). */
134
+ get isValid(): boolean;
135
+ /** Whether the opt-in success state should be displayed (touched + valid + `showValid`). */
136
+ get showsValid(): boolean;
124
137
  /** Current validation errors, from the reactive control or from native validity. */
125
138
  get errors(): ValidationErrors | null;
126
139
  ngAfterContentInit(): void;
@@ -149,7 +162,7 @@ declare abstract class HubFieldControl extends HubFormControl implements Control
149
162
  */
150
163
  protected updateNativeErrors(target?: EventTarget | null): void;
151
164
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubFieldControl, never>;
152
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<HubFieldControl, never, never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalidFeedbackTemplateFn": { "alias": "invalidFeedbackTemplateFn"; "required": false; "isSignal": true; }; }, { "disabled": "disabledChange"; }, ["formTextTmp", "errorTpts"], never, true, 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>;
153
166
  }
154
167
 
155
168
  /** When a container reveals its group-level validation errors. */
@@ -282,6 +295,12 @@ interface HubFormsConfig {
282
295
  * @returns The message string (HTML allowed).
283
296
  */
284
297
  invalidFeedbackTemplateFn: (key: string, value: any) => string;
298
+ /**
299
+ * Whether fields render the opt-in valid/success state by default once they
300
+ * are touched and valid. `false` keeps the success state off everywhere
301
+ * (only invalid is automatic); a per-field `showValid` input overrides this.
302
+ */
303
+ showValid: boolean;
285
304
  /** Global datepicker defaults (locale labels, formats, first day of week…). */
286
305
  datepicker: HubDatepickerConfig;
287
306
  }
Binary file