@ng-forge/dynamic-forms-bootstrap 0.8.0 → 0.9.0-next.10

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.
@@ -1,28 +1,18 @@
1
1
  import { AsyncPipe } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, input, computed, ChangeDetectionStrategy, Component, ElementRef, viewChild, Directive, InjectionToken, afterRenderEffect, linkedSignal, model, isSignal } from '@angular/core';
4
- import { EventBus, ARRAY_CONTEXT, resolveTokens, DynamicTextPipe, DEFAULT_PROPS, buildBaseInputs } from '@ng-forge/dynamic-forms';
5
- import { explicitEffect } from 'ngxtension/explicit-effect';
3
+ import { input, computed, ChangeDetectionStrategy, Component, inject, ElementRef, Directive, InjectionToken, linkedSignal, model, viewChild, afterRenderEffect, isSignal } from '@angular/core';
4
+ import { DynamicTextPipe, DEFAULT_PROPS, ARRAY_CONTEXT, buildBaseInputs } from '@ng-forge/dynamic-forms';
5
+ import * as i1 from '@ng-forge/dynamic-forms/integration';
6
+ import { injectNgForgeAction, NgForgeActionHost, injectNgForgeField, NgForgeControl, NgForgeFieldHost, isEqual, valueFieldMapper, optionsFieldMapper, checkboxFieldMapper, submitButtonFieldMapper, nextButtonFieldMapper, previousButtonFieldMapper, addArrayItemButtonMapper, prependArrayItemButtonMapper, insertArrayItemButtonMapper, removeArrayItemButtonMapper, popArrayItemButtonMapper, shiftArrayItemButtonMapper, datepickerFieldMapper } from '@ng-forge/dynamic-forms/integration';
6
7
  import { FormField } from '@angular/forms/signals';
7
- import { createResolvedErrorsSignal, shouldShowErrors, setupMetaTracking, isEqual, valueFieldMapper, optionsFieldMapper, checkboxFieldMapper, submitButtonFieldMapper, nextButtonFieldMapper, previousButtonFieldMapper, addArrayItemButtonMapper, prependArrayItemButtonMapper, insertArrayItemButtonMapper, removeArrayItemButtonMapper, popArrayItemButtonMapper, shiftArrayItemButtonMapper, datepickerFieldMapper } from '@ng-forge/dynamic-forms/integration';
8
+ import { explicitEffect } from 'ngxtension/explicit-effect';
8
9
 
9
10
  class BsButtonFieldComponent {
10
- eventBus = inject(EventBus);
11
- arrayContext = inject(ARRAY_CONTEXT, { optional: true });
12
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
13
- label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
14
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
15
- hidden = input(false, ...(ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []));
16
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
17
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
18
- /** Event to dispatch on click. Optional for submit buttons (native form submit handles it). */
19
- event = input(...(ngDevMode ? [undefined, { debugName: "event" }] : /* istanbul ignore next */ []));
20
- eventArgs = input(...(ngDevMode ? [undefined, { debugName: "eventArgs" }] : /* istanbul ignore next */ []));
11
+ action = injectNgForgeAction();
21
12
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
22
- eventContext = input(...(ngDevMode ? [undefined, { debugName: "eventContext" }] : /* istanbul ignore next */ []));
23
- /** Resolved button type - defaults to 'button' if not specified in props */
13
+ /** Resolved button type defaults to 'button' unless overridden via props. */
24
14
  buttonType = computed(() => this.props()?.type ?? 'button', ...(ngDevMode ? [{ debugName: "buttonType" }] : /* istanbul ignore next */ []));
25
- buttonTestId = computed(() => `${this.buttonType()}-${this.key()}`, ...(ngDevMode ? [{ debugName: "buttonTestId" }] : /* istanbul ignore next */ []));
15
+ buttonTestId = computed(() => `${this.buttonType()}-${this.action.key()}`, ...(ngDevMode ? [{ debugName: "buttonTestId" }] : /* istanbul ignore next */ []));
26
16
  buttonClasses = computed(() => {
27
17
  const p = this.props();
28
18
  const variant = p?.variant || 'primary';
@@ -34,88 +24,50 @@ class BsButtonFieldComponent {
34
24
  p?.size === 'lg' && 'btn-lg',
35
25
  p?.block && 'w-100',
36
26
  p?.active && 'active',
37
- this.className(),
27
+ this.action.className(),
38
28
  ]
39
29
  .filter(Boolean)
40
30
  .join(' ');
41
31
  }, ...(ngDevMode ? [{ debugName: "buttonClasses" }] : /* istanbul ignore next */ []));
42
- /**
43
- * Handle button click.
44
- * - For submit buttons (type="submit"): do nothing, native form submit handles it
45
- * - For other buttons: dispatch the configured event via EventBus
46
- */
32
+ /** Submit buttons let the native form handle submission; other buttons dispatch via the directive. */
47
33
  onClick() {
48
- // Native submit buttons let the form handle submission
49
- if (this.buttonType() === 'submit') {
34
+ if (this.buttonType() === 'submit')
50
35
  return;
51
- }
52
- // Other buttons dispatch their event (if configured)
53
- const event = this.event();
54
- if (event) {
55
- this.dispatchEvent(event);
56
- }
57
- }
58
- dispatchEvent(event) {
59
- const args = this.eventArgs();
60
- if (args && args.length > 0) {
61
- // Build context from injected ARRAY_CONTEXT (with linkedSignal index) or fallback to eventContext
62
- const context = this.arrayContext
63
- ? {
64
- key: this.key(),
65
- // Read signal to get current index (automatically updates via linkedSignal)
66
- index: this.arrayContext.index(),
67
- arrayKey: this.arrayContext.arrayKey,
68
- formValue: this.arrayContext.formValue,
69
- }
70
- : this.eventContext() || { key: this.key() };
71
- // Resolve tokens in event args using the provided context
72
- const resolvedArgs = resolveTokens(args, context);
73
- // Dispatch event with resolved args
74
- this.eventBus.dispatch(event, ...resolvedArgs);
75
- }
76
- else {
77
- // No args, dispatch event without arguments
78
- this.eventBus.dispatch(event);
79
- }
36
+ this.action.dispatch();
80
37
  }
81
38
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsButtonFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
82
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: BsButtonFieldComponent, isStandalone: true, selector: "df-bs-button", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, event: { classPropertyName: "event", publicName: "event", isSignal: true, isRequired: false, transformFunction: null }, eventArgs: { classPropertyName: "eventArgs", publicName: "eventArgs", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, eventContext: { classPropertyName: "eventContext", publicName: "eventContext", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "hidden() || null" } }, ngImport: i0, template: `
83
- @let buttonId = key() + '-button';
39
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: BsButtonFieldComponent, isStandalone: true, selector: "df-bs-button", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeActionHost }], ngImport: i0, template: `
40
+ @let buttonId = action.key() + '-button';
84
41
  <button
85
42
  [id]="buttonId"
86
43
  [type]="buttonType()"
87
- [disabled]="disabled()"
44
+ [disabled]="action.disabled()"
88
45
  [class]="buttonClasses()"
89
- [attr.tabindex]="tabIndex()"
46
+ [attr.tabindex]="action.tabIndex()"
90
47
  [attr.data-testid]="buttonTestId()"
91
48
  (click)="onClick()"
92
49
  >
93
- {{ label() | dynamicText | async }}
50
+ {{ action.label() | dynamicText | async }}
94
51
  </button>
95
52
  `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
96
53
  }
97
54
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsButtonFieldComponent, decorators: [{
98
55
  type: Component,
99
- args: [{ selector: 'df-bs-button', imports: [DynamicTextPipe, AsyncPipe], host: {
100
- '[id]': '`${key()}`',
101
- '[attr.data-testid]': 'key()',
102
- '[class]': 'className()',
103
- '[attr.hidden]': 'hidden() || null',
104
- }, template: `
105
- @let buttonId = key() + '-button';
56
+ args: [{ selector: 'df-bs-button', imports: [DynamicTextPipe, AsyncPipe], hostDirectives: [NgForgeActionHost], template: `
57
+ @let buttonId = action.key() + '-button';
106
58
  <button
107
59
  [id]="buttonId"
108
60
  [type]="buttonType()"
109
- [disabled]="disabled()"
61
+ [disabled]="action.disabled()"
110
62
  [class]="buttonClasses()"
111
- [attr.tabindex]="tabIndex()"
63
+ [attr.tabindex]="action.tabIndex()"
112
64
  [attr.data-testid]="buttonTestId()"
113
65
  (click)="onClick()"
114
66
  >
115
- {{ label() | dynamicText | async }}
67
+ {{ action.label() | dynamicText | async }}
116
68
  </button>
117
69
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n"] }]
118
- }], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], event: [{ type: i0.Input, args: [{ isSignal: true, alias: "event", required: false }] }], eventArgs: [{ type: i0.Input, args: [{ isSignal: true, alias: "eventArgs", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], eventContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "eventContext", required: false }] }] } });
70
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
119
71
 
120
72
  var bsButton_component = /*#__PURE__*/Object.freeze({
121
73
  __proto__: null,
@@ -124,72 +76,12 @@ var bsButton_component = /*#__PURE__*/Object.freeze({
124
76
 
125
77
  // Public API - component
126
78
 
127
- /**
128
- * Creates a signal that computes the aria-describedby value based on errors and hint state.
129
- * Errors take precedence over hints - when errors are displayed, the hint is hidden.
130
- * Only the first error is displayed (single error ID, not indexed).
131
- *
132
- * @param errorsToDisplay Signal containing the array of errors currently being displayed
133
- * @param errorId Signal containing the ID for the error element (single error only)
134
- * @param hintId Signal containing the ID for the hint element
135
- * @param hasHint Function that returns true if a hint is configured
136
- * @returns Signal containing the aria-describedby value or null
137
- */
138
- function createAriaDescribedBySignal(errorsToDisplay, errorId, hintId, hasHint) {
139
- return computed(() => {
140
- if (errorsToDisplay().length > 0) {
141
- return errorId();
142
- }
143
- if (hasHint()) {
144
- return hintId();
145
- }
146
- return null;
147
- });
148
- }
149
-
150
79
  class BsCheckboxFieldComponent {
151
- elementRef = inject((ElementRef));
152
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
153
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
154
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
155
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
156
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
157
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
80
+ ngf = injectNgForgeField();
158
81
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
159
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
160
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
161
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
162
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
163
- showErrors = shouldShowErrors(this.field);
164
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
165
- checkboxInput = viewChild('checkboxInput', ...(ngDevMode ? [{ debugName: "checkboxInput" }] : /* istanbul ignore next */ []));
166
- constructor() {
167
- setupMetaTracking(this.elementRef, this.meta, { selector: 'input[type="checkbox"]' });
168
- // Handle indeterminate state
169
- explicitEffect([this.props, this.checkboxInput], ([props, checkboxInput]) => {
170
- const indeterminate = props?.indeterminate;
171
- const inputEl = checkboxInput?.nativeElement;
172
- if (inputEl && indeterminate !== undefined) {
173
- inputEl.indeterminate = indeterminate;
174
- }
175
- });
176
- }
177
- // ─────────────────────────────────────────────────────────────────────────────
178
- // Accessibility
179
- // ─────────────────────────────────────────────────────────────────────────────
180
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
181
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
182
- ariaInvalid = computed(() => {
183
- const fieldState = this.field()();
184
- return fieldState.invalid() && fieldState.touched();
185
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
186
- ariaRequired = computed(() => {
187
- return this.field()().required?.() === true ? true : null;
188
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
189
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
190
82
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
191
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsCheckboxFieldComponent, isStandalone: true, selector: "df-bs-checkbox", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, viewQueries: [{ propertyName: "checkboxInput", first: true, predicate: ["checkboxInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
192
- @let f = field(); @let checkboxId = key() + '-checkbox';
83
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsCheckboxFieldComponent, isStandalone: true, selector: "df-bs-checkbox", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
84
+ @let f = ngf.field(); @let checkboxId = ngf.key() + '-checkbox';
193
85
 
194
86
  <div
195
87
  class="form-check"
@@ -199,33 +91,31 @@ class BsCheckboxFieldComponent {
199
91
  [attr.hidden]="f().hidden() || null"
200
92
  >
201
93
  <input
202
- #checkboxInput
94
+ ngForgeControl
203
95
  type="checkbox"
204
96
  [formField]="f"
205
97
  [id]="checkboxId"
98
+ [indeterminate]="props()?.indeterminate ?? false"
206
99
  class="form-check-input"
207
100
  [class.is-invalid]="f().invalid() && f().touched()"
208
- [attr.tabindex]="tabIndex()"
209
- [attr.aria-invalid]="ariaInvalid()"
210
- [attr.aria-required]="ariaRequired()"
211
- [attr.aria-describedby]="ariaDescribedBy()"
101
+ [attr.tabindex]="ngf.tabIndex()"
212
102
  />
213
103
  <label [for]="checkboxId" class="form-check-label">
214
- {{ label() | dynamicText | async }}
104
+ {{ ngf.label() | dynamicText | async }}
215
105
  </label>
216
106
  </div>
217
107
 
218
- @if (errorsToDisplay()[0]; as error) {
219
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
108
+ @if (ngf.errorsToDisplay()[0]; as error) {
109
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
220
110
  } @else if (props()?.hint; as hint) {
221
- <div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
111
+ <div class="form-text" [id]="ngf.hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
222
112
  }
223
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
113
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
224
114
  }
225
115
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsCheckboxFieldComponent, decorators: [{
226
116
  type: Component,
227
- args: [{ selector: 'df-bs-checkbox', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
228
- @let f = field(); @let checkboxId = key() + '-checkbox';
117
+ args: [{ selector: 'df-bs-checkbox', imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
118
+ @let f = ngf.field(); @let checkboxId = ngf.key() + '-checkbox';
229
119
 
230
120
  <div
231
121
  class="form-check"
@@ -235,34 +125,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
235
125
  [attr.hidden]="f().hidden() || null"
236
126
  >
237
127
  <input
238
- #checkboxInput
128
+ ngForgeControl
239
129
  type="checkbox"
240
130
  [formField]="f"
241
131
  [id]="checkboxId"
132
+ [indeterminate]="props()?.indeterminate ?? false"
242
133
  class="form-check-input"
243
134
  [class.is-invalid]="f().invalid() && f().touched()"
244
- [attr.tabindex]="tabIndex()"
245
- [attr.aria-invalid]="ariaInvalid()"
246
- [attr.aria-required]="ariaRequired()"
247
- [attr.aria-describedby]="ariaDescribedBy()"
135
+ [attr.tabindex]="ngf.tabIndex()"
248
136
  />
249
137
  <label [for]="checkboxId" class="form-check-label">
250
- {{ label() | dynamicText | async }}
138
+ {{ ngf.label() | dynamicText | async }}
251
139
  </label>
252
140
  </div>
253
141
 
254
- @if (errorsToDisplay()[0]; as error) {
255
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
142
+ @if (ngf.errorsToDisplay()[0]; as error) {
143
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
256
144
  } @else if (props()?.hint; as hint) {
257
- <div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
145
+ <div class="form-text" [id]="ngf.hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
258
146
  }
259
- `, host: {
260
- '[class]': 'className()',
261
- '[id]': '`${key()}`',
262
- '[attr.data-testid]': 'key()',
263
- '[attr.hidden]': 'field()().hidden() || null',
264
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
265
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], checkboxInput: [{ type: i0.ViewChild, args: ['checkboxInput', { isSignal: true }] }] } });
147
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
148
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
266
149
 
267
150
  var bsCheckbox_component = /*#__PURE__*/Object.freeze({
268
151
  __proto__: null,
@@ -315,26 +198,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
315
198
  }], propDecorators: { dfMin: [{ type: i0.Input, args: [{ isSignal: true, alias: "dfMin", required: false }] }], dfMax: [{ type: i0.Input, args: [{ isSignal: true, alias: "dfMax", required: false }] }], dfStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "dfStep", required: false }] }] } });
316
199
 
317
200
  class BsDatepickerFieldComponent {
318
- elementRef = inject((ElementRef));
319
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
320
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
321
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
322
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
323
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
324
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
201
+ ngf = injectNgForgeField();
325
202
  minDate = input(null, ...(ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []));
326
203
  maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []));
327
204
  startAt = input(null, ...(ngDevMode ? [{ debugName: "startAt" }] : /* istanbul ignore next */ []));
328
205
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
329
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
330
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
331
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
332
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
333
- showErrors = shouldShowErrors(this.field);
334
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
335
- constructor() {
336
- setupMetaTracking(this.elementRef, this.meta, { selector: 'input' });
337
- }
338
206
  // Helper methods to convert Date to string for HTML attributes
339
207
  minAsString = computed(() => {
340
208
  const min = this.minDate();
@@ -344,74 +212,57 @@ class BsDatepickerFieldComponent {
344
212
  const max = this.maxDate();
345
213
  return max instanceof Date ? max.toISOString().split('T')[0] : max;
346
214
  }, ...(ngDevMode ? [{ debugName: "maxAsString" }] : /* istanbul ignore next */ []));
347
- // ─────────────────────────────────────────────────────────────────────────────
348
- // Accessibility
349
- // ─────────────────────────────────────────────────────────────────────────────
350
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
351
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
352
- ariaInvalid = computed(() => {
353
- const fieldState = this.field()();
354
- return fieldState.invalid() && fieldState.touched();
355
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
356
- ariaRequired = computed(() => {
357
- return this.field()().required?.() === true ? true : null;
358
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
359
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
360
215
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsDatepickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
361
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsDatepickerFieldComponent, isStandalone: true, selector: "df-bs-datepicker", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
362
- @let f = field(); @let p = props(); @let inputId = key() + '-input';
216
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsDatepickerFieldComponent, isStandalone: true, selector: "df-bs-datepicker", inputs: { minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
217
+ @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';
363
218
  @if (p?.floatingLabel) {
364
219
  <!-- Floating label variant -->
365
220
  <div class="form-floating mb-3">
366
221
  <input
222
+ ngForgeControl
367
223
  dfBsInputConstraints
368
224
  [formField]="f"
369
225
  [id]="inputId"
370
226
  type="date"
371
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
227
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
372
228
  [dfMin]="minAsString()"
373
229
  [dfMax]="maxAsString()"
374
- [attr.tabindex]="tabIndex()"
375
- [attr.aria-invalid]="ariaInvalid()"
376
- [attr.aria-required]="ariaRequired()"
377
- [attr.aria-describedby]="ariaDescribedBy()"
230
+ [attr.tabindex]="ngf.tabIndex()"
378
231
  class="form-control"
379
232
  [class.form-control-sm]="p?.size === 'sm'"
380
233
  [class.form-control-lg]="p?.size === 'lg'"
381
234
  [class.is-invalid]="f().invalid() && f().touched()"
382
235
  [class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
383
236
  />
384
- @if (label()) {
385
- <label [for]="inputId">{{ label() | dynamicText | async }}</label>
237
+ @if (ngf.label()) {
238
+ <label [for]="inputId">{{ ngf.label() | dynamicText | async }}</label>
386
239
  }
387
240
  @if (p?.validFeedback && f().valid() && f().touched()) {
388
241
  <div class="valid-feedback d-block">
389
242
  {{ p?.validFeedback | dynamicText | async }}
390
243
  </div>
391
244
  }
392
- @if (errorsToDisplay()[0]; as error) {
393
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
245
+ @if (ngf.errorsToDisplay()[0]; as error) {
246
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
394
247
  }
395
248
  </div>
396
249
  } @else {
397
250
  <!-- Standard variant -->
398
251
  <div class="mb-3">
399
- @if (label()) {
400
- <label [for]="inputId" class="form-label">{{ label() | dynamicText | async }}</label>
252
+ @if (ngf.label()) {
253
+ <label [for]="inputId" class="form-label">{{ ngf.label() | dynamicText | async }}</label>
401
254
  }
402
255
 
403
256
  <input
257
+ ngForgeControl
404
258
  dfBsInputConstraints
405
259
  [formField]="f"
406
260
  [id]="inputId"
407
261
  type="date"
408
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
262
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
409
263
  [dfMin]="minAsString()"
410
264
  [dfMax]="maxAsString()"
411
- [attr.tabindex]="tabIndex()"
412
- [attr.aria-invalid]="ariaInvalid()"
413
- [attr.aria-required]="ariaRequired()"
414
- [attr.aria-describedby]="ariaDescribedBy()"
265
+ [attr.tabindex]="ngf.tabIndex()"
415
266
  class="form-control"
416
267
  [class.form-control-sm]="p?.size === 'sm'"
417
268
  [class.form-control-lg]="p?.size === 'lg'"
@@ -424,71 +275,67 @@ class BsDatepickerFieldComponent {
424
275
  {{ p?.validFeedback | dynamicText | async }}
425
276
  </div>
426
277
  }
427
- @if (errorsToDisplay()[0]; as error) {
428
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
278
+ @if (ngf.errorsToDisplay()[0]; as error) {
279
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
429
280
  } @else if (p?.hint) {
430
- <div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
281
+ <div class="form-text" [id]="ngf.hintId()">{{ p?.hint | dynamicText | async }}</div>
431
282
  }
432
283
  </div>
433
284
  }
434
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: InputConstraintsDirective, selector: "[dfBsInputConstraints]", inputs: ["dfMin", "dfMax", "dfStep"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
285
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: InputConstraintsDirective, selector: "[dfBsInputConstraints]", inputs: ["dfMin", "dfMax", "dfStep"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
435
286
  }
436
287
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsDatepickerFieldComponent, decorators: [{
437
288
  type: Component,
438
- args: [{ selector: 'df-bs-datepicker', imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective], template: `
439
- @let f = field(); @let p = props(); @let inputId = key() + '-input';
289
+ args: [{ selector: 'df-bs-datepicker', imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
290
+ @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';
440
291
  @if (p?.floatingLabel) {
441
292
  <!-- Floating label variant -->
442
293
  <div class="form-floating mb-3">
443
294
  <input
295
+ ngForgeControl
444
296
  dfBsInputConstraints
445
297
  [formField]="f"
446
298
  [id]="inputId"
447
299
  type="date"
448
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
300
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
449
301
  [dfMin]="minAsString()"
450
302
  [dfMax]="maxAsString()"
451
- [attr.tabindex]="tabIndex()"
452
- [attr.aria-invalid]="ariaInvalid()"
453
- [attr.aria-required]="ariaRequired()"
454
- [attr.aria-describedby]="ariaDescribedBy()"
303
+ [attr.tabindex]="ngf.tabIndex()"
455
304
  class="form-control"
456
305
  [class.form-control-sm]="p?.size === 'sm'"
457
306
  [class.form-control-lg]="p?.size === 'lg'"
458
307
  [class.is-invalid]="f().invalid() && f().touched()"
459
308
  [class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
460
309
  />
461
- @if (label()) {
462
- <label [for]="inputId">{{ label() | dynamicText | async }}</label>
310
+ @if (ngf.label()) {
311
+ <label [for]="inputId">{{ ngf.label() | dynamicText | async }}</label>
463
312
  }
464
313
  @if (p?.validFeedback && f().valid() && f().touched()) {
465
314
  <div class="valid-feedback d-block">
466
315
  {{ p?.validFeedback | dynamicText | async }}
467
316
  </div>
468
317
  }
469
- @if (errorsToDisplay()[0]; as error) {
470
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
318
+ @if (ngf.errorsToDisplay()[0]; as error) {
319
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
471
320
  }
472
321
  </div>
473
322
  } @else {
474
323
  <!-- Standard variant -->
475
324
  <div class="mb-3">
476
- @if (label()) {
477
- <label [for]="inputId" class="form-label">{{ label() | dynamicText | async }}</label>
325
+ @if (ngf.label()) {
326
+ <label [for]="inputId" class="form-label">{{ ngf.label() | dynamicText | async }}</label>
478
327
  }
479
328
 
480
329
  <input
330
+ ngForgeControl
481
331
  dfBsInputConstraints
482
332
  [formField]="f"
483
333
  [id]="inputId"
484
334
  type="date"
485
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
335
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
486
336
  [dfMin]="minAsString()"
487
337
  [dfMax]="maxAsString()"
488
- [attr.tabindex]="tabIndex()"
489
- [attr.aria-invalid]="ariaInvalid()"
490
- [attr.aria-required]="ariaRequired()"
491
- [attr.aria-describedby]="ariaDescribedBy()"
338
+ [attr.tabindex]="ngf.tabIndex()"
492
339
  class="form-control"
493
340
  [class.form-control-sm]="p?.size === 'sm'"
494
341
  [class.form-control-lg]="p?.size === 'lg'"
@@ -501,20 +348,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
501
348
  {{ p?.validFeedback | dynamicText | async }}
502
349
  </div>
503
350
  }
504
- @if (errorsToDisplay()[0]; as error) {
505
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
351
+ @if (ngf.errorsToDisplay()[0]; as error) {
352
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
506
353
  } @else if (p?.hint) {
507
- <div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
354
+ <div class="form-text" [id]="ngf.hintId()">{{ p?.hint | dynamicText | async }}</div>
508
355
  }
509
356
  </div>
510
357
  }
511
- `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
512
- '[id]': '`${key()}`',
513
- '[attr.data-testid]': 'key()',
514
- '[class]': 'className()',
515
- '[attr.hidden]': 'field()().hidden() || null',
516
- }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
517
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }] } });
358
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
359
+ }], propDecorators: { minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
518
360
 
519
361
  var bsDatepicker_component = /*#__PURE__*/Object.freeze({
520
362
  __proto__: null,
@@ -546,129 +388,58 @@ const BOOTSTRAP_CONFIG = new InjectionToken('BOOTSTRAP_CONFIG');
546
388
 
547
389
  class BsInputFieldComponent {
548
390
  bootstrapConfig = inject(BOOTSTRAP_CONFIG, { optional: true });
549
- elementRef = inject((ElementRef));
550
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
551
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
552
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
553
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
554
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
555
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
391
+ ngf = injectNgForgeField();
556
392
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
557
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
558
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
559
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
560
- /**
561
- * Reference to the native input element.
562
- * Used to imperatively sync the readonly attribute since Angular Signal Forms'
563
- * [field] directive doesn't sync FieldState.readonly() to the DOM.
564
- */
565
- inputRef = viewChild('inputRef', ...(ngDevMode ? [{ debugName: "inputRef" }] : /* istanbul ignore next */ []));
566
- /**
567
- * Computed signal that extracts the readonly state from the field.
568
- * Used by the effect to reactively sync the readonly attribute to the DOM.
569
- */
570
- isReadonly = computed(() => this.field()().readonly(), ...(ngDevMode ? [{ debugName: "isReadonly" }] : /* istanbul ignore next */ []));
571
- /**
572
- * Workaround: Angular Signal Forms' [field] directive does NOT sync the readonly
573
- * attribute to the DOM. This effect imperatively sets/removes the readonly attribute
574
- * on the native input element whenever the readonly state changes.
575
- *
576
- * Uses afterRenderEffect to ensure DOM is ready before manipulating attributes.
577
- */
578
- syncReadonlyToDom = afterRenderEffect({
579
- write: () => {
580
- const inputRef = this.inputRef();
581
- const isReadonly = this.isReadonly();
582
- if (inputRef?.nativeElement) {
583
- if (isReadonly) {
584
- inputRef.nativeElement.setAttribute('readonly', '');
585
- }
586
- else {
587
- inputRef.nativeElement.removeAttribute('readonly');
588
- }
589
- }
590
- },
591
- });
592
- constructor() {
593
- setupMetaTracking(this.elementRef, this.meta, { selector: 'input' });
594
- }
595
- effectiveSize = computed(() => this.props()?.size ?? this.bootstrapConfig?.size, ...(ngDevMode ? [{ debugName: "effectiveSize" }] : /* istanbul ignore next */ []));
596
- effectiveFloatingLabel = computed(() => this.props()?.floatingLabel ?? this.bootstrapConfig?.floatingLabel ?? false, ...(ngDevMode ? [{ debugName: "effectiveFloatingLabel" }] : /* istanbul ignore next */ []));
597
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
598
- showErrors = shouldShowErrors(this.field);
599
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
600
- // ─────────────────────────────────────────────────────────────────────────────
601
- // Accessibility
602
- // ─────────────────────────────────────────────────────────────────────────────
603
- /** Unique ID for the hint element, used for aria-describedby */
604
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
605
- /** Base ID for error elements, used for aria-describedby */
606
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
607
- /** aria-invalid: true when field is invalid AND touched, false otherwise */
608
- ariaInvalid = computed(() => {
609
- const fieldState = this.field()();
610
- return fieldState.invalid() && fieldState.touched();
611
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
612
- /** aria-required: true if field is required, null otherwise (to remove attribute) */
613
- ariaRequired = computed(() => {
614
- return this.field()().required?.() === true ? true : null;
615
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
616
- /** aria-describedby: links to hint and error messages for screen readers */
617
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
393
+ size = computed(() => this.props()?.size ?? this.bootstrapConfig?.size, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
394
+ floatingLabel = computed(() => this.props()?.floatingLabel ?? this.bootstrapConfig?.floatingLabel ?? false, ...(ngDevMode ? [{ debugName: "floatingLabel" }] : /* istanbul ignore next */ []));
618
395
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
619
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsInputFieldComponent, isStandalone: true, selector: "df-bs-input", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
620
- @let f = field(); @let p = props(); @let inputId = key() + '-input';
621
- @if (effectiveFloatingLabel()) {
396
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsInputFieldComponent, isStandalone: true, selector: "df-bs-input", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
397
+ @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';
398
+ @if (floatingLabel()) {
622
399
  <!-- Floating label variant -->
623
400
  <div class="form-floating mb-3">
624
401
  <input
625
- #inputRef
402
+ ngForgeControl
626
403
  [formField]="f"
627
404
  [id]="inputId"
628
405
  [type]="p?.type ?? 'text'"
629
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
630
- [attr.tabindex]="tabIndex()"
631
- [attr.aria-invalid]="ariaInvalid()"
632
- [attr.aria-required]="ariaRequired()"
633
- [attr.aria-describedby]="ariaDescribedBy()"
406
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
407
+ [attr.tabindex]="ngf.tabIndex()"
634
408
  class="form-control"
635
- [class.form-control-sm]="effectiveSize() === 'sm'"
636
- [class.form-control-lg]="effectiveSize() === 'lg'"
409
+ [class.form-control-sm]="size() === 'sm'"
410
+ [class.form-control-lg]="size() === 'lg'"
637
411
  [class.form-control-plaintext]="p?.plaintext"
638
412
  [class.is-invalid]="f().invalid() && f().touched()"
639
413
  [class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
640
414
  />
641
- @if (label()) {
642
- <label [for]="inputId">{{ label() | dynamicText | async }}</label>
415
+ @if (ngf.label()) {
416
+ <label [for]="inputId">{{ ngf.label() | dynamicText | async }}</label>
643
417
  }
644
418
  @if (p?.validFeedback && f().valid() && f().touched()) {
645
419
  <div class="valid-feedback d-block">
646
420
  {{ p?.validFeedback | dynamicText | async }}
647
421
  </div>
648
422
  }
649
- @if (errorsToDisplay()[0]; as error) {
650
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
423
+ @if (ngf.errorsToDisplay()[0]; as error) {
424
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
651
425
  }
652
426
  </div>
653
427
  } @else {
654
428
  <!-- Standard variant -->
655
429
  <div class="mb-3">
656
- @if (label()) {
657
- <label [for]="inputId" class="form-label">{{ label() | dynamicText | async }}</label>
430
+ @if (ngf.label()) {
431
+ <label [for]="inputId" class="form-label">{{ ngf.label() | dynamicText | async }}</label>
658
432
  }
659
433
  <input
660
- #inputRef
434
+ ngForgeControl
661
435
  [formField]="f"
662
436
  [id]="inputId"
663
437
  [type]="p?.type ?? 'text'"
664
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
665
- [attr.tabindex]="tabIndex()"
666
- [attr.aria-invalid]="ariaInvalid()"
667
- [attr.aria-required]="ariaRequired()"
668
- [attr.aria-describedby]="ariaDescribedBy()"
438
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
439
+ [attr.tabindex]="ngf.tabIndex()"
669
440
  class="form-control"
670
- [class.form-control-sm]="effectiveSize() === 'sm'"
671
- [class.form-control-lg]="effectiveSize() === 'lg'"
441
+ [class.form-control-sm]="size() === 'sm'"
442
+ [class.form-control-lg]="size() === 'lg'"
672
443
  [class.form-control-plaintext]="p?.plaintext"
673
444
  [class.is-invalid]="f().invalid() && f().touched()"
674
445
  [class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
@@ -678,70 +449,64 @@ class BsInputFieldComponent {
678
449
  {{ p?.validFeedback | dynamicText | async }}
679
450
  </div>
680
451
  }
681
- @if (errorsToDisplay()[0]; as error) {
682
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
452
+ @if (ngf.errorsToDisplay()[0]; as error) {
453
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
683
454
  } @else if (p?.hint) {
684
- <div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
455
+ <div class="form-text" [id]="ngf.hintId()">{{ p?.hint | dynamicText | async }}</div>
685
456
  }
686
457
  </div>
687
458
  }
688
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
459
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
689
460
  }
690
461
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsInputFieldComponent, decorators: [{
691
462
  type: Component,
692
- args: [{ selector: 'df-bs-input', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
693
- @let f = field(); @let p = props(); @let inputId = key() + '-input';
694
- @if (effectiveFloatingLabel()) {
463
+ args: [{ selector: 'df-bs-input', imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
464
+ @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';
465
+ @if (floatingLabel()) {
695
466
  <!-- Floating label variant -->
696
467
  <div class="form-floating mb-3">
697
468
  <input
698
- #inputRef
469
+ ngForgeControl
699
470
  [formField]="f"
700
471
  [id]="inputId"
701
472
  [type]="p?.type ?? 'text'"
702
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
703
- [attr.tabindex]="tabIndex()"
704
- [attr.aria-invalid]="ariaInvalid()"
705
- [attr.aria-required]="ariaRequired()"
706
- [attr.aria-describedby]="ariaDescribedBy()"
473
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
474
+ [attr.tabindex]="ngf.tabIndex()"
707
475
  class="form-control"
708
- [class.form-control-sm]="effectiveSize() === 'sm'"
709
- [class.form-control-lg]="effectiveSize() === 'lg'"
476
+ [class.form-control-sm]="size() === 'sm'"
477
+ [class.form-control-lg]="size() === 'lg'"
710
478
  [class.form-control-plaintext]="p?.plaintext"
711
479
  [class.is-invalid]="f().invalid() && f().touched()"
712
480
  [class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
713
481
  />
714
- @if (label()) {
715
- <label [for]="inputId">{{ label() | dynamicText | async }}</label>
482
+ @if (ngf.label()) {
483
+ <label [for]="inputId">{{ ngf.label() | dynamicText | async }}</label>
716
484
  }
717
485
  @if (p?.validFeedback && f().valid() && f().touched()) {
718
486
  <div class="valid-feedback d-block">
719
487
  {{ p?.validFeedback | dynamicText | async }}
720
488
  </div>
721
489
  }
722
- @if (errorsToDisplay()[0]; as error) {
723
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
490
+ @if (ngf.errorsToDisplay()[0]; as error) {
491
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
724
492
  }
725
493
  </div>
726
494
  } @else {
727
495
  <!-- Standard variant -->
728
496
  <div class="mb-3">
729
- @if (label()) {
730
- <label [for]="inputId" class="form-label">{{ label() | dynamicText | async }}</label>
497
+ @if (ngf.label()) {
498
+ <label [for]="inputId" class="form-label">{{ ngf.label() | dynamicText | async }}</label>
731
499
  }
732
500
  <input
733
- #inputRef
501
+ ngForgeControl
734
502
  [formField]="f"
735
503
  [id]="inputId"
736
504
  [type]="p?.type ?? 'text'"
737
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
738
- [attr.tabindex]="tabIndex()"
739
- [attr.aria-invalid]="ariaInvalid()"
740
- [attr.aria-required]="ariaRequired()"
741
- [attr.aria-describedby]="ariaDescribedBy()"
505
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
506
+ [attr.tabindex]="ngf.tabIndex()"
742
507
  class="form-control"
743
- [class.form-control-sm]="effectiveSize() === 'sm'"
744
- [class.form-control-lg]="effectiveSize() === 'lg'"
508
+ [class.form-control-sm]="size() === 'sm'"
509
+ [class.form-control-lg]="size() === 'lg'"
745
510
  [class.form-control-plaintext]="p?.plaintext"
746
511
  [class.is-invalid]="f().invalid() && f().touched()"
747
512
  [class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
@@ -751,20 +516,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
751
516
  {{ p?.validFeedback | dynamicText | async }}
752
517
  </div>
753
518
  }
754
- @if (errorsToDisplay()[0]; as error) {
755
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
519
+ @if (ngf.errorsToDisplay()[0]; as error) {
520
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
756
521
  } @else if (p?.hint) {
757
- <div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
522
+ <div class="form-text" [id]="ngf.hintId()">{{ p?.hint | dynamicText | async }}</div>
758
523
  }
759
524
  </div>
760
525
  }
761
- `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
762
- '[id]': '`${key()}`',
763
- '[attr.data-testid]': 'key()',
764
- '[class]': 'className()',
765
- '[attr.hidden]': 'field()().hidden() || null',
766
- }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
767
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], inputRef: [{ type: i0.ViewChild, args: ['inputRef', { isSignal: true }] }] } });
526
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
527
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
768
528
 
769
529
  var bsInput_component = /*#__PURE__*/Object.freeze({
770
530
  __proto__: null,
@@ -772,21 +532,9 @@ var bsInput_component = /*#__PURE__*/Object.freeze({
772
532
  });
773
533
 
774
534
  class BsMultiCheckboxFieldComponent {
775
- elementRef = inject((ElementRef));
776
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
777
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
778
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
779
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
780
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
781
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
535
+ ngf = injectNgForgeField();
782
536
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
783
537
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
784
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
785
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
786
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
787
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
788
- showErrors = shouldShowErrors(this.field);
789
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
790
538
  /** Computed map of checked option values for O(1) lookup in template */
791
539
  checkedValuesMap = computed(() => {
792
540
  const map = {};
@@ -796,15 +544,14 @@ class BsMultiCheckboxFieldComponent {
796
544
  return map;
797
545
  }, ...(ngDevMode ? [{ debugName: "checkedValuesMap" }] : /* istanbul ignore next */ []));
798
546
  valueViewModel = linkedSignal(() => {
799
- const currentValues = this.field()().value();
547
+ const currentValues = this.ngf.field()().value();
800
548
  return this.options().filter((option) => currentValues.includes(option.value));
801
549
  }, { ...(ngDevMode ? { debugName: "valueViewModel" } : /* istanbul ignore next */ {}), equal: isEqual });
802
550
  constructor() {
803
- setupMetaTracking(this.elementRef, this.meta, { selector: 'input[type="checkbox"]', dependents: [this.options] });
804
551
  explicitEffect([this.valueViewModel], ([selectedOptions]) => {
805
552
  const selectedValues = selectedOptions.map((option) => option.value);
806
- if (!isEqual(selectedValues, this.field()().value())) {
807
- this.field()().value.set(selectedValues);
553
+ if (!isEqual(selectedValues, this.ngf.field()().value())) {
554
+ this.ngf.field()().value.set(selectedValues);
808
555
  }
809
556
  });
810
557
  explicitEffect([this.options], ([options]) => {
@@ -829,24 +576,11 @@ class BsMultiCheckboxFieldComponent {
829
576
  }
830
577
  });
831
578
  }
832
- // ─────────────────────────────────────────────────────────────────────────────
833
- // Accessibility
834
- // ─────────────────────────────────────────────────────────────────────────────
835
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
836
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
837
- ariaInvalid = computed(() => {
838
- const fieldState = this.field()();
839
- return fieldState.invalid() && fieldState.touched();
840
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
841
- ariaRequired = computed(() => {
842
- return this.field()().required?.() === true ? true : null;
843
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
844
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
845
579
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
846
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsMultiCheckboxFieldComponent, isStandalone: true, selector: "df-bs-multi-checkbox", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className() || \"\"", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
847
- @let f = field();
580
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsMultiCheckboxFieldComponent, isStandalone: true, selector: "df-bs-multi-checkbox", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
581
+ @let f = ngf.field();
848
582
  @let checked = checkedValuesMap();
849
- @if (label(); as label) {
583
+ @if (ngf.label(); as label) {
850
584
  <div class="form-label">{{ label | dynamicText | async }}</div>
851
585
  }
852
586
 
@@ -859,38 +593,36 @@ class BsMultiCheckboxFieldComponent {
859
593
  [class.form-check-reverse]="props()?.reverse"
860
594
  >
861
595
  <input
596
+ ngForgeControl
862
597
  type="checkbox"
863
- [id]="key() + '_' + i"
598
+ [id]="ngf.key() + '_' + i"
864
599
  [checked]="checked['' + option.value]"
865
600
  [disabled]="f().disabled() || option.disabled"
866
601
  (change)="onCheckboxChange(option, $event)"
867
602
  class="form-check-input"
868
603
  [class.is-invalid]="f().invalid() && f().touched()"
869
- [attr.tabindex]="tabIndex()"
870
- [attr.aria-invalid]="ariaInvalid()"
871
- [attr.aria-required]="ariaRequired()"
872
- [attr.aria-describedby]="ariaDescribedBy()"
604
+ [attr.tabindex]="ngf.tabIndex()"
873
605
  />
874
- <label [for]="key() + '_' + i" class="form-check-label">
606
+ <label [for]="ngf.key() + '_' + i" class="form-check-label">
875
607
  {{ option.label | dynamicText | async }}
876
608
  </label>
877
609
  </div>
878
610
  }
879
611
  </div>
880
612
 
881
- @if (errorsToDisplay()[0]; as error) {
882
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
613
+ @if (ngf.errorsToDisplay()[0]; as error) {
614
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
883
615
  } @else if (props()?.hint; as hint) {
884
- <div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
616
+ <div class="form-text" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</div>
885
617
  }
886
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}.checkbox-group{margin-bottom:.5rem}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
618
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}.checkbox-group{margin-bottom:.5rem}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
887
619
  }
888
620
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsMultiCheckboxFieldComponent, decorators: [{
889
621
  type: Component,
890
- args: [{ selector: 'df-bs-multi-checkbox', imports: [DynamicTextPipe, AsyncPipe], template: `
891
- @let f = field();
622
+ args: [{ selector: 'df-bs-multi-checkbox', imports: [DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
623
+ @let f = ngf.field();
892
624
  @let checked = checkedValuesMap();
893
- @if (label(); as label) {
625
+ @if (ngf.label(); as label) {
894
626
  <div class="form-label">{{ label | dynamicText | async }}</div>
895
627
  }
896
628
 
@@ -903,45 +635,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
903
635
  [class.form-check-reverse]="props()?.reverse"
904
636
  >
905
637
  <input
638
+ ngForgeControl
906
639
  type="checkbox"
907
- [id]="key() + '_' + i"
640
+ [id]="ngf.key() + '_' + i"
908
641
  [checked]="checked['' + option.value]"
909
642
  [disabled]="f().disabled() || option.disabled"
910
643
  (change)="onCheckboxChange(option, $event)"
911
644
  class="form-check-input"
912
645
  [class.is-invalid]="f().invalid() && f().touched()"
913
- [attr.tabindex]="tabIndex()"
914
- [attr.aria-invalid]="ariaInvalid()"
915
- [attr.aria-required]="ariaRequired()"
916
- [attr.aria-describedby]="ariaDescribedBy()"
646
+ [attr.tabindex]="ngf.tabIndex()"
917
647
  />
918
- <label [for]="key() + '_' + i" class="form-check-label">
648
+ <label [for]="ngf.key() + '_' + i" class="form-check-label">
919
649
  {{ option.label | dynamicText | async }}
920
650
  </label>
921
651
  </div>
922
652
  }
923
653
  </div>
924
654
 
925
- @if (errorsToDisplay()[0]; as error) {
926
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
655
+ @if (ngf.errorsToDisplay()[0]; as error) {
656
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
927
657
  } @else if (props()?.hint; as hint) {
928
- <div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
658
+ <div class="form-text" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</div>
929
659
  }
930
- `, host: {
931
- '[class]': 'className() || ""',
932
- '[id]': '`${key()}`',
933
- '[attr.data-testid]': 'key()',
934
- '[attr.hidden]': 'field()().hidden() || null',
935
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}.checkbox-group{margin-bottom:.5rem}:host([hidden]){display:none!important}\n"] }]
936
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }] } });
660
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}.checkbox-group{margin-bottom:.5rem}:host([hidden]){display:none!important}\n"] }]
661
+ }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
937
662
 
938
663
  var bsMultiCheckbox_component = /*#__PURE__*/Object.freeze({
939
664
  __proto__: null,
940
665
  default: BsMultiCheckboxFieldComponent
941
666
  });
942
667
 
668
+ /**
669
+ * Bootstrap radio group implementing FormValueControl. Rendered inside
670
+ * `df-bs-radio` — each `<input type="radio">` carries `ngForgeControl`, so
671
+ * the marker absorbs meta + aria from the ambient parent NgForgeField.
672
+ */
943
673
  class BsRadioGroupComponent {
944
- elementRef = inject((ElementRef));
945
674
  // Value model - FormField directive binds form value to this
946
675
  value = model(undefined, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
947
676
  // Optional FormValueControl properties - Field directive will bind these
@@ -952,12 +681,6 @@ class BsRadioGroupComponent {
952
681
  label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
953
682
  options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
954
683
  properties = input(...(ngDevMode ? [undefined, { debugName: "properties" }] : /* istanbul ignore next */ []));
955
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
956
- // Accessibility - this will be provided by parent component through input
957
- ariaDescribedBy = input(null, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []));
958
- constructor() {
959
- setupMetaTracking(this.elementRef, this.meta, { selector: 'input[type="radio"]', dependents: [this.options] });
960
- }
961
684
  /**
962
685
  * Handle radio button change event
963
686
  */
@@ -967,19 +690,19 @@ class BsRadioGroupComponent {
967
690
  }
968
691
  }
969
692
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsRadioGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
970
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsRadioGroupComponent, isStandalone: true, selector: "df-bs-radio-group", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, properties: { classPropertyName: "properties", publicName: "properties", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: `
693
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsRadioGroupComponent, isStandalone: true, selector: "df-bs-radio-group", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, properties: { classPropertyName: "properties", publicName: "properties", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: `
971
694
  @let props = properties();
972
695
  @if (props?.buttonGroup) {
973
696
  <div class="btn-group" role="group" [attr.aria-label]="label() | dynamicText | async">
974
697
  @for (option of options(); track option.value; let i = $index) {
975
698
  <input
699
+ ngForgeControl
976
700
  type="radio"
977
701
  [name]="name()"
978
702
  [value]="option.value"
979
703
  [checked]="value() === option.value"
980
704
  (change)="onRadioChange(option.value)"
981
705
  [disabled]="disabled() || option.disabled || false"
982
- [attr.aria-describedby]="ariaDescribedBy()"
983
706
  class="btn-check"
984
707
  [id]="name() + '_' + i"
985
708
  autocomplete="off"
@@ -998,13 +721,13 @@ class BsRadioGroupComponent {
998
721
  @for (option of options(); track option.value; let i = $index) {
999
722
  <div class="form-check" [class.form-check-inline]="props?.inline" [class.form-check-reverse]="props?.reverse">
1000
723
  <input
724
+ ngForgeControl
1001
725
  type="radio"
1002
726
  [name]="name()"
1003
727
  [value]="option.value"
1004
728
  [checked]="value() === option.value"
1005
729
  (change)="onRadioChange(option.value)"
1006
730
  [disabled]="disabled() || option.disabled || false"
1007
- [attr.aria-describedby]="ariaDescribedBy()"
1008
731
  class="form-check-input"
1009
732
  [id]="name() + '_' + i"
1010
733
  />
@@ -1014,23 +737,23 @@ class BsRadioGroupComponent {
1014
737
  </div>
1015
738
  }
1016
739
  }
1017
- `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
740
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1018
741
  }
1019
742
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsRadioGroupComponent, decorators: [{
1020
743
  type: Component,
1021
- args: [{ selector: 'df-bs-radio-group', imports: [DynamicTextPipe, AsyncPipe], template: `
744
+ args: [{ selector: 'df-bs-radio-group', imports: [DynamicTextPipe, AsyncPipe, NgForgeControl], template: `
1022
745
  @let props = properties();
1023
746
  @if (props?.buttonGroup) {
1024
747
  <div class="btn-group" role="group" [attr.aria-label]="label() | dynamicText | async">
1025
748
  @for (option of options(); track option.value; let i = $index) {
1026
749
  <input
750
+ ngForgeControl
1027
751
  type="radio"
1028
752
  [name]="name()"
1029
753
  [value]="option.value"
1030
754
  [checked]="value() === option.value"
1031
755
  (change)="onRadioChange(option.value)"
1032
756
  [disabled]="disabled() || option.disabled || false"
1033
- [attr.aria-describedby]="ariaDescribedBy()"
1034
757
  class="btn-check"
1035
758
  [id]="name() + '_' + i"
1036
759
  autocomplete="off"
@@ -1049,13 +772,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1049
772
  @for (option of options(); track option.value; let i = $index) {
1050
773
  <div class="form-check" [class.form-check-inline]="props?.inline" [class.form-check-reverse]="props?.reverse">
1051
774
  <input
775
+ ngForgeControl
1052
776
  type="radio"
1053
777
  [name]="name()"
1054
778
  [value]="option.value"
1055
779
  [checked]="value() === option.value"
1056
780
  (change)="onRadioChange(option.value)"
1057
781
  [disabled]="disabled() || option.disabled || false"
1058
- [attr.aria-describedby]="ariaDescribedBy()"
1059
782
  class="form-check-input"
1060
783
  [id]="name() + '_' + i"
1061
784
  />
@@ -1066,99 +789,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1066
789
  }
1067
790
  }
1068
791
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
1069
- }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], properties: [{ type: i0.Input, args: [{ isSignal: true, alias: "properties", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }] } });
792
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], properties: [{ type: i0.Input, args: [{ isSignal: true, alias: "properties", required: false }] }] } });
1070
793
 
1071
794
  class BsRadioFieldComponent {
1072
- elementRef = inject((ElementRef));
1073
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
1074
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
1075
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
1076
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
1077
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
1078
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
795
+ ngf = injectNgForgeField();
1079
796
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
1080
797
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
1081
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
1082
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
1083
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
1084
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
1085
- showErrors = shouldShowErrors(this.field);
1086
- constructor() {
1087
- setupMetaTracking(this.elementRef, this.meta, {
1088
- selector: 'input[type="radio"]',
1089
- dependents: [this.options],
1090
- });
1091
- }
1092
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
1093
- // ─────────────────────────────────────────────────────────────────────────────
1094
- // Accessibility
1095
- // ─────────────────────────────────────────────────────────────────────────────
1096
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
1097
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
1098
- ariaInvalid = computed(() => {
1099
- const fieldState = this.field()();
1100
- return fieldState.invalid() && fieldState.touched();
1101
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
1102
- ariaRequired = computed(() => {
1103
- return this.field()().required?.() === true ? true : null;
1104
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
1105
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
1106
798
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1107
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsRadioFieldComponent, isStandalone: true, selector: "df-bs-radio", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
1108
- @let f = field();
799
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsRadioFieldComponent, isStandalone: true, selector: "df-bs-radio", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
800
+ @let f = ngf.field();
1109
801
 
1110
802
  <div class="mb-3">
1111
- @if (label(); as label) {
803
+ @if (ngf.label(); as label) {
1112
804
  <div class="form-label">{{ label | dynamicText | async }}</div>
1113
805
  }
1114
806
 
1115
- <df-bs-radio-group
1116
- [formField]="f"
1117
- [label]="label()"
1118
- [options]="options()"
1119
- [properties]="props()"
1120
- [ariaDescribedBy]="ariaDescribedBy()"
1121
- />
807
+ <df-bs-radio-group [formField]="f" [label]="ngf.label()" [options]="options()" [properties]="props()" />
1122
808
 
1123
- @if (errorsToDisplay()[0]; as error) {
1124
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
809
+ @if (ngf.errorsToDisplay()[0]; as error) {
810
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1125
811
  } @else if (props()?.hint; as hint) {
1126
- <div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
812
+ <div class="form-text" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</div>
1127
813
  }
1128
814
  </div>
1129
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: BsRadioGroupComponent, selector: "df-bs-radio-group", inputs: ["value", "disabled", "readonly", "name", "label", "options", "properties", "meta", "ariaDescribedBy"], outputs: ["valueChange"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
815
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: BsRadioGroupComponent, selector: "df-bs-radio-group", inputs: ["value", "disabled", "readonly", "name", "label", "options", "properties"], outputs: ["valueChange"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1130
816
  }
1131
817
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsRadioFieldComponent, decorators: [{
1132
818
  type: Component,
1133
- args: [{ selector: 'df-bs-radio', imports: [BsRadioGroupComponent, FormField, DynamicTextPipe, AsyncPipe], template: `
1134
- @let f = field();
819
+ args: [{ selector: 'df-bs-radio', imports: [BsRadioGroupComponent, FormField, DynamicTextPipe, AsyncPipe], hostDirectives: [NgForgeFieldHost], template: `
820
+ @let f = ngf.field();
1135
821
 
1136
822
  <div class="mb-3">
1137
- @if (label(); as label) {
823
+ @if (ngf.label(); as label) {
1138
824
  <div class="form-label">{{ label | dynamicText | async }}</div>
1139
825
  }
1140
826
 
1141
- <df-bs-radio-group
1142
- [formField]="f"
1143
- [label]="label()"
1144
- [options]="options()"
1145
- [properties]="props()"
1146
- [ariaDescribedBy]="ariaDescribedBy()"
1147
- />
827
+ <df-bs-radio-group [formField]="f" [label]="ngf.label()" [options]="options()" [properties]="props()" />
1148
828
 
1149
- @if (errorsToDisplay()[0]; as error) {
1150
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
829
+ @if (ngf.errorsToDisplay()[0]; as error) {
830
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1151
831
  } @else if (props()?.hint; as hint) {
1152
- <div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
832
+ <div class="form-text" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</div>
1153
833
  }
1154
834
  </div>
1155
- `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1156
- '[id]': '`${key()}`',
1157
- '[attr.data-testid]': 'key()',
1158
- '[class]': 'className()',
1159
- '[attr.hidden]': 'field()().hidden() || null',
1160
- }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
1161
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
835
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
836
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
1162
837
 
1163
838
  var bsRadio_component = /*#__PURE__*/Object.freeze({
1164
839
  __proto__: null,
@@ -1166,24 +841,9 @@ var bsRadio_component = /*#__PURE__*/Object.freeze({
1166
841
  });
1167
842
 
1168
843
  class BsSelectFieldComponent {
1169
- elementRef = inject((ElementRef));
1170
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
1171
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
1172
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
1173
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
1174
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
1175
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
844
+ ngf = injectNgForgeField();
1176
845
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
1177
846
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
1178
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
1179
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
1180
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
1181
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
1182
- showErrors = shouldShowErrors(this.field);
1183
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
1184
- constructor() {
1185
- setupMetaTracking(this.elementRef, this.meta, { selector: 'select' });
1186
- }
1187
847
  defaultCompare = Object.is;
1188
848
  isSelected(optionValue, fieldValue) {
1189
849
  const compareWith = this.props()?.compareWith || this.defaultCompare;
@@ -1192,41 +852,27 @@ class BsSelectFieldComponent {
1192
852
  }
1193
853
  return fieldValue !== null && compareWith(fieldValue, optionValue);
1194
854
  }
1195
- // ─────────────────────────────────────────────────────────────────────────────
1196
- // Accessibility
1197
- // ─────────────────────────────────────────────────────────────────────────────
1198
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
1199
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
1200
- ariaInvalid = computed(() => {
1201
- const fieldState = this.field()();
1202
- return fieldState.invalid() && fieldState.touched();
1203
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
1204
- ariaRequired = computed(() => {
1205
- return this.field()().required?.() === true ? true : null;
1206
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
1207
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
1208
855
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1209
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsSelectFieldComponent, isStandalone: true, selector: "df-bs-select", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
1210
- @let f = field(); @let selectId = key() + '-select';
856
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsSelectFieldComponent, isStandalone: true, selector: "df-bs-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
857
+ @let f = ngf.field(); @let selectId = ngf.key() + '-select';
1211
858
 
1212
859
  <div class="mb-3">
1213
- @if (label(); as label) {
860
+ @if (ngf.label(); as label) {
1214
861
  <label [for]="selectId" class="form-label">{{ label | dynamicText | async }}</label>
1215
862
  }
1216
863
  <select
864
+ ngForgeControl
1217
865
  [formField]="f"
1218
866
  [id]="selectId"
867
+ [attr.tabindex]="ngf.tabIndex()"
1219
868
  class="form-select"
1220
869
  [class.form-select-sm]="props()?.size === 'sm'"
1221
870
  [class.form-select-lg]="props()?.size === 'lg'"
1222
871
  [class.is-invalid]="f().invalid() && f().touched()"
1223
872
  [multiple]="props()?.multiple || false"
1224
873
  [size]="props()?.htmlSize"
1225
- [attr.aria-invalid]="ariaInvalid()"
1226
- [attr.aria-required]="ariaRequired()"
1227
- [attr.aria-describedby]="ariaDescribedBy()"
1228
874
  >
1229
- @if (placeholder(); as placeholder) {
875
+ @if (ngf.placeholder(); as placeholder) {
1230
876
  <option value="" disabled [selected]="!f().value()">{{ placeholder | dynamicText | async }}</option>
1231
877
  }
1232
878
  @for (option of options(); track option.value) {
@@ -1236,37 +882,36 @@ class BsSelectFieldComponent {
1236
882
  }
1237
883
  </select>
1238
884
 
1239
- @if (errorsToDisplay()[0]; as error) {
1240
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
885
+ @if (ngf.errorsToDisplay()[0]; as error) {
886
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1241
887
  } @else if (props()?.hint; as hint) {
1242
- <div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
888
+ <div class="form-text" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</div>
1243
889
  }
1244
890
  </div>
1245
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
891
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1246
892
  }
1247
893
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsSelectFieldComponent, decorators: [{
1248
894
  type: Component,
1249
- args: [{ selector: 'df-bs-select', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
1250
- @let f = field(); @let selectId = key() + '-select';
895
+ args: [{ selector: 'df-bs-select', imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
896
+ @let f = ngf.field(); @let selectId = ngf.key() + '-select';
1251
897
 
1252
898
  <div class="mb-3">
1253
- @if (label(); as label) {
899
+ @if (ngf.label(); as label) {
1254
900
  <label [for]="selectId" class="form-label">{{ label | dynamicText | async }}</label>
1255
901
  }
1256
902
  <select
903
+ ngForgeControl
1257
904
  [formField]="f"
1258
905
  [id]="selectId"
906
+ [attr.tabindex]="ngf.tabIndex()"
1259
907
  class="form-select"
1260
908
  [class.form-select-sm]="props()?.size === 'sm'"
1261
909
  [class.form-select-lg]="props()?.size === 'lg'"
1262
910
  [class.is-invalid]="f().invalid() && f().touched()"
1263
911
  [multiple]="props()?.multiple || false"
1264
912
  [size]="props()?.htmlSize"
1265
- [attr.aria-invalid]="ariaInvalid()"
1266
- [attr.aria-required]="ariaRequired()"
1267
- [attr.aria-describedby]="ariaDescribedBy()"
1268
913
  >
1269
- @if (placeholder(); as placeholder) {
914
+ @if (ngf.placeholder(); as placeholder) {
1270
915
  <option value="" disabled [selected]="!f().value()">{{ placeholder | dynamicText | async }}</option>
1271
916
  }
1272
917
  @for (option of options(); track option.value) {
@@ -1276,19 +921,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1276
921
  }
1277
922
  </select>
1278
923
 
1279
- @if (errorsToDisplay()[0]; as error) {
1280
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
924
+ @if (ngf.errorsToDisplay()[0]; as error) {
925
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1281
926
  } @else if (props()?.hint; as hint) {
1282
- <div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
927
+ <div class="form-text" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</div>
1283
928
  }
1284
929
  </div>
1285
- `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1286
- '[id]': '`${key()}`',
1287
- '[attr.data-testid]': 'key()',
1288
- '[class]': 'className()',
1289
- '[attr.hidden]': 'field()().hidden() || null',
1290
- }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
1291
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }] } });
930
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
931
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
1292
932
 
1293
933
  var bsSelect_component = /*#__PURE__*/Object.freeze({
1294
934
  __proto__: null,
@@ -1296,45 +936,17 @@ var bsSelect_component = /*#__PURE__*/Object.freeze({
1296
936
  });
1297
937
 
1298
938
  class BsSliderFieldComponent {
1299
- elementRef = inject((ElementRef));
1300
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
1301
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
1302
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
1303
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
1304
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
1305
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
939
+ ngf = injectNgForgeField();
1306
940
  min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
1307
941
  max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
1308
942
  step = input(...(ngDevMode ? [undefined, { debugName: "step" }] : /* istanbul ignore next */ []));
1309
943
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
1310
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
1311
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
1312
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
1313
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
1314
- showErrors = shouldShowErrors(this.field);
1315
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
1316
- constructor() {
1317
- setupMetaTracking(this.elementRef, this.meta, { selector: 'input' });
1318
- }
1319
- // ─────────────────────────────────────────────────────────────────────────────
1320
- // Accessibility
1321
- // ─────────────────────────────────────────────────────────────────────────────
1322
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
1323
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
1324
- ariaInvalid = computed(() => {
1325
- const fieldState = this.field()();
1326
- return fieldState.invalid() && fieldState.touched();
1327
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
1328
- ariaRequired = computed(() => {
1329
- return this.field()().required?.() === true ? true : null;
1330
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
1331
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
1332
944
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1333
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsSliderFieldComponent, isStandalone: true, selector: "df-bs-slider", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
1334
- @let f = field(); @let inputId = key() + '-input';
945
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsSliderFieldComponent, isStandalone: true, selector: "df-bs-slider", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
946
+ @let f = ngf.field(); @let inputId = ngf.key() + '-input';
1335
947
 
1336
948
  <div class="mb-3">
1337
- @if (label(); as label) {
949
+ @if (ngf.label(); as label) {
1338
950
  <label [for]="inputId" class="form-label">
1339
951
  {{ label | dynamicText | async }}
1340
952
  @if (props()?.showValue) {
@@ -1344,6 +956,7 @@ class BsSliderFieldComponent {
1344
956
  }
1345
957
 
1346
958
  <input
959
+ ngForgeControl
1347
960
  type="range"
1348
961
  dfBsInputConstraints
1349
962
  [formField]="f"
@@ -1351,28 +964,25 @@ class BsSliderFieldComponent {
1351
964
  [dfMin]="f().min?.() ?? props()?.min ?? min()"
1352
965
  [dfMax]="f().max?.() ?? props()?.max ?? max()"
1353
966
  [dfStep]="step() ?? props()?.step ?? 1"
1354
- [attr.tabindex]="tabIndex()"
1355
- [attr.aria-invalid]="ariaInvalid()"
1356
- [attr.aria-required]="ariaRequired()"
1357
- [attr.aria-describedby]="ariaDescribedBy()"
967
+ [attr.tabindex]="ngf.tabIndex()"
1358
968
  class="form-range"
1359
969
  />
1360
970
 
1361
- @if (errorsToDisplay()[0]; as error) {
1362
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
971
+ @if (ngf.errorsToDisplay()[0]; as error) {
972
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1363
973
  } @else if (props()?.hint; as hint) {
1364
- <div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
974
+ <div class="form-text" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</div>
1365
975
  }
1366
976
  </div>
1367
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: InputConstraintsDirective, selector: "[dfBsInputConstraints]", inputs: ["dfMin", "dfMax", "dfStep"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
977
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: InputConstraintsDirective, selector: "[dfBsInputConstraints]", inputs: ["dfMin", "dfMax", "dfStep"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1368
978
  }
1369
979
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsSliderFieldComponent, decorators: [{
1370
980
  type: Component,
1371
- args: [{ selector: 'df-bs-slider', imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective], template: `
1372
- @let f = field(); @let inputId = key() + '-input';
981
+ args: [{ selector: 'df-bs-slider', imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
982
+ @let f = ngf.field(); @let inputId = ngf.key() + '-input';
1373
983
 
1374
984
  <div class="mb-3">
1375
- @if (label(); as label) {
985
+ @if (ngf.label(); as label) {
1376
986
  <label [for]="inputId" class="form-label">
1377
987
  {{ label | dynamicText | async }}
1378
988
  @if (props()?.showValue) {
@@ -1382,6 +992,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1382
992
  }
1383
993
 
1384
994
  <input
995
+ ngForgeControl
1385
996
  type="range"
1386
997
  dfBsInputConstraints
1387
998
  [formField]="f"
@@ -1389,26 +1000,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1389
1000
  [dfMin]="f().min?.() ?? props()?.min ?? min()"
1390
1001
  [dfMax]="f().max?.() ?? props()?.max ?? max()"
1391
1002
  [dfStep]="step() ?? props()?.step ?? 1"
1392
- [attr.tabindex]="tabIndex()"
1393
- [attr.aria-invalid]="ariaInvalid()"
1394
- [attr.aria-required]="ariaRequired()"
1395
- [attr.aria-describedby]="ariaDescribedBy()"
1003
+ [attr.tabindex]="ngf.tabIndex()"
1396
1004
  class="form-range"
1397
1005
  />
1398
1006
 
1399
- @if (errorsToDisplay()[0]; as error) {
1400
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
1007
+ @if (ngf.errorsToDisplay()[0]; as error) {
1008
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1401
1009
  } @else if (props()?.hint; as hint) {
1402
- <div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
1010
+ <div class="form-text" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</div>
1403
1011
  }
1404
1012
  </div>
1405
- `, host: {
1406
- '[class]': 'className()',
1407
- '[id]': '`${key()}`',
1408
- '[attr.data-testid]': 'key()',
1409
- '[attr.hidden]': 'field()().hidden() || null',
1410
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
1411
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }] } });
1013
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
1014
+ }], propDecorators: { min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
1412
1015
 
1413
1016
  var bsSlider_component = /*#__PURE__*/Object.freeze({
1414
1017
  __proto__: null,
@@ -1416,17 +1019,8 @@ var bsSlider_component = /*#__PURE__*/Object.freeze({
1416
1019
  });
1417
1020
 
1418
1021
  class BsTextareaFieldComponent {
1419
- elementRef = inject((ElementRef));
1420
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
1421
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
1422
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
1423
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
1424
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
1425
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
1022
+ ngf = injectNgForgeField();
1426
1023
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
1427
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
1428
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
1429
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
1430
1024
  /**
1431
1025
  * Reference to the native textarea element.
1432
1026
  * Used to imperatively sync the readonly attribute since Angular Signal Forms'
@@ -1436,7 +1030,7 @@ class BsTextareaFieldComponent {
1436
1030
  /**
1437
1031
  * Computed signal that extracts the readonly state from the field.
1438
1032
  */
1439
- isReadonly = computed(() => this.field()().readonly(), ...(ngDevMode ? [{ debugName: "isReadonly" }] : /* istanbul ignore next */ []));
1033
+ isReadonly = computed(() => this.ngf.field()().readonly(), ...(ngDevMode ? [{ debugName: "isReadonly" }] : /* istanbul ignore next */ []));
1440
1034
  /**
1441
1035
  * Workaround: Angular Signal Forms' [field] directive does NOT sync the readonly
1442
1036
  * attribute to the DOM. This effect imperatively sets/removes the readonly attribute
@@ -1456,40 +1050,19 @@ class BsTextareaFieldComponent {
1456
1050
  }
1457
1051
  },
1458
1052
  });
1459
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
1460
- showErrors = shouldShowErrors(this.field);
1461
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
1462
- constructor() {
1463
- setupMetaTracking(this.elementRef, this.meta, { selector: 'textarea' });
1464
- }
1465
- // ─────────────────────────────────────────────────────────────────────────────
1466
- // Accessibility
1467
- // ─────────────────────────────────────────────────────────────────────────────
1468
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
1469
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
1470
- ariaInvalid = computed(() => {
1471
- const fieldState = this.field()();
1472
- return fieldState.invalid() && fieldState.touched();
1473
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
1474
- ariaRequired = computed(() => {
1475
- return this.field()().required?.() === true ? true : null;
1476
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
1477
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
1478
1053
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1479
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsTextareaFieldComponent, isStandalone: true, selector: "df-bs-textarea", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "class": "className()", "attr.hidden": "field()().hidden() || null" } }, viewQueries: [{ propertyName: "textareaRef", first: true, predicate: ["textareaRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
1480
- @let f = field(); @let p = props(); @let textareaId = key() + '-textarea';
1054
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsTextareaFieldComponent, isStandalone: true, selector: "df-bs-textarea", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "textareaRef", first: true, predicate: ["textareaRef"], descendants: true, isSignal: true }], hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
1055
+ @let f = ngf.field(); @let p = props(); @let textareaId = ngf.key() + '-textarea';
1481
1056
  @if (p?.floatingLabel) {
1482
1057
  <!-- Floating label variant -->
1483
1058
  <div class="form-floating mb-3">
1484
1059
  <textarea
1060
+ ngForgeControl
1485
1061
  #textareaRef
1486
1062
  [formField]="f"
1487
1063
  [id]="textareaId"
1488
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
1489
- [attr.tabindex]="tabIndex()"
1490
- [attr.aria-invalid]="ariaInvalid()"
1491
- [attr.aria-required]="ariaRequired()"
1492
- [attr.aria-describedby]="ariaDescribedBy()"
1064
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
1065
+ [attr.tabindex]="ngf.tabIndex()"
1493
1066
  class="form-control"
1494
1067
  [class.form-control-sm]="p?.size === 'sm'"
1495
1068
  [class.form-control-lg]="p?.size === 'lg'"
@@ -1497,36 +1070,34 @@ class BsTextareaFieldComponent {
1497
1070
  [class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
1498
1071
  ></textarea>
1499
1072
 
1500
- @if (label()) {
1501
- <label [for]="textareaId">{{ label() | dynamicText | async }}</label>
1073
+ @if (ngf.label()) {
1074
+ <label [for]="textareaId">{{ ngf.label() | dynamicText | async }}</label>
1502
1075
  }
1503
1076
  @if (p?.validFeedback && f().valid() && f().touched()) {
1504
1077
  <div class="valid-feedback d-block">
1505
1078
  {{ p?.validFeedback | dynamicText | async }}
1506
1079
  </div>
1507
1080
  }
1508
- @if (errorsToDisplay()[0]; as error) {
1509
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
1081
+ @if (ngf.errorsToDisplay()[0]; as error) {
1082
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1510
1083
  } @else if (p?.hint) {
1511
- <div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
1084
+ <div class="form-text" [id]="ngf.hintId()">{{ p?.hint | dynamicText | async }}</div>
1512
1085
  }
1513
1086
  </div>
1514
1087
  } @else {
1515
1088
  <!-- Standard variant -->
1516
1089
  <div class="mb-3">
1517
- @if (label()) {
1518
- <label [for]="textareaId" class="form-label">{{ label() | dynamicText | async }}</label>
1090
+ @if (ngf.label()) {
1091
+ <label [for]="textareaId" class="form-label">{{ ngf.label() | dynamicText | async }}</label>
1519
1092
  }
1520
1093
 
1521
1094
  <textarea
1095
+ ngForgeControl
1522
1096
  #textareaRef
1523
1097
  [formField]="f"
1524
1098
  [id]="textareaId"
1525
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
1526
- [attr.tabindex]="tabIndex()"
1527
- [attr.aria-invalid]="ariaInvalid()"
1528
- [attr.aria-required]="ariaRequired()"
1529
- [attr.aria-describedby]="ariaDescribedBy()"
1099
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
1100
+ [attr.tabindex]="ngf.tabIndex()"
1530
1101
  class="form-control"
1531
1102
  [class.form-control-sm]="p?.size === 'sm'"
1532
1103
  [class.form-control-lg]="p?.size === 'lg'"
@@ -1539,31 +1110,29 @@ class BsTextareaFieldComponent {
1539
1110
  {{ p?.validFeedback | dynamicText | async }}
1540
1111
  </div>
1541
1112
  }
1542
- @if (errorsToDisplay()[0]; as error) {
1543
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
1113
+ @if (ngf.errorsToDisplay()[0]; as error) {
1114
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1544
1115
  } @else if (p?.hint) {
1545
- <div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
1116
+ <div class="form-text" [id]="ngf.hintId()">{{ p?.hint | dynamicText | async }}</div>
1546
1117
  }
1547
1118
  </div>
1548
1119
  }
1549
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1120
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1550
1121
  }
1551
1122
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsTextareaFieldComponent, decorators: [{
1552
1123
  type: Component,
1553
- args: [{ selector: 'df-bs-textarea', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
1554
- @let f = field(); @let p = props(); @let textareaId = key() + '-textarea';
1124
+ args: [{ selector: 'df-bs-textarea', imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
1125
+ @let f = ngf.field(); @let p = props(); @let textareaId = ngf.key() + '-textarea';
1555
1126
  @if (p?.floatingLabel) {
1556
1127
  <!-- Floating label variant -->
1557
1128
  <div class="form-floating mb-3">
1558
1129
  <textarea
1130
+ ngForgeControl
1559
1131
  #textareaRef
1560
1132
  [formField]="f"
1561
1133
  [id]="textareaId"
1562
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
1563
- [attr.tabindex]="tabIndex()"
1564
- [attr.aria-invalid]="ariaInvalid()"
1565
- [attr.aria-required]="ariaRequired()"
1566
- [attr.aria-describedby]="ariaDescribedBy()"
1134
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
1135
+ [attr.tabindex]="ngf.tabIndex()"
1567
1136
  class="form-control"
1568
1137
  [class.form-control-sm]="p?.size === 'sm'"
1569
1138
  [class.form-control-lg]="p?.size === 'lg'"
@@ -1571,36 +1140,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1571
1140
  [class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
1572
1141
  ></textarea>
1573
1142
 
1574
- @if (label()) {
1575
- <label [for]="textareaId">{{ label() | dynamicText | async }}</label>
1143
+ @if (ngf.label()) {
1144
+ <label [for]="textareaId">{{ ngf.label() | dynamicText | async }}</label>
1576
1145
  }
1577
1146
  @if (p?.validFeedback && f().valid() && f().touched()) {
1578
1147
  <div class="valid-feedback d-block">
1579
1148
  {{ p?.validFeedback | dynamicText | async }}
1580
1149
  </div>
1581
1150
  }
1582
- @if (errorsToDisplay()[0]; as error) {
1583
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
1151
+ @if (ngf.errorsToDisplay()[0]; as error) {
1152
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1584
1153
  } @else if (p?.hint) {
1585
- <div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
1154
+ <div class="form-text" [id]="ngf.hintId()">{{ p?.hint | dynamicText | async }}</div>
1586
1155
  }
1587
1156
  </div>
1588
1157
  } @else {
1589
1158
  <!-- Standard variant -->
1590
1159
  <div class="mb-3">
1591
- @if (label()) {
1592
- <label [for]="textareaId" class="form-label">{{ label() | dynamicText | async }}</label>
1160
+ @if (ngf.label()) {
1161
+ <label [for]="textareaId" class="form-label">{{ ngf.label() | dynamicText | async }}</label>
1593
1162
  }
1594
1163
 
1595
1164
  <textarea
1165
+ ngForgeControl
1596
1166
  #textareaRef
1597
1167
  [formField]="f"
1598
1168
  [id]="textareaId"
1599
- [placeholder]="(placeholder() | dynamicText | async) ?? ''"
1600
- [attr.tabindex]="tabIndex()"
1601
- [attr.aria-invalid]="ariaInvalid()"
1602
- [attr.aria-required]="ariaRequired()"
1603
- [attr.aria-describedby]="ariaDescribedBy()"
1169
+ [placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
1170
+ [attr.tabindex]="ngf.tabIndex()"
1604
1171
  class="form-control"
1605
1172
  [class.form-control-sm]="p?.size === 'sm'"
1606
1173
  [class.form-control-lg]="p?.size === 'lg'"
@@ -1613,20 +1180,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1613
1180
  {{ p?.validFeedback | dynamicText | async }}
1614
1181
  </div>
1615
1182
  }
1616
- @if (errorsToDisplay()[0]; as error) {
1617
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
1183
+ @if (ngf.errorsToDisplay()[0]; as error) {
1184
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1618
1185
  } @else if (p?.hint) {
1619
- <div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
1186
+ <div class="form-text" [id]="ngf.hintId()">{{ p?.hint | dynamicText | async }}</div>
1620
1187
  }
1621
1188
  </div>
1622
1189
  }
1623
- `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1624
- '[id]': '`${key()}`',
1625
- '[attr.data-testid]': 'key()',
1626
- '[class]': 'className()',
1627
- '[attr.hidden]': 'field()().hidden() || null',
1628
- }, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
1629
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], textareaRef: [{ type: i0.ViewChild, args: ['textareaRef', { isSignal: true }] }] } });
1190
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
1191
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], textareaRef: [{ type: i0.ViewChild, args: ['textareaRef', { isSignal: true }] }] } });
1630
1192
 
1631
1193
  var bsTextarea_component = /*#__PURE__*/Object.freeze({
1632
1194
  __proto__: null,
@@ -1634,39 +1196,11 @@ var bsTextarea_component = /*#__PURE__*/Object.freeze({
1634
1196
  });
1635
1197
 
1636
1198
  class BsToggleFieldComponent {
1637
- elementRef = inject((ElementRef));
1638
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
1639
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
1640
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
1641
- placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
1642
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
1643
- tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
1199
+ ngf = injectNgForgeField();
1644
1200
  props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
1645
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
1646
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
1647
- meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
1648
- resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
1649
- showErrors = shouldShowErrors(this.field);
1650
- errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
1651
- constructor() {
1652
- setupMetaTracking(this.elementRef, this.meta, { selector: 'input[type="checkbox"]' });
1653
- }
1654
- // ─────────────────────────────────────────────────────────────────────────────
1655
- // Accessibility
1656
- // ─────────────────────────────────────────────────────────────────────────────
1657
- hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
1658
- errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
1659
- ariaInvalid = computed(() => {
1660
- const fieldState = this.field()();
1661
- return fieldState.invalid() && fieldState.touched();
1662
- }, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
1663
- ariaRequired = computed(() => {
1664
- return this.field()().required?.() === true ? true : null;
1665
- }, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
1666
- ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
1667
1201
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1668
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsToggleFieldComponent, isStandalone: true, selector: "df-bs-toggle", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
1669
- @let f = field(); @let inputId = key() + '-input';
1202
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: BsToggleFieldComponent, isStandalone: true, selector: "df-bs-toggle", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
1203
+ @let f = ngf.field(); @let inputId = ngf.key() + '-input';
1670
1204
 
1671
1205
  <div
1672
1206
  class="form-check form-switch"
@@ -1677,32 +1211,30 @@ class BsToggleFieldComponent {
1677
1211
  [attr.hidden]="f().hidden() || null"
1678
1212
  >
1679
1213
  <input
1214
+ ngForgeControl
1680
1215
  type="checkbox"
1681
1216
  [formField]="f"
1682
1217
  [id]="inputId"
1683
1218
  class="form-check-input"
1684
1219
  [class.is-invalid]="f().invalid() && f().touched()"
1685
- [attr.tabindex]="tabIndex()"
1686
- [attr.aria-invalid]="ariaInvalid()"
1687
- [attr.aria-required]="ariaRequired()"
1688
- [attr.aria-describedby]="ariaDescribedBy()"
1220
+ [attr.tabindex]="ngf.tabIndex()"
1689
1221
  />
1690
1222
  <label [for]="inputId" class="form-check-label">
1691
- {{ label() | dynamicText | async }}
1223
+ {{ ngf.label() | dynamicText | async }}
1692
1224
  </label>
1693
1225
  </div>
1694
1226
 
1695
- @if (errorsToDisplay()[0]; as error) {
1696
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
1227
+ @if (ngf.errorsToDisplay()[0]; as error) {
1228
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1697
1229
  } @else if (props()?.hint; as hint) {
1698
- <div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
1230
+ <div class="form-text" [id]="ngf.hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
1699
1231
  }
1700
- `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}.form-switch-sm .form-check-input{width:1.75rem;height:1rem;font-size:.875rem}.form-switch-lg .form-check-input{width:3rem;height:1.75rem;font-size:1.125rem}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1232
+ `, isInline: true, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}.form-switch-sm .form-check-input{width:1.75rem;height:1rem;font-size:.875rem}.form-switch-lg .form-check-input{width:3rem;height:1.75rem;font-size:1.125rem}\n"], dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1701
1233
  }
1702
1234
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BsToggleFieldComponent, decorators: [{
1703
1235
  type: Component,
1704
- args: [{ selector: 'df-bs-toggle', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
1705
- @let f = field(); @let inputId = key() + '-input';
1236
+ args: [{ selector: 'df-bs-toggle', imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
1237
+ @let f = ngf.field(); @let inputId = ngf.key() + '-input';
1706
1238
 
1707
1239
  <div
1708
1240
  class="form-check form-switch"
@@ -1713,33 +1245,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1713
1245
  [attr.hidden]="f().hidden() || null"
1714
1246
  >
1715
1247
  <input
1248
+ ngForgeControl
1716
1249
  type="checkbox"
1717
1250
  [formField]="f"
1718
1251
  [id]="inputId"
1719
1252
  class="form-check-input"
1720
1253
  [class.is-invalid]="f().invalid() && f().touched()"
1721
- [attr.tabindex]="tabIndex()"
1722
- [attr.aria-invalid]="ariaInvalid()"
1723
- [attr.aria-required]="ariaRequired()"
1724
- [attr.aria-describedby]="ariaDescribedBy()"
1254
+ [attr.tabindex]="ngf.tabIndex()"
1725
1255
  />
1726
1256
  <label [for]="inputId" class="form-check-label">
1727
- {{ label() | dynamicText | async }}
1257
+ {{ ngf.label() | dynamicText | async }}
1728
1258
  </label>
1729
1259
  </div>
1730
1260
 
1731
- @if (errorsToDisplay()[0]; as error) {
1732
- <div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
1261
+ @if (ngf.errorsToDisplay()[0]; as error) {
1262
+ <div class="invalid-feedback d-block" [id]="ngf.errorId()" role="alert">{{ error.message }}</div>
1733
1263
  } @else if (props()?.hint; as hint) {
1734
- <div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
1264
+ <div class="form-text" [id]="ngf.hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
1735
1265
  }
1736
- `, host: {
1737
- '[class]': 'className()',
1738
- '[id]': '`${key()}`',
1739
- '[attr.data-testid]': 'key()',
1740
- '[attr.hidden]': 'field()().hidden() || null',
1741
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}.form-switch-sm .form-check-input{width:1.75rem;height:1rem;font-size:.875rem}.form-switch-lg .form-check-input{width:3rem;height:1.75rem;font-size:1.125rem}\n"] }]
1742
- }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }] } });
1266
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--bs-secondary-color, #6c757d);--df-hint-font-size: .875rem;--df-error-color: var(--bs-danger, #dc3545);--df-error-font-size: .875rem}.df-bs-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%;margin-bottom:1rem}.df-bs-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color);margin-bottom:0}.df-bs-hint{color:var(--df-hint-color);font-size:var(--df-hint-font-size);margin-top:.25rem}.df-bs-field:has(.df-bs-hint){margin-bottom:.5rem}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}.form-switch-sm .form-check-input{width:1.75rem;height:1rem;font-size:.875rem}.form-switch-lg .form-check-input{width:3rem;height:1.75rem;font-size:1.125rem}\n"] }]
1267
+ }], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
1743
1268
 
1744
1269
  var bsToggle_component = /*#__PURE__*/Object.freeze({
1745
1270
  __proto__: null,