ng-primitives 0.92.0 → 0.94.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 (69) hide show
  1. package/a11y/index.d.ts +5 -1
  2. package/accordion/index.d.ts +30 -1
  3. package/autofill/index.d.ts +6 -0
  4. package/avatar/index.d.ts +17 -2
  5. package/breadcrumbs/index.d.ts +35 -7
  6. package/button/index.d.ts +24 -4
  7. package/checkbox/index.d.ts +17 -1
  8. package/fesm2022/ng-primitives-accordion.mjs +24 -0
  9. package/fesm2022/ng-primitives-accordion.mjs.map +1 -1
  10. package/fesm2022/ng-primitives-button.mjs +18 -4
  11. package/fesm2022/ng-primitives-button.mjs.map +1 -1
  12. package/fesm2022/ng-primitives-checkbox.mjs +25 -8
  13. package/fesm2022/ng-primitives-checkbox.mjs.map +1 -1
  14. package/fesm2022/ng-primitives-file-upload.mjs +39 -38
  15. package/fesm2022/ng-primitives-file-upload.mjs.map +1 -1
  16. package/fesm2022/ng-primitives-focus-trap.mjs +107 -138
  17. package/fesm2022/ng-primitives-focus-trap.mjs.map +1 -1
  18. package/fesm2022/ng-primitives-form-field.mjs +323 -365
  19. package/fesm2022/ng-primitives-form-field.mjs.map +1 -1
  20. package/fesm2022/ng-primitives-input.mjs +10 -2
  21. package/fesm2022/ng-primitives-input.mjs.map +1 -1
  22. package/fesm2022/ng-primitives-interactions.mjs +57 -58
  23. package/fesm2022/ng-primitives-interactions.mjs.map +1 -1
  24. package/fesm2022/ng-primitives-listbox.mjs +2 -2
  25. package/fesm2022/ng-primitives-listbox.mjs.map +1 -1
  26. package/fesm2022/ng-primitives-menu.mjs +313 -352
  27. package/fesm2022/ng-primitives-menu.mjs.map +1 -1
  28. package/fesm2022/ng-primitives-roving-focus.mjs +1 -1
  29. package/fesm2022/ng-primitives-roving-focus.mjs.map +1 -1
  30. package/fesm2022/ng-primitives-separator.mjs +15 -7
  31. package/fesm2022/ng-primitives-separator.mjs.map +1 -1
  32. package/fesm2022/ng-primitives-slider.mjs +26 -9
  33. package/fesm2022/ng-primitives-slider.mjs.map +1 -1
  34. package/fesm2022/ng-primitives-state.mjs +37 -8
  35. package/fesm2022/ng-primitives-state.mjs.map +1 -1
  36. package/fesm2022/ng-primitives-switch.mjs +16 -5
  37. package/fesm2022/ng-primitives-switch.mjs.map +1 -1
  38. package/fesm2022/ng-primitives-tabs.mjs +197 -189
  39. package/fesm2022/ng-primitives-tabs.mjs.map +1 -1
  40. package/fesm2022/ng-primitives-textarea.mjs +7 -0
  41. package/fesm2022/ng-primitives-textarea.mjs.map +1 -1
  42. package/fesm2022/ng-primitives-toggle-group.mjs +22 -5
  43. package/fesm2022/ng-primitives-toggle-group.mjs.map +1 -1
  44. package/fesm2022/ng-primitives-toggle.mjs +16 -5
  45. package/fesm2022/ng-primitives-toggle.mjs.map +1 -1
  46. package/fesm2022/ng-primitives-toolbar.mjs +2 -2
  47. package/fesm2022/ng-primitives-toolbar.mjs.map +1 -1
  48. package/fesm2022/ng-primitives-tooltip.mjs +4 -4
  49. package/fesm2022/ng-primitives-tooltip.mjs.map +1 -1
  50. package/fesm2022/ng-primitives-utils.mjs.map +1 -1
  51. package/file-upload/index.d.ts +30 -8
  52. package/focus-trap/index.d.ts +35 -75
  53. package/form-field/index.d.ts +328 -123
  54. package/input/index.d.ts +19 -0
  55. package/interactions/index.d.ts +16 -16
  56. package/menu/index.d.ts +247 -120
  57. package/package.json +1 -1
  58. package/roving-focus/index.d.ts +88 -12
  59. package/schematics/ng-generate/templates/tabs/tabs.__fileSuffix@dasherize__.ts.template +2 -2
  60. package/separator/index.d.ts +1 -0
  61. package/slider/index.d.ts +34 -6
  62. package/state/index.d.ts +31 -8
  63. package/switch/index.d.ts +20 -4
  64. package/tabs/index.d.ts +343 -82
  65. package/textarea/index.d.ts +13 -0
  66. package/toggle/index.d.ts +12 -3
  67. package/toggle-group/index.d.ts +22 -2
  68. package/toolbar/index.d.ts +7 -0
  69. package/utils/index.d.ts +1 -1
@@ -1,75 +1,253 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, effect, Directive, computed, booleanAttribute, signal, contentChild, inject, Injector, untracked, ElementRef, HostListener } from '@angular/core';
3
- import { uniqueId, onBooleanChange, controlStatus, onChange } from 'ng-primitives/utils';
4
- import { createStateToken, createStateProvider, createStateInjector, createState, attrBinding, dataBinding } from 'ng-primitives/state';
2
+ import { inject, Injector, signal, untracked, effect, input, Directive, computed, booleanAttribute, contentChild } from '@angular/core';
3
+ import { onChange, uniqueId, onBooleanChange, controlStatus } from 'ng-primitives/utils';
5
4
  import { injectElementRef, explicitEffect } from 'ng-primitives/internal';
5
+ import { createPrimitive, dataBinding, onDestroy, attrBinding, listener } from 'ng-primitives/state';
6
6
  import { NgControl } from '@angular/forms';
7
7
 
8
- /**
9
- * The state token for the FormField primitive.
10
- */
11
- const NgpFormFieldStateToken = createStateToken('FormField');
12
- /**
13
- * Provides the FormField state.
14
- */
15
- const provideFormFieldState = createStateProvider(NgpFormFieldStateToken);
16
- /**
17
- * Injects the FormField state.
18
- */
19
- const injectFormFieldState = createStateInjector(NgpFormFieldStateToken);
20
- /**
21
- * The FormField state registration function.
22
- */
23
- const formFieldState = createState(NgpFormFieldStateToken);
8
+ const [NgpFormFieldStateToken, ngpFormField, injectFormFieldState, provideFormFieldState] = createPrimitive('NgpFormField', ({ ngControl }) => {
9
+ const element = injectElementRef();
10
+ const injector = inject(Injector);
11
+ // Store the form labels
12
+ const labels = signal([], ...(ngDevMode ? [{ debugName: "labels" }] : []));
13
+ // Store the form descriptions
14
+ const descriptions = signal([], ...(ngDevMode ? [{ debugName: "descriptions" }] : []));
15
+ // Store the id of the associated form control
16
+ const formControl = signal(null, ...(ngDevMode ? [{ debugName: "formControl" }] : []));
17
+ // Store the validation error messages
18
+ const errors = signal([], ...(ngDevMode ? [{ debugName: "errors" }] : []));
19
+ // Form control state signals
20
+ const pristine = signal(null, ...(ngDevMode ? [{ debugName: "pristine" }] : []));
21
+ const touched = signal(null, ...(ngDevMode ? [{ debugName: "touched" }] : []));
22
+ const dirty = signal(null, ...(ngDevMode ? [{ debugName: "dirty" }] : []));
23
+ const valid = signal(null, ...(ngDevMode ? [{ debugName: "valid" }] : []));
24
+ const invalid = signal(null, ...(ngDevMode ? [{ debugName: "invalid" }] : []));
25
+ const pending = signal(null, ...(ngDevMode ? [{ debugName: "pending" }] : []));
26
+ const disabled = signal(null, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
27
+ // Store the current status subscription
28
+ let subscription;
29
+ // Host bindings
30
+ dataBinding(element, 'data-invalid', invalid);
31
+ dataBinding(element, 'data-valid', valid);
32
+ dataBinding(element, 'data-touched', touched);
33
+ dataBinding(element, 'data-pristine', pristine);
34
+ dataBinding(element, 'data-dirty', dirty);
35
+ dataBinding(element, 'data-pending', pending);
36
+ dataBinding(element, 'data-disabled', disabled);
37
+ function updateStatus() {
38
+ const control = ngControl();
39
+ if (!control) {
40
+ return;
41
+ }
42
+ // Wrap in try-catch to handle signal-forms interop controls where
43
+ // the `field` input may not be available yet (throws NG0950).
44
+ // Reading the signal still establishes a dependency, so the effect
45
+ // will re-run when the input becomes available.
46
+ try {
47
+ const controlPristine = control.pristine;
48
+ const controlTouched = control.touched;
49
+ const controlDirty = control.dirty;
50
+ const controlValid = control.valid;
51
+ const controlInvalid = control.invalid;
52
+ const controlPending = control.pending;
53
+ const controlDisabled = control.disabled;
54
+ const controlErrors = control.errors;
55
+ untracked(() => {
56
+ pristine.set(controlPristine);
57
+ touched.set(controlTouched);
58
+ dirty.set(controlDirty);
59
+ valid.set(controlValid);
60
+ invalid.set(controlInvalid);
61
+ pending.set(controlPending);
62
+ disabled.set(controlDisabled);
63
+ errors.set(controlErrors ? Object.keys(controlErrors) : []);
64
+ });
65
+ }
66
+ catch {
67
+ // NG0950: Required input not available yet. The effect will re-run
68
+ // when the signal input becomes available.
69
+ }
70
+ }
71
+ function setupSubscriptions(control) {
72
+ // Unsubscribe from the previous subscriptions.
73
+ subscription?.unsubscribe();
74
+ if (!control) {
75
+ return;
76
+ }
77
+ // For signal-forms interop controls, use an effect to reactively track status.
78
+ // For classic controls, also use an effect but additionally subscribe to events.
79
+ effect(() => {
80
+ updateStatus();
81
+ }, { injector });
82
+ // Classic controls also have an events observable we can subscribe to.
83
+ const underlyingControl = control?.control;
84
+ if (underlyingControl?.events) {
85
+ subscription = underlyingControl.events.subscribe(() => updateStatus());
86
+ }
87
+ }
88
+ // Setup subscriptions when ngControl changes
89
+ onChange(ngControl, setupSubscriptions);
90
+ // Cleanup subscription on destroy
91
+ onDestroy(() => subscription?.unsubscribe());
92
+ // Methods
93
+ function setFormControl(id) {
94
+ formControl.set(id);
95
+ }
96
+ function addLabel(label) {
97
+ if (labels().includes(label)) {
98
+ return;
99
+ }
100
+ labels.update(currentLabels => [...currentLabels, label]);
101
+ }
102
+ function addDescription(description) {
103
+ if (descriptions().includes(description)) {
104
+ return;
105
+ }
106
+ descriptions.update(currentDescriptions => [...currentDescriptions, description]);
107
+ }
108
+ function removeFormControl() {
109
+ formControl.set(null);
110
+ }
111
+ function removeLabel(label) {
112
+ labels.update(currentLabels => currentLabels.filter(l => l !== label));
113
+ }
114
+ function removeDescription(description) {
115
+ descriptions.update(currentDescriptions => currentDescriptions.filter(d => d !== description));
116
+ }
117
+ return {
118
+ labels,
119
+ descriptions,
120
+ formControl,
121
+ errors,
122
+ pristine,
123
+ touched,
124
+ dirty,
125
+ valid,
126
+ invalid,
127
+ pending,
128
+ disabled,
129
+ setFormControl,
130
+ addLabel,
131
+ addDescription,
132
+ removeFormControl,
133
+ removeLabel,
134
+ removeDescription,
135
+ };
136
+ });
137
+
138
+ const [NgpDescriptionStateToken, ngpDescription, injectDescriptionState, provideDescriptionState,] = createPrimitive('NgpDescription', ({ id = signal(uniqueId('ngp-description')) }) => {
139
+ const element = injectElementRef();
140
+ const formField = injectFormFieldState({ optional: true });
141
+ // Host bindings
142
+ attrBinding(element, 'id', id);
143
+ dataBinding(element, 'data-invalid', () => (formField()?.invalid() ? '' : null));
144
+ dataBinding(element, 'data-valid', () => (formField()?.valid() ? '' : null));
145
+ dataBinding(element, 'data-touched', () => (formField()?.touched() ? '' : null));
146
+ dataBinding(element, 'data-pristine', () => (formField()?.pristine() ? '' : null));
147
+ dataBinding(element, 'data-dirty', () => (formField()?.dirty() ? '' : null));
148
+ dataBinding(element, 'data-pending', () => (formField()?.pending() ? '' : null));
149
+ dataBinding(element, 'data-disabled', () => (formField()?.disabled() ? '' : null));
150
+ // Register with form field and cleanup on destroy
151
+ formField()?.addDescription(id());
152
+ onDestroy(() => formField()?.removeDescription(id()));
153
+ onChange(id, (newId, oldId) => {
154
+ if (oldId) {
155
+ formField()?.removeDescription(oldId);
156
+ }
157
+ formField()?.addDescription(newId);
158
+ });
159
+ return { id };
160
+ });
24
161
 
25
162
  /**
26
163
  * The `NgpDescription` directive is used to mark a description element within a form field. There may be multiple descriptions associated with a form control.
27
164
  */
28
165
  class NgpDescription {
166
+ /**
167
+ * The description state.
168
+ */
29
169
  constructor() {
30
170
  /**
31
171
  * The id of the description. If not provided, a unique id will be generated.
32
172
  */
33
173
  this.id = input(uniqueId('ngp-description'), ...(ngDevMode ? [{ debugName: "id" }] : []));
34
- /**
35
- * Access the form field that the description is associated with.
36
- */
37
- this.formField = injectFormFieldState({ optional: true });
38
- effect(onCleanup => {
39
- this.formField()?.addDescription(this.id());
40
- onCleanup(() => this.formField()?.removeDescription(this.id()));
41
- });
174
+ ngpDescription({ id: this.id });
42
175
  }
43
176
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpDescription, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
44
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpDescription, isStandalone: true, selector: "[ngpDescription]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.id": "id()", "attr.data-invalid": "formField()?.invalid() ? \"\" : null", "attr.data-valid": "formField()?.valid() ? \"\" : null", "attr.data-touched": "formField()?.touched() ? \"\" : null", "attr.data-pristine": "formField()?.pristine() ? \"\" : null", "attr.data-dirty": "formField()?.dirty() ? \"\" : null", "attr.data-pending": "formField()?.pending() ? \"\" : null", "attr.data-disabled": "formField()?.disabled() ? \"\" : null" } }, exportAs: ["ngpDescription"], ngImport: i0 }); }
177
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpDescription, isStandalone: true, selector: "[ngpDescription]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideDescriptionState()], exportAs: ["ngpDescription"], ngImport: i0 }); }
45
178
  }
46
179
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpDescription, decorators: [{
47
180
  type: Directive,
48
181
  args: [{
49
182
  selector: '[ngpDescription]',
50
183
  exportAs: 'ngpDescription',
51
- host: {
52
- '[attr.id]': 'id()',
53
- '[attr.data-invalid]': 'formField()?.invalid() ? "" : null',
54
- '[attr.data-valid]': 'formField()?.valid() ? "" : null',
55
- '[attr.data-touched]': 'formField()?.touched() ? "" : null',
56
- '[attr.data-pristine]': 'formField()?.pristine() ? "" : null',
57
- '[attr.data-dirty]': 'formField()?.dirty() ? "" : null',
58
- '[attr.data-pending]': 'formField()?.pending() ? "" : null',
59
- '[attr.data-disabled]': 'formField()?.disabled() ? "" : null',
60
- },
184
+ providers: [provideDescriptionState()],
61
185
  }]
62
186
  }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
63
187
 
188
+ const [NgpErrorStateToken, ngpError, injectErrorState, provideErrorState] = createPrimitive('NgpError', ({ id, validator = signal(null) }) => {
189
+ const element = injectElementRef();
190
+ const formField = injectFormFieldState({ optional: true });
191
+ // Determine if there is an error message
192
+ const hasError = computed(() => {
193
+ const errors = formField()?.errors() ?? [];
194
+ const validatorValue = validator();
195
+ return validatorValue ? errors?.includes(validatorValue) : errors?.length > 0;
196
+ }, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
197
+ // Determine whether the validator associated with this error is failing
198
+ const state = computed(() => (hasError() ? 'fail' : 'pass'), ...(ngDevMode ? [{ debugName: "state" }] : []));
199
+ // Host bindings
200
+ attrBinding(element, 'id', id);
201
+ dataBinding(element, 'data-invalid', () => (formField()?.invalid() ? '' : null));
202
+ dataBinding(element, 'data-valid', () => (formField()?.valid() ? '' : null));
203
+ dataBinding(element, 'data-touched', () => (formField()?.touched() ? '' : null));
204
+ dataBinding(element, 'data-pristine', () => (formField()?.pristine() ? '' : null));
205
+ dataBinding(element, 'data-dirty', () => (formField()?.dirty() ? '' : null));
206
+ dataBinding(element, 'data-pending', () => (formField()?.pending() ? '' : null));
207
+ dataBinding(element, 'data-disabled', () => (formField()?.disabled() ? '' : null));
208
+ dataBinding(element, 'data-validator', state);
209
+ let currentId = id();
210
+ // Register/unregister with form field based on error state
211
+ function registerError() {
212
+ formField()?.addDescription(currentId);
213
+ }
214
+ function unregisterError() {
215
+ formField()?.removeDescription(currentId);
216
+ }
217
+ // Update error registration when hasError changes
218
+ onBooleanChange(hasError, registerError, unregisterError);
219
+ function updateIdRegistration(newId, oldId) {
220
+ if (oldId && hasError()) {
221
+ formField()?.removeDescription(oldId);
222
+ }
223
+ currentId = newId;
224
+ if (hasError()) {
225
+ formField()?.addDescription(newId);
226
+ }
227
+ }
228
+ // Watch for id changes to update registration
229
+ explicitEffect([id], () => updateIdRegistration(id(), currentId));
230
+ // Cleanup on destroy
231
+ onDestroy(() => {
232
+ if (hasError()) {
233
+ formField()?.removeDescription(currentId);
234
+ }
235
+ });
236
+ return {
237
+ id,
238
+ hasError,
239
+ state,
240
+ };
241
+ });
242
+
64
243
  /**
65
244
  * The `NgpError` directive is used to mark an error message element within a form field. There may be multiple error messages associated with a form control.
66
245
  */
67
246
  class NgpError {
247
+ /**
248
+ * The error state.
249
+ */
68
250
  constructor() {
69
- /**
70
- * Access the form field that the description is associated with.
71
- */
72
- this.formField = injectFormFieldState({ optional: true });
73
251
  /**
74
252
  * The id of the error message. If not provided, a unique id will be generated.
75
253
  */
@@ -80,67 +258,55 @@ class NgpError {
80
258
  this.validator = input(null, ...(ngDevMode ? [{ debugName: "validator", alias: 'ngpErrorValidator' }] : [{
81
259
  alias: 'ngpErrorValidator',
82
260
  }]));
83
- /**
84
- * Determine if there is an error message.
85
- */
86
- this.hasError = computed(() => {
87
- const errors = this.formField()?.errors() ?? [];
88
- const validator = this.validator();
89
- return validator ? errors?.includes(validator) : errors?.length > 0;
90
- }, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
91
- /**
92
- * Determine whether the validator associated with this error is failing.
93
- */
94
- this.state = computed(() => (this.hasError() ? 'fail' : 'pass'), ...(ngDevMode ? [{ debugName: "state" }] : []));
95
- // add or remove the error message when the error state changes
96
- onBooleanChange(this.hasError, () => this.formField()?.addDescription(this.id()), () => this.formField()?.removeDescription(this.id()));
97
- }
98
- ngOnChanges(changes) {
99
- if ('id' in changes) {
100
- this.formField()?.removeDescription(changes['id'].previousValue);
101
- }
102
- }
103
- ngOnDestroy() {
104
- this.formField()?.removeDescription(this.id());
261
+ ngpError({ id: this.id, validator: this.validator });
105
262
  }
106
263
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpError, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
107
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpError, isStandalone: true, selector: "[ngpError]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, validator: { classPropertyName: "validator", publicName: "ngpErrorValidator", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.id": "id()", "attr.data-invalid": "formField()?.invalid() ? \"\" : null", "attr.data-valid": "formField()?.valid() ? \"\" : null", "attr.data-touched": "formField()?.touched() ? \"\" : null", "attr.data-pristine": "formField()?.pristine() ? \"\" : null", "attr.data-dirty": "formField()?.dirty() ? \"\" : null", "attr.data-pending": "formField()?.pending() ? \"\" : null", "attr.data-disabled": "formField()?.disabled() ? \"\" : null", "attr.data-validator": "state()" } }, exportAs: ["ngpError"], usesOnChanges: true, ngImport: i0 }); }
264
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpError, isStandalone: true, selector: "[ngpError]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, validator: { classPropertyName: "validator", publicName: "ngpErrorValidator", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideErrorState()], exportAs: ["ngpError"], ngImport: i0 }); }
108
265
  }
109
266
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpError, decorators: [{
110
267
  type: Directive,
111
268
  args: [{
112
269
  selector: '[ngpError]',
113
270
  exportAs: 'ngpError',
114
- host: {
115
- '[attr.id]': 'id()',
116
- '[attr.data-invalid]': 'formField()?.invalid() ? "" : null',
117
- '[attr.data-valid]': 'formField()?.valid() ? "" : null',
118
- '[attr.data-touched]': 'formField()?.touched() ? "" : null',
119
- '[attr.data-pristine]': 'formField()?.pristine() ? "" : null',
120
- '[attr.data-dirty]': 'formField()?.dirty() ? "" : null',
121
- '[attr.data-pending]': 'formField()?.pending() ? "" : null',
122
- '[attr.data-disabled]': 'formField()?.disabled() ? "" : null',
123
- '[attr.data-validator]': 'state()',
124
- },
271
+ providers: [provideErrorState()],
125
272
  }]
126
273
  }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], validator: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpErrorValidator", required: false }] }] } });
127
274
 
128
- /**
129
- * The state token for the FormControl primitive.
130
- */
131
- const NgpFormControlStateToken = createStateToken('FormControl');
132
- /**
133
- * Provides the FormControl state.
134
- */
135
- const provideFormControlState = createStateProvider(NgpFormControlStateToken);
136
- /**
137
- * Injects the FormControl state.
138
- */
139
- const injectFormControlState = createStateInjector(NgpFormControlStateToken);
140
- /**
141
- * The FormControl state registration function.
142
- */
143
- const formControlState = createState(NgpFormControlStateToken);
275
+ function ngpFormControl({ id, disabled = signal(false), }) {
276
+ const elementRef = injectElementRef();
277
+ // Access the form field that the form control is associated with.
278
+ const formField = injectFormFieldState({ optional: true });
279
+ // Access the form control status.
280
+ const status = controlStatus();
281
+ // Determine the aria-labelledby attribute value.
282
+ const ariaLabelledBy = computed(() => {
283
+ const labels = formField()?.labels() ?? [];
284
+ return labels.length > 0 ? labels.join(' ') : null;
285
+ }, ...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : []));
286
+ // Determine the aria-describedby attribute value.
287
+ const ariaDescribedBy = computed(() => {
288
+ const descriptions = formField()?.descriptions() ?? [];
289
+ return descriptions.length > 0 ? descriptions.join(' ') : null;
290
+ }, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
291
+ const supportsDisabledAttribute = 'disabled' in elementRef.nativeElement;
292
+ // Host bindings
293
+ attrBinding(elementRef, 'disabled', () => (supportsDisabledAttribute && disabled() ? '' : null));
294
+ explicitEffect([id], ([id], onCleanup) => {
295
+ formField()?.setFormControl(id);
296
+ onCleanup(() => formField()?.removeFormControl());
297
+ });
298
+ attrBinding(elementRef, 'id', id);
299
+ attrBinding(elementRef, 'aria-labelledby', ariaLabelledBy);
300
+ attrBinding(elementRef, 'aria-describedby', ariaDescribedBy);
301
+ dataBinding(elementRef, 'data-invalid', () => status().invalid);
302
+ dataBinding(elementRef, 'data-valid', () => status().valid);
303
+ dataBinding(elementRef, 'data-touched', () => status().touched);
304
+ dataBinding(elementRef, 'data-pristine', () => status().pristine);
305
+ dataBinding(elementRef, 'data-dirty', () => status().dirty);
306
+ dataBinding(elementRef, 'data-pending', () => status().pending);
307
+ dataBinding(elementRef, 'data-disabled', () => disabled() || status().disabled);
308
+ return computed(() => ({ ...status(), disabled: status().disabled || disabled() }));
309
+ }
144
310
 
145
311
  /**
146
312
  * Typically this primitive would be not be used directly, but instead a more specific form control primitive would be used (e.g. `ngpInput`). All of our form control primitives use `ngpFormControl` internally so they will have the same accessibility features as described below.
@@ -162,243 +328,38 @@ class NgpFormControl {
162
328
  transform: booleanAttribute,
163
329
  }]));
164
330
  /**
165
- * The element reference.
331
+ * The status of the form control.
166
332
  */
167
- this.elementRef = injectElementRef();
168
- /**
169
- * Whether the element supports the disabled attribute.
170
- */
171
- this.supportsDisabledAttribute = 'disabled' in this.elementRef.nativeElement;
172
- /**
173
- * The state of the form control.
174
- */
175
- this.state = formControlState(this);
176
- // Sync the form control state with the control state.
177
- this.status = ngpFormControl({ id: this.state.id, disabled: this.state.disabled });
333
+ this.status = ngpFormControl({ id: this.id, disabled: this.disabled });
178
334
  }
179
335
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpFormControl, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
180
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpFormControl, isStandalone: true, selector: "[ngpFormControl]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpFormControlDisabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.disabled": "supportsDisabledAttribute && status().disabled ? \"\" : null" } }, providers: [provideFormControlState()], exportAs: ["ngpFormControl"], ngImport: i0 }); }
336
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpFormControl, isStandalone: true, selector: "[ngpFormControl]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpFormControlDisabled", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["ngpFormControl"], ngImport: i0 }); }
181
337
  }
182
338
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpFormControl, decorators: [{
183
339
  type: Directive,
184
340
  args: [{
185
341
  selector: '[ngpFormControl]',
186
342
  exportAs: 'ngpFormControl',
187
- providers: [provideFormControlState()],
188
- host: {
189
- '[attr.disabled]': 'supportsDisabledAttribute && status().disabled ? "" : null',
190
- },
191
343
  }]
192
- }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpFormControlDisabled", required: false }] }] } });
193
- function ngpFormControl({ id, disabled = signal(false), }) {
194
- const element = injectElementRef();
195
- // Access the form field that the form control is associated with.
196
- const formField = injectFormFieldState({ optional: true });
197
- // Access the form control status.
198
- const status = controlStatus();
199
- // Determine the aria-labelledby attribute value.
200
- const ariaLabelledBy = computed(() => formField()?.labels().join(' '), ...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : []));
201
- // Determine the aria-describedby attribute value.
202
- const ariaDescribedBy = computed(() => formField()?.descriptions().join(' '), ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
203
- explicitEffect([id], ([id], onCleanup) => {
204
- formField()?.setFormControl(id);
205
- onCleanup(() => formField()?.removeFormControl());
206
- });
207
- attrBinding(element, 'id', id);
208
- attrBinding(element, 'aria-labelledby', ariaLabelledBy);
209
- attrBinding(element, 'aria-describedby', ariaDescribedBy);
210
- dataBinding(element, 'data-invalid', () => status().invalid);
211
- dataBinding(element, 'data-valid', () => status().valid);
212
- dataBinding(element, 'data-touched', () => status().touched);
213
- dataBinding(element, 'data-pristine', () => status().pristine);
214
- dataBinding(element, 'data-dirty', () => status().dirty);
215
- dataBinding(element, 'data-pending', () => status().pending);
216
- dataBinding(element, 'data-disabled', () => disabled() || status().disabled);
217
- return computed(() => ({ ...status(), disabled: status().disabled || disabled() }));
218
- }
344
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpFormControlDisabled", required: false }] }] } });
219
345
 
220
346
  /**
221
347
  * The `NgpFormField` directive is a container for form field elements. Any labels, form controls, or descriptions should be placed within this directive.
222
348
  */
223
349
  class NgpFormField {
350
+ /**
351
+ * The form field state.
352
+ */
224
353
  constructor() {
225
- /**
226
- * Store the form label.
227
- * @internal
228
- */
229
- this.labels = signal([], ...(ngDevMode ? [{ debugName: "labels" }] : []));
230
- /**
231
- * Store the form descriptions.
232
- * @internal
233
- */
234
- this.descriptions = signal([], ...(ngDevMode ? [{ debugName: "descriptions" }] : []));
235
- /**
236
- * Store the id of the associated form control.
237
- * @internal
238
- */
239
- this.formControl = signal(null, ...(ngDevMode ? [{ debugName: "formControl" }] : []));
240
354
  /**
241
355
  * Find any NgControl within the form field.
242
356
  * @internal
243
357
  */
244
358
  this.ngControl = contentChild(NgControl, ...(ngDevMode ? [{ debugName: "ngControl" }] : []));
245
- /**
246
- * Store the validation error messages.
247
- * @internal
248
- */
249
- this.errors = signal([], ...(ngDevMode ? [{ debugName: "errors" }] : []));
250
- /**
251
- * Whether the control is pristine.
252
- * @internal
253
- */
254
- this.pristine = signal(null, ...(ngDevMode ? [{ debugName: "pristine" }] : []));
255
- /**
256
- * Whether the control is touched.
257
- * @internal
258
- */
259
- this.touched = signal(null, ...(ngDevMode ? [{ debugName: "touched" }] : []));
260
- /**
261
- * Whether the control is dirty.
262
- * @internal
263
- */
264
- this.dirty = signal(null, ...(ngDevMode ? [{ debugName: "dirty" }] : []));
265
- /**
266
- * Whether the control is valid.
267
- */
268
- this.valid = signal(null, ...(ngDevMode ? [{ debugName: "valid" }] : []));
269
- /**
270
- * Whether the control is invalid.
271
- * @internal
272
- */
273
- this.invalid = signal(null, ...(ngDevMode ? [{ debugName: "invalid" }] : []));
274
- /**
275
- * Whether the control is pending.
276
- * @internal
277
- */
278
- this.pending = signal(null, ...(ngDevMode ? [{ debugName: "pending" }] : []));
279
- /**
280
- * Whether the control is disabled.
281
- * @internal
282
- */
283
- this.disabled = signal(null, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
284
- /**
285
- * Injector for creating effects outside the constructor.
286
- */
287
- this.injector = inject(Injector);
288
- /**
289
- * The form field state.
290
- */
291
- this.state = formFieldState(this);
292
- // any time the ngControl changes, setup the subscriptions.
293
- onChange(this.ngControl, this.setupSubscriptions.bind(this));
294
- }
295
- ngOnDestroy() {
296
- this.subscription?.unsubscribe();
297
- }
298
- /**
299
- * Setup a listener for the form control status.
300
- * @param control
301
- */
302
- setupSubscriptions(control) {
303
- // Unsubscribe from the previous subscriptions.
304
- this.subscription?.unsubscribe();
305
- if (!control) {
306
- return;
307
- }
308
- // For signal-forms interop controls, use an effect to reactively track status.
309
- // For classic controls, also use an effect but additionally subscribe to events.
310
- effect(() => {
311
- this.updateStatus();
312
- }, { injector: this.injector });
313
- // Classic controls also have an events observable we can subscribe to.
314
- const underlyingControl = control?.control;
315
- if (underlyingControl?.events) {
316
- this.subscription = underlyingControl.events.subscribe(() => this.updateStatus());
317
- }
318
- }
319
- updateStatus() {
320
- const control = this.ngControl();
321
- if (!control) {
322
- return;
323
- }
324
- // Wrap in try-catch to handle signal-forms interop controls where
325
- // the `field` input may not be available yet (throws NG0950).
326
- // Reading the signal still establishes a dependency, so the effect
327
- // will re-run when the input becomes available.
328
- try {
329
- const pristine = control.pristine;
330
- const touched = control.touched;
331
- const dirty = control.dirty;
332
- const valid = control.valid;
333
- const invalid = control.invalid;
334
- const pending = control.pending;
335
- const disabled = control.disabled;
336
- const errors = control.errors;
337
- untracked(() => {
338
- this.pristine.set(pristine);
339
- this.touched.set(touched);
340
- this.dirty.set(dirty);
341
- this.valid.set(valid);
342
- this.invalid.set(invalid);
343
- this.pending.set(pending);
344
- this.disabled.set(disabled);
345
- this.errors.set(errors ? Object.keys(errors) : []);
346
- });
347
- }
348
- catch {
349
- // NG0950: Required input not available yet. The effect will re-run
350
- // when the signal input becomes available.
351
- }
352
- }
353
- /**
354
- * Register the id of the associated form control.
355
- * @param id
356
- * @internal
357
- */
358
- setFormControl(id) {
359
- this.formControl.set(id);
360
- }
361
- /**
362
- * Register a label with the form field.
363
- * @param label
364
- * @internal
365
- */
366
- addLabel(label) {
367
- this.labels.update(labels => [...labels, label]);
368
- }
369
- /**
370
- * Register a description with the form field.
371
- * @param description
372
- * @internal
373
- */
374
- addDescription(description) {
375
- this.descriptions.update(descriptions => [...descriptions, description]);
376
- }
377
- /**
378
- * Remove the associated form control.
379
- * @internal
380
- */
381
- removeFormControl() {
382
- this.formControl.set(null);
383
- }
384
- /**
385
- * Remove a label from the form field.
386
- * @param label
387
- * @internal
388
- */
389
- removeLabel(label) {
390
- this.labels.update(labels => labels.filter(l => l !== label));
391
- }
392
- /**
393
- * Remove a description from the form field.
394
- * @param description
395
- * @internal
396
- */
397
- removeDescription(description) {
398
- this.descriptions.update(descriptions => descriptions.filter(d => d !== description));
359
+ ngpFormField({ ngControl: this.ngControl });
399
360
  }
400
361
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpFormField, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
401
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.9", type: NgpFormField, isStandalone: true, selector: "[ngpFormField]", host: { properties: { "attr.data-invalid": "invalid() ? \"\" : null", "attr.data-valid": "valid() ? \"\" : null", "attr.data-touched": "touched() ? \"\" : null", "attr.data-pristine": "pristine() ? \"\" : null", "attr.data-dirty": "dirty() ? \"\" : null", "attr.data-pending": "pending() ? \"\" : null", "attr.data-disabled": "disabled() ? \"\" : null" } }, providers: [provideFormFieldState()], queries: [{ propertyName: "ngControl", first: true, predicate: NgControl, descendants: true, isSignal: true }], exportAs: ["ngpFormField"], ngImport: i0 }); }
362
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.9", type: NgpFormField, isStandalone: true, selector: "[ngpFormField]", providers: [provideFormFieldState()], queries: [{ propertyName: "ngControl", first: true, predicate: NgControl, descendants: true, isSignal: true }], exportAs: ["ngpFormField"], ngImport: i0 }); }
402
363
  }
403
364
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpFormField, decorators: [{
404
365
  type: Directive,
@@ -406,59 +367,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
406
367
  selector: '[ngpFormField]',
407
368
  exportAs: 'ngpFormField',
408
369
  providers: [provideFormFieldState()],
409
- host: {
410
- '[attr.data-invalid]': 'invalid() ? "" : null',
411
- '[attr.data-valid]': 'valid() ? "" : null',
412
- '[attr.data-touched]': 'touched() ? "" : null',
413
- '[attr.data-pristine]': 'pristine() ? "" : null',
414
- '[attr.data-dirty]': 'dirty() ? "" : null',
415
- '[attr.data-pending]': 'pending() ? "" : null',
416
- '[attr.data-disabled]': 'disabled() ? "" : null',
417
- },
418
370
  }]
419
371
  }], ctorParameters: () => [], propDecorators: { ngControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NgControl), { isSignal: true }] }] } });
420
372
 
421
- /**
422
- * The `NgpLabel` directive is used to mark a label element within a form field. Preferably, there should use an HTML `<label>` element.
423
- */
424
- class NgpLabel {
425
- constructor() {
426
- /**
427
- * The id of the label. If not provided, a unique id will be generated.
428
- */
429
- this.id = input(uniqueId('ngp-label'), ...(ngDevMode ? [{ debugName: "id" }] : []));
430
- /**
431
- * Access the form field that the label is associated with.
432
- */
433
- this.formField = injectFormFieldState({ optional: true });
434
- /**
435
- * Derive the for attribute value if the label is an HTML label element.
436
- */
437
- this.htmlFor = computed(() => this.formField()?.formControl(), ...(ngDevMode ? [{ debugName: "htmlFor" }] : []));
438
- /**
439
- * Access the element that the label is associated with.
440
- */
441
- this.elementRef = inject(ElementRef);
442
- /**
443
- * Determine if the label is an HTML label element.
444
- */
445
- this.isLabel = this.elementRef.nativeElement instanceof HTMLLabelElement;
446
- effect(onCleanup => {
447
- this.formField()?.addLabel(this.id());
448
- onCleanup(() => this.formField()?.removeLabel(this.id()));
449
- });
450
- }
451
- onClick(event) {
373
+ const [NgpLabelStateToken, ngpLabel, injectLabelState, provideLabelState] = createPrimitive('NgpLabel', ({ id }) => {
374
+ const element = injectElementRef();
375
+ const formField = injectFormFieldState({ optional: true });
376
+ // Derive the for attribute value if the label is an HTML label element
377
+ const htmlFor = computed(() => formField()?.formControl() ?? null, ...(ngDevMode ? [{ debugName: "htmlFor" }] : []));
378
+ // Determine if the label is an HTML label element
379
+ const isLabel = element.nativeElement instanceof HTMLLabelElement;
380
+ // Host bindings
381
+ attrBinding(element, 'id', id);
382
+ attrBinding(element, 'for', htmlFor);
383
+ dataBinding(element, 'data-invalid', () => (formField()?.invalid() ? '' : null));
384
+ dataBinding(element, 'data-valid', () => (formField()?.valid() ? '' : null));
385
+ dataBinding(element, 'data-touched', () => (formField()?.touched() ? '' : null));
386
+ dataBinding(element, 'data-pristine', () => (formField()?.pristine() ? '' : null));
387
+ dataBinding(element, 'data-dirty', () => (formField()?.dirty() ? '' : null));
388
+ dataBinding(element, 'data-pending', () => (formField()?.pending() ? '' : null));
389
+ dataBinding(element, 'data-disabled', () => (formField()?.disabled() ? '' : null));
390
+ function onClick(event) {
452
391
  // by default a label will perform a click on the associated form control, however
453
392
  // this only works if the associated form control is an input element which may not always
454
393
  // be the case, so we prevent the default behavior and handle the click event ourselves.
455
394
  // This was inspired by the HeadlessUI approach:
456
395
  // https://github.com/tailwindlabs/headlessui/blob/main/packages/%40headlessui-react/src/components/label/label.tsx#L58
457
- if (this.isLabel) {
396
+ if (isLabel) {
458
397
  event.preventDefault();
459
398
  }
460
399
  // to find the associated form control we can lookup via the known id
461
- const targetId = this.htmlFor();
400
+ const targetId = htmlFor();
462
401
  if (!targetId) {
463
402
  return;
464
403
  }
@@ -484,34 +423,53 @@ class NgpLabel {
484
423
  // bound element is now focused.
485
424
  target.focus({ preventScroll: true });
486
425
  }
426
+ // Event listeners
427
+ listener(element, 'click', onClick);
428
+ // Register with form field and cleanup on destroy
429
+ formField()?.addLabel(id());
430
+ onDestroy(() => formField()?.removeLabel(id()));
431
+ // any time the id changes we need to update the registration with the form field
432
+ onChange(id, (newId, oldId) => {
433
+ if (oldId) {
434
+ formField()?.removeLabel(oldId);
435
+ }
436
+ formField()?.addLabel(newId);
437
+ });
438
+ return {
439
+ id,
440
+ htmlFor,
441
+ };
442
+ });
443
+
444
+ /**
445
+ * The `NgpLabel` directive is used to mark a label element within a form field. Preferably, there should use an HTML `<label>` element.
446
+ */
447
+ class NgpLabel {
448
+ /**
449
+ * The label state.
450
+ */
451
+ constructor() {
452
+ /**
453
+ * The id of the label. If not provided, a unique id will be generated.
454
+ */
455
+ this.id = input(uniqueId('ngp-label'), ...(ngDevMode ? [{ debugName: "id" }] : []));
456
+ ngpLabel({ id: this.id });
457
+ }
487
458
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpLabel, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
488
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpLabel, isStandalone: true, selector: "[ngpLabel]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick($event)" }, properties: { "attr.id": "id()", "attr.for": "htmlFor()", "attr.data-invalid": "formField()?.invalid() ? \"\" : null", "attr.data-valid": "formField()?.valid() ? \"\" : null", "attr.data-touched": "formField()?.touched() ? \"\" : null", "attr.data-pristine": "formField()?.pristine() ? \"\" : null", "attr.data-dirty": "formField()?.dirty() ? \"\" : null", "attr.data-pending": "formField()?.pending() ? \"\" : null", "attr.data-disabled": "formField()?.disabled() ? \"\" : null" } }, exportAs: ["ngpLabel"], ngImport: i0 }); }
459
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpLabel, isStandalone: true, selector: "[ngpLabel]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideLabelState()], exportAs: ["ngpLabel"], ngImport: i0 }); }
489
460
  }
490
461
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpLabel, decorators: [{
491
462
  type: Directive,
492
463
  args: [{
493
464
  selector: '[ngpLabel]',
494
465
  exportAs: 'ngpLabel',
495
- host: {
496
- '[attr.id]': 'id()',
497
- '[attr.for]': 'htmlFor()',
498
- '[attr.data-invalid]': 'formField()?.invalid() ? "" : null',
499
- '[attr.data-valid]': 'formField()?.valid() ? "" : null',
500
- '[attr.data-touched]': 'formField()?.touched() ? "" : null',
501
- '[attr.data-pristine]': 'formField()?.pristine() ? "" : null',
502
- '[attr.data-dirty]': 'formField()?.dirty() ? "" : null',
503
- '[attr.data-pending]': 'formField()?.pending() ? "" : null',
504
- '[attr.data-disabled]': 'formField()?.disabled() ? "" : null',
505
- },
466
+ providers: [provideLabelState()],
506
467
  }]
507
- }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], onClick: [{
508
- type: HostListener,
509
- args: ['click', ['$event']]
510
- }] } });
468
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
511
469
 
512
470
  /**
513
471
  * Generated bundle index. Do not edit.
514
472
  */
515
473
 
516
- export { NgpDescription, NgpError, NgpFormControl, NgpFormField, NgpLabel, injectFormControlState, injectFormFieldState, ngpFormControl, provideFormControlState, provideFormFieldState };
474
+ export { NgpDescription, NgpError, NgpFormControl, NgpFormField, NgpLabel, injectDescriptionState, injectErrorState, injectFormFieldState, injectLabelState, ngpDescription, ngpError, ngpFormControl, ngpFormField, ngpLabel, provideDescriptionState, provideErrorState, provideFormFieldState, provideLabelState };
517
475
  //# sourceMappingURL=ng-primitives-form-field.mjs.map