@ng-forge/dynamic-forms-bootstrap 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AsyncPipe } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { inject, input, computed, ChangeDetectionStrategy, Component, ElementRef, viewChild, effect, Directive, InjectionToken, afterRenderEffect, linkedSignal, model, isSignal } from '@angular/core';
|
|
4
|
-
import { EventBus, ARRAY_CONTEXT, resolveTokens, DynamicTextPipe, buildBaseInputs,
|
|
4
|
+
import { EventBus, ARRAY_CONTEXT, resolveTokens, DynamicTextPipe, DEFAULT_PROPS, buildBaseInputs, RootFormRegistryService, FORM_OPTIONS, resolveSubmitButtonDisabled, FIELD_SIGNAL_CONTEXT, resolveNextButtonDisabled, NextPageEvent, PreviousPageEvent, DynamicFormLogger, AddArrayItemEvent, RemoveArrayItemEvent } from '@ng-forge/dynamic-forms';
|
|
5
5
|
import { FormField } from '@angular/forms/signals';
|
|
6
6
|
import { createResolvedErrorsSignal, shouldShowErrors, setupMetaTracking, isEqual, valueFieldMapper, optionsFieldMapper, checkboxFieldMapper, datepickerFieldMapper } from '@ng-forge/dynamic-forms/integration';
|
|
7
7
|
import { explicitEffect } from 'ngxtension/explicit-effect';
|
|
@@ -78,8 +78,8 @@ class BsButtonFieldComponent {
|
|
|
78
78
|
this.eventBus.dispatch(event);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0
|
|
82
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0
|
|
81
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsButtonFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
82
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.0", 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
83
|
@let buttonId = key() + '-button';
|
|
84
84
|
<button
|
|
85
85
|
[id]="buttonId"
|
|
@@ -94,13 +94,13 @@ class BsButtonFieldComponent {
|
|
|
94
94
|
</button>
|
|
95
95
|
`, 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
96
|
}
|
|
97
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
97
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsButtonFieldComponent, decorators: [{
|
|
98
98
|
type: Component,
|
|
99
99
|
args: [{ selector: 'df-bs-button', imports: [DynamicTextPipe, AsyncPipe], host: {
|
|
100
100
|
'[id]': '`${key()}`',
|
|
101
101
|
'[attr.data-testid]': 'key()',
|
|
102
102
|
'[class]': 'className()',
|
|
103
|
-
'[hidden]': 'hidden()',
|
|
103
|
+
'[attr.hidden]': 'hidden() || null',
|
|
104
104
|
}, template: `
|
|
105
105
|
@let buttonId = key() + '-button';
|
|
106
106
|
<button
|
|
@@ -124,6 +124,29 @@ var bsButton_component = /*#__PURE__*/Object.freeze({
|
|
|
124
124
|
|
|
125
125
|
// Public API - component
|
|
126
126
|
|
|
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
|
+
|
|
127
150
|
class BsCheckboxFieldComponent {
|
|
128
151
|
elementRef = inject((ElementRef));
|
|
129
152
|
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
@@ -154,7 +177,7 @@ class BsCheckboxFieldComponent {
|
|
|
154
177
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
155
178
|
// Accessibility
|
|
156
179
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
157
|
-
|
|
180
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
158
181
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
159
182
|
ariaInvalid = computed(() => {
|
|
160
183
|
const fieldState = this.field()();
|
|
@@ -163,21 +186,10 @@ class BsCheckboxFieldComponent {
|
|
|
163
186
|
ariaRequired = computed(() => {
|
|
164
187
|
return this.field()().required?.() === true ? true : null;
|
|
165
188
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
166
|
-
ariaDescribedBy =
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
const errors = this.errorsToDisplay();
|
|
172
|
-
errors.forEach((_, i) => {
|
|
173
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
174
|
-
});
|
|
175
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
176
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
177
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
178
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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: `
|
|
179
|
-
@let f = field(); @let checkboxId = key() + '-checkbox'; @let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
180
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
189
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
190
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
191
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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';
|
|
181
193
|
|
|
182
194
|
<div
|
|
183
195
|
class="form-check"
|
|
@@ -194,30 +206,26 @@ class BsCheckboxFieldComponent {
|
|
|
194
206
|
class="form-check-input"
|
|
195
207
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
196
208
|
[attr.tabindex]="tabIndex()"
|
|
197
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
198
|
-
[attr.aria-required]="ariaRequired"
|
|
199
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
209
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
210
|
+
[attr.aria-required]="ariaRequired()"
|
|
211
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
200
212
|
/>
|
|
201
213
|
<label [for]="checkboxId" class="form-check-label">
|
|
202
214
|
{{ label() | dynamicText | async }}
|
|
203
215
|
</label>
|
|
204
216
|
</div>
|
|
205
217
|
|
|
206
|
-
@if (
|
|
207
|
-
<div class="
|
|
208
|
-
|
|
209
|
-
</div>
|
|
210
|
-
}
|
|
211
|
-
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
212
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
218
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
219
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
220
|
+
} @else if (props()?.hint; as hint) {
|
|
221
|
+
<div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
|
|
213
222
|
}
|
|
214
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"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
215
224
|
}
|
|
216
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
225
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsCheckboxFieldComponent, decorators: [{
|
|
217
226
|
type: Component,
|
|
218
227
|
args: [{ selector: 'df-bs-checkbox', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
219
|
-
@let f = field(); @let checkboxId = key() + '-checkbox';
|
|
220
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
228
|
+
@let f = field(); @let checkboxId = key() + '-checkbox';
|
|
221
229
|
|
|
222
230
|
<div
|
|
223
231
|
class="form-check"
|
|
@@ -234,22 +242,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
234
242
|
class="form-check-input"
|
|
235
243
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
236
244
|
[attr.tabindex]="tabIndex()"
|
|
237
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
238
|
-
[attr.aria-required]="ariaRequired"
|
|
239
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
245
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
246
|
+
[attr.aria-required]="ariaRequired()"
|
|
247
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
240
248
|
/>
|
|
241
249
|
<label [for]="checkboxId" class="form-check-label">
|
|
242
250
|
{{ label() | dynamicText | async }}
|
|
243
251
|
</label>
|
|
244
252
|
</div>
|
|
245
253
|
|
|
246
|
-
@if (
|
|
247
|
-
<div class="
|
|
248
|
-
|
|
249
|
-
</div>
|
|
250
|
-
}
|
|
251
|
-
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
252
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
254
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
255
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
256
|
+
} @else if (props()?.hint; as hint) {
|
|
257
|
+
<div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
|
|
253
258
|
}
|
|
254
259
|
`, host: {
|
|
255
260
|
'[class]': 'className()',
|
|
@@ -299,10 +304,10 @@ class InputConstraintsDirective {
|
|
|
299
304
|
nativeElement.removeAttribute('step');
|
|
300
305
|
}
|
|
301
306
|
});
|
|
302
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0
|
|
303
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0
|
|
307
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: InputConstraintsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
308
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: InputConstraintsDirective, isStandalone: true, selector: "[dfBsInputConstraints]", inputs: { dfMin: { classPropertyName: "dfMin", publicName: "dfMin", isSignal: true, isRequired: false, transformFunction: null }, dfMax: { classPropertyName: "dfMax", publicName: "dfMax", isSignal: true, isRequired: false, transformFunction: null }, dfStep: { classPropertyName: "dfStep", publicName: "dfStep", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
304
309
|
}
|
|
305
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
310
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: InputConstraintsDirective, decorators: [{
|
|
306
311
|
type: Directive,
|
|
307
312
|
args: [{
|
|
308
313
|
selector: '[dfBsInputConstraints]',
|
|
@@ -342,7 +347,7 @@ class BsDatepickerFieldComponent {
|
|
|
342
347
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
343
348
|
// Accessibility
|
|
344
349
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
345
|
-
|
|
350
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
346
351
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
347
352
|
ariaInvalid = computed(() => {
|
|
348
353
|
const fieldState = this.field()();
|
|
@@ -351,21 +356,10 @@ class BsDatepickerFieldComponent {
|
|
|
351
356
|
ariaRequired = computed(() => {
|
|
352
357
|
return this.field()().required?.() === true ? true : null;
|
|
353
358
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
354
|
-
ariaDescribedBy =
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
const errors = this.errorsToDisplay();
|
|
360
|
-
errors.forEach((_, i) => {
|
|
361
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
362
|
-
});
|
|
363
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
364
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
365
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsDatepickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
366
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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: `
|
|
367
|
-
@let f = field(); @let p = props(); @let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
368
|
-
@let ariaDescribedBy = this.ariaDescribedBy(); @let inputId = key() + '-input';
|
|
359
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
360
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsDatepickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
361
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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';
|
|
369
363
|
@if (p?.floatingLabel) {
|
|
370
364
|
<!-- Floating label variant -->
|
|
371
365
|
<div class="form-floating mb-3">
|
|
@@ -378,9 +372,9 @@ class BsDatepickerFieldComponent {
|
|
|
378
372
|
[dfMin]="minAsString()"
|
|
379
373
|
[dfMax]="maxAsString()"
|
|
380
374
|
[attr.tabindex]="tabIndex()"
|
|
381
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
382
|
-
[attr.aria-required]="ariaRequired"
|
|
383
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
375
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
376
|
+
[attr.aria-required]="ariaRequired()"
|
|
377
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
384
378
|
class="form-control"
|
|
385
379
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
386
380
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -395,8 +389,8 @@ class BsDatepickerFieldComponent {
|
|
|
395
389
|
{{ p?.validFeedback | dynamicText | async }}
|
|
396
390
|
</div>
|
|
397
391
|
}
|
|
398
|
-
@
|
|
399
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
392
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
393
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
400
394
|
}
|
|
401
395
|
</div>
|
|
402
396
|
} @else {
|
|
@@ -415,9 +409,9 @@ class BsDatepickerFieldComponent {
|
|
|
415
409
|
[dfMin]="minAsString()"
|
|
416
410
|
[dfMax]="maxAsString()"
|
|
417
411
|
[attr.tabindex]="tabIndex()"
|
|
418
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
419
|
-
[attr.aria-required]="ariaRequired"
|
|
420
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
412
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
413
|
+
[attr.aria-required]="ariaRequired()"
|
|
414
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
421
415
|
class="form-control"
|
|
422
416
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
423
417
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -425,28 +419,24 @@ class BsDatepickerFieldComponent {
|
|
|
425
419
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
426
420
|
/>
|
|
427
421
|
|
|
428
|
-
@if (p?.helpText) {
|
|
429
|
-
<div class="form-text" [id]="helpTextId()">
|
|
430
|
-
{{ p?.helpText | dynamicText | async }}
|
|
431
|
-
</div>
|
|
432
|
-
}
|
|
433
422
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
434
423
|
<div class="valid-feedback d-block">
|
|
435
424
|
{{ p?.validFeedback | dynamicText | async }}
|
|
436
425
|
</div>
|
|
437
426
|
}
|
|
438
|
-
@
|
|
439
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
427
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
428
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
429
|
+
} @else if (p?.hint) {
|
|
430
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
440
431
|
}
|
|
441
432
|
</div>
|
|
442
433
|
}
|
|
443
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"] }, { 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 });
|
|
444
435
|
}
|
|
445
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
436
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsDatepickerFieldComponent, decorators: [{
|
|
446
437
|
type: Component,
|
|
447
438
|
args: [{ selector: 'df-bs-datepicker', imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective], template: `
|
|
448
|
-
@let f = field(); @let p = props(); @let
|
|
449
|
-
@let ariaDescribedBy = this.ariaDescribedBy(); @let inputId = key() + '-input';
|
|
439
|
+
@let f = field(); @let p = props(); @let inputId = key() + '-input';
|
|
450
440
|
@if (p?.floatingLabel) {
|
|
451
441
|
<!-- Floating label variant -->
|
|
452
442
|
<div class="form-floating mb-3">
|
|
@@ -459,9 +449,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
459
449
|
[dfMin]="minAsString()"
|
|
460
450
|
[dfMax]="maxAsString()"
|
|
461
451
|
[attr.tabindex]="tabIndex()"
|
|
462
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
463
|
-
[attr.aria-required]="ariaRequired"
|
|
464
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
452
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
453
|
+
[attr.aria-required]="ariaRequired()"
|
|
454
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
465
455
|
class="form-control"
|
|
466
456
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
467
457
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -476,8 +466,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
476
466
|
{{ p?.validFeedback | dynamicText | async }}
|
|
477
467
|
</div>
|
|
478
468
|
}
|
|
479
|
-
@
|
|
480
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
469
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
470
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
481
471
|
}
|
|
482
472
|
</div>
|
|
483
473
|
} @else {
|
|
@@ -496,9 +486,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
496
486
|
[dfMin]="minAsString()"
|
|
497
487
|
[dfMax]="maxAsString()"
|
|
498
488
|
[attr.tabindex]="tabIndex()"
|
|
499
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
500
|
-
[attr.aria-required]="ariaRequired"
|
|
501
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
489
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
490
|
+
[attr.aria-required]="ariaRequired()"
|
|
491
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
502
492
|
class="form-control"
|
|
503
493
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
504
494
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -506,18 +496,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
506
496
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
507
497
|
/>
|
|
508
498
|
|
|
509
|
-
@if (p?.helpText) {
|
|
510
|
-
<div class="form-text" [id]="helpTextId()">
|
|
511
|
-
{{ p?.helpText | dynamicText | async }}
|
|
512
|
-
</div>
|
|
513
|
-
}
|
|
514
499
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
515
500
|
<div class="valid-feedback d-block">
|
|
516
501
|
{{ p?.validFeedback | dynamicText | async }}
|
|
517
502
|
</div>
|
|
518
503
|
}
|
|
519
|
-
@
|
|
520
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
504
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
505
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
506
|
+
} @else if (p?.hint) {
|
|
507
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
521
508
|
}
|
|
522
509
|
</div>
|
|
523
510
|
}
|
|
@@ -613,8 +600,8 @@ class BsInputFieldComponent {
|
|
|
613
600
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
614
601
|
// Accessibility
|
|
615
602
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
616
|
-
/** Unique ID for the
|
|
617
|
-
|
|
603
|
+
/** Unique ID for the hint element, used for aria-describedby */
|
|
604
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
618
605
|
/** Base ID for error elements, used for aria-describedby */
|
|
619
606
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
620
607
|
/** aria-invalid: true when field is invalid AND touched, false otherwise */
|
|
@@ -626,26 +613,12 @@ class BsInputFieldComponent {
|
|
|
626
613
|
ariaRequired = computed(() => {
|
|
627
614
|
return this.field()().required?.() === true ? true : null;
|
|
628
615
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
629
|
-
/** aria-describedby: links to
|
|
630
|
-
ariaDescribedBy =
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
const errors = this.errorsToDisplay();
|
|
636
|
-
errors.forEach((_, i) => {
|
|
637
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
638
|
-
});
|
|
639
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
640
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
641
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
642
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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: `
|
|
643
|
-
@let f = field(); @let p = props(); @let effectiveSize = this.effectiveSize();
|
|
644
|
-
@let effectiveFloatingLabel = this.effectiveFloatingLabel();
|
|
645
|
-
@let inputId = key() + '-input';
|
|
646
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
647
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
648
|
-
@if (effectiveFloatingLabel) {
|
|
616
|
+
/** aria-describedby: links to hint and error messages for screen readers */
|
|
617
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
618
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
619
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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()) {
|
|
649
622
|
<!-- Floating label variant -->
|
|
650
623
|
<div class="form-floating mb-3">
|
|
651
624
|
<input
|
|
@@ -655,12 +628,12 @@ class BsInputFieldComponent {
|
|
|
655
628
|
[type]="p?.type ?? 'text'"
|
|
656
629
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
657
630
|
[attr.tabindex]="tabIndex()"
|
|
658
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
659
|
-
[attr.aria-required]="ariaRequired"
|
|
660
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
631
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
632
|
+
[attr.aria-required]="ariaRequired()"
|
|
633
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
661
634
|
class="form-control"
|
|
662
|
-
[class.form-control-sm]="effectiveSize === 'sm'"
|
|
663
|
-
[class.form-control-lg]="effectiveSize === 'lg'"
|
|
635
|
+
[class.form-control-sm]="effectiveSize() === 'sm'"
|
|
636
|
+
[class.form-control-lg]="effectiveSize() === 'lg'"
|
|
664
637
|
[class.form-control-plaintext]="p?.plaintext"
|
|
665
638
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
666
639
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
@@ -673,8 +646,8 @@ class BsInputFieldComponent {
|
|
|
673
646
|
{{ p?.validFeedback | dynamicText | async }}
|
|
674
647
|
</div>
|
|
675
648
|
}
|
|
676
|
-
@
|
|
677
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
649
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
650
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
678
651
|
}
|
|
679
652
|
</div>
|
|
680
653
|
} @else {
|
|
@@ -690,42 +663,35 @@ class BsInputFieldComponent {
|
|
|
690
663
|
[type]="p?.type ?? 'text'"
|
|
691
664
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
692
665
|
[attr.tabindex]="tabIndex()"
|
|
693
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
694
|
-
[attr.aria-required]="ariaRequired"
|
|
695
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
666
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
667
|
+
[attr.aria-required]="ariaRequired()"
|
|
668
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
696
669
|
class="form-control"
|
|
697
|
-
[class.form-control-sm]="effectiveSize === 'sm'"
|
|
698
|
-
[class.form-control-lg]="effectiveSize === 'lg'"
|
|
670
|
+
[class.form-control-sm]="effectiveSize() === 'sm'"
|
|
671
|
+
[class.form-control-lg]="effectiveSize() === 'lg'"
|
|
699
672
|
[class.form-control-plaintext]="p?.plaintext"
|
|
700
673
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
701
674
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
702
675
|
/>
|
|
703
|
-
@if (p?.helpText) {
|
|
704
|
-
<div class="form-text" [id]="helpTextId()">
|
|
705
|
-
{{ p?.helpText | dynamicText | async }}
|
|
706
|
-
</div>
|
|
707
|
-
}
|
|
708
676
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
709
677
|
<div class="valid-feedback d-block">
|
|
710
678
|
{{ p?.validFeedback | dynamicText | async }}
|
|
711
679
|
</div>
|
|
712
680
|
}
|
|
713
|
-
@
|
|
714
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
681
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
682
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
683
|
+
} @else if (p?.hint) {
|
|
684
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
715
685
|
}
|
|
716
686
|
</div>
|
|
717
687
|
}
|
|
718
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"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
719
689
|
}
|
|
720
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
690
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsInputFieldComponent, decorators: [{
|
|
721
691
|
type: Component,
|
|
722
692
|
args: [{ selector: 'df-bs-input', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
723
|
-
@let f = field(); @let p = props(); @let
|
|
724
|
-
@
|
|
725
|
-
@let inputId = key() + '-input';
|
|
726
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
727
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
728
|
-
@if (effectiveFloatingLabel) {
|
|
693
|
+
@let f = field(); @let p = props(); @let inputId = key() + '-input';
|
|
694
|
+
@if (effectiveFloatingLabel()) {
|
|
729
695
|
<!-- Floating label variant -->
|
|
730
696
|
<div class="form-floating mb-3">
|
|
731
697
|
<input
|
|
@@ -735,12 +701,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
735
701
|
[type]="p?.type ?? 'text'"
|
|
736
702
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
737
703
|
[attr.tabindex]="tabIndex()"
|
|
738
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
739
|
-
[attr.aria-required]="ariaRequired"
|
|
740
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
704
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
705
|
+
[attr.aria-required]="ariaRequired()"
|
|
706
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
741
707
|
class="form-control"
|
|
742
|
-
[class.form-control-sm]="effectiveSize === 'sm'"
|
|
743
|
-
[class.form-control-lg]="effectiveSize === 'lg'"
|
|
708
|
+
[class.form-control-sm]="effectiveSize() === 'sm'"
|
|
709
|
+
[class.form-control-lg]="effectiveSize() === 'lg'"
|
|
744
710
|
[class.form-control-plaintext]="p?.plaintext"
|
|
745
711
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
746
712
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
@@ -753,8 +719,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
753
719
|
{{ p?.validFeedback | dynamicText | async }}
|
|
754
720
|
</div>
|
|
755
721
|
}
|
|
756
|
-
@
|
|
757
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
722
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
723
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
758
724
|
}
|
|
759
725
|
</div>
|
|
760
726
|
} @else {
|
|
@@ -770,28 +736,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
770
736
|
[type]="p?.type ?? 'text'"
|
|
771
737
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
772
738
|
[attr.tabindex]="tabIndex()"
|
|
773
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
774
|
-
[attr.aria-required]="ariaRequired"
|
|
775
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
739
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
740
|
+
[attr.aria-required]="ariaRequired()"
|
|
741
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
776
742
|
class="form-control"
|
|
777
|
-
[class.form-control-sm]="effectiveSize === 'sm'"
|
|
778
|
-
[class.form-control-lg]="effectiveSize === 'lg'"
|
|
743
|
+
[class.form-control-sm]="effectiveSize() === 'sm'"
|
|
744
|
+
[class.form-control-lg]="effectiveSize() === 'lg'"
|
|
779
745
|
[class.form-control-plaintext]="p?.plaintext"
|
|
780
746
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
781
747
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
782
748
|
/>
|
|
783
|
-
@if (p?.helpText) {
|
|
784
|
-
<div class="form-text" [id]="helpTextId()">
|
|
785
|
-
{{ p?.helpText | dynamicText | async }}
|
|
786
|
-
</div>
|
|
787
|
-
}
|
|
788
749
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
789
750
|
<div class="valid-feedback d-block">
|
|
790
751
|
{{ p?.validFeedback | dynamicText | async }}
|
|
791
752
|
</div>
|
|
792
753
|
}
|
|
793
|
-
@
|
|
794
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
754
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
755
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
756
|
+
} @else if (p?.hint) {
|
|
757
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
795
758
|
}
|
|
796
759
|
</div>
|
|
797
760
|
}
|
|
@@ -824,6 +787,14 @@ class BsMultiCheckboxFieldComponent {
|
|
|
824
787
|
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
825
788
|
showErrors = shouldShowErrors(this.field);
|
|
826
789
|
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
|
|
790
|
+
/** Computed map of checked option values for O(1) lookup in template */
|
|
791
|
+
checkedValuesMap = computed(() => {
|
|
792
|
+
const map = {};
|
|
793
|
+
for (const opt of this.valueViewModel()) {
|
|
794
|
+
map[String(opt.value)] = true;
|
|
795
|
+
}
|
|
796
|
+
return map;
|
|
797
|
+
}, ...(ngDevMode ? [{ debugName: "checkedValuesMap" }] : []));
|
|
827
798
|
valueViewModel = linkedSignal(() => {
|
|
828
799
|
const currentValues = this.field()().value();
|
|
829
800
|
return this.options().filter((option) => currentValues.includes(option.value));
|
|
@@ -845,23 +816,23 @@ class BsMultiCheckboxFieldComponent {
|
|
|
845
816
|
}
|
|
846
817
|
});
|
|
847
818
|
}
|
|
848
|
-
onCheckboxChange(option,
|
|
819
|
+
onCheckboxChange(option, event) {
|
|
820
|
+
const checked = event.target.checked;
|
|
849
821
|
this.valueViewModel.update((currentOptions) => {
|
|
850
822
|
if (checked) {
|
|
851
|
-
return currentOptions.some((opt) => opt.value === option.value)
|
|
823
|
+
return currentOptions.some((opt) => opt.value === option.value)
|
|
824
|
+
? currentOptions
|
|
825
|
+
: [...currentOptions, option];
|
|
852
826
|
}
|
|
853
827
|
else {
|
|
854
828
|
return currentOptions.filter((opt) => opt.value !== option.value);
|
|
855
829
|
}
|
|
856
830
|
});
|
|
857
831
|
}
|
|
858
|
-
isChecked(option) {
|
|
859
|
-
return this.valueViewModel().some((opt) => opt.value === option.value);
|
|
860
|
-
}
|
|
861
832
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
862
833
|
// Accessibility
|
|
863
834
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
864
|
-
|
|
835
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
865
836
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
866
837
|
ariaInvalid = computed(() => {
|
|
867
838
|
const fieldState = this.field()();
|
|
@@ -870,22 +841,11 @@ class BsMultiCheckboxFieldComponent {
|
|
|
870
841
|
ariaRequired = computed(() => {
|
|
871
842
|
return this.field()().required?.() === true ? true : null;
|
|
872
843
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
873
|
-
ariaDescribedBy =
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
ids.push(this.helpTextId());
|
|
877
|
-
}
|
|
878
|
-
const errors = this.errorsToDisplay();
|
|
879
|
-
errors.forEach((_, i) => {
|
|
880
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
881
|
-
});
|
|
882
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
883
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
884
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
885
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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: `
|
|
844
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
845
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
846
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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: `
|
|
886
847
|
@let f = field();
|
|
887
|
-
@let
|
|
888
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
848
|
+
@let checked = checkedValuesMap();
|
|
889
849
|
@if (label(); as label) {
|
|
890
850
|
<div class="form-label">{{ label | dynamicText | async }}</div>
|
|
891
851
|
}
|
|
@@ -901,15 +861,15 @@ class BsMultiCheckboxFieldComponent {
|
|
|
901
861
|
<input
|
|
902
862
|
type="checkbox"
|
|
903
863
|
[id]="key() + '_' + i"
|
|
904
|
-
[checked]="
|
|
864
|
+
[checked]="checked['' + option.value]"
|
|
905
865
|
[disabled]="f().disabled() || option.disabled"
|
|
906
|
-
(change)="onCheckboxChange(option, $
|
|
866
|
+
(change)="onCheckboxChange(option, $event)"
|
|
907
867
|
class="form-check-input"
|
|
908
868
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
909
869
|
[attr.tabindex]="tabIndex()"
|
|
910
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
911
|
-
[attr.aria-required]="ariaRequired"
|
|
912
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
870
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
871
|
+
[attr.aria-required]="ariaRequired()"
|
|
872
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
913
873
|
/>
|
|
914
874
|
<label [for]="key() + '_' + i" class="form-check-label">
|
|
915
875
|
{{ option.label | dynamicText | async }}
|
|
@@ -918,22 +878,18 @@ class BsMultiCheckboxFieldComponent {
|
|
|
918
878
|
}
|
|
919
879
|
</div>
|
|
920
880
|
|
|
921
|
-
@if (
|
|
922
|
-
<div class="
|
|
923
|
-
|
|
924
|
-
</div>
|
|
925
|
-
}
|
|
926
|
-
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
927
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
881
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
882
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
883
|
+
} @else if (props()?.hint; as hint) {
|
|
884
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
928
885
|
}
|
|
929
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 });
|
|
930
887
|
}
|
|
931
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
888
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsMultiCheckboxFieldComponent, decorators: [{
|
|
932
889
|
type: Component,
|
|
933
890
|
args: [{ selector: 'df-bs-multi-checkbox', imports: [DynamicTextPipe, AsyncPipe], template: `
|
|
934
891
|
@let f = field();
|
|
935
|
-
@let
|
|
936
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
892
|
+
@let checked = checkedValuesMap();
|
|
937
893
|
@if (label(); as label) {
|
|
938
894
|
<div class="form-label">{{ label | dynamicText | async }}</div>
|
|
939
895
|
}
|
|
@@ -949,15 +905,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
949
905
|
<input
|
|
950
906
|
type="checkbox"
|
|
951
907
|
[id]="key() + '_' + i"
|
|
952
|
-
[checked]="
|
|
908
|
+
[checked]="checked['' + option.value]"
|
|
953
909
|
[disabled]="f().disabled() || option.disabled"
|
|
954
|
-
(change)="onCheckboxChange(option, $
|
|
910
|
+
(change)="onCheckboxChange(option, $event)"
|
|
955
911
|
class="form-check-input"
|
|
956
912
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
957
913
|
[attr.tabindex]="tabIndex()"
|
|
958
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
959
|
-
[attr.aria-required]="ariaRequired"
|
|
960
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
914
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
915
|
+
[attr.aria-required]="ariaRequired()"
|
|
916
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
961
917
|
/>
|
|
962
918
|
<label [for]="key() + '_' + i" class="form-check-label">
|
|
963
919
|
{{ option.label | dynamicText | async }}
|
|
@@ -966,13 +922,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
966
922
|
}
|
|
967
923
|
</div>
|
|
968
924
|
|
|
969
|
-
@if (
|
|
970
|
-
<div class="
|
|
971
|
-
|
|
972
|
-
</div>
|
|
973
|
-
}
|
|
974
|
-
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
975
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
925
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
926
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
927
|
+
} @else if (props()?.hint; as hint) {
|
|
928
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
976
929
|
}
|
|
977
930
|
`, host: {
|
|
978
931
|
'[class]': 'className() || ""',
|
|
@@ -1013,10 +966,9 @@ class BsRadioGroupComponent {
|
|
|
1013
966
|
this.value.set(newValue);
|
|
1014
967
|
}
|
|
1015
968
|
}
|
|
1016
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0
|
|
1017
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0
|
|
969
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsRadioGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
970
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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: `
|
|
1018
971
|
@let props = properties();
|
|
1019
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1020
972
|
@if (props?.buttonGroup) {
|
|
1021
973
|
<div class="btn-group" role="group" [attr.aria-label]="label() | dynamicText | async">
|
|
1022
974
|
@for (option of options(); track option.value; let i = $index) {
|
|
@@ -1027,7 +979,7 @@ class BsRadioGroupComponent {
|
|
|
1027
979
|
[checked]="value() === option.value"
|
|
1028
980
|
(change)="onRadioChange(option.value)"
|
|
1029
981
|
[disabled]="disabled() || option.disabled || false"
|
|
1030
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
982
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1031
983
|
class="btn-check"
|
|
1032
984
|
[id]="name() + '_' + i"
|
|
1033
985
|
autocomplete="off"
|
|
@@ -1052,7 +1004,7 @@ class BsRadioGroupComponent {
|
|
|
1052
1004
|
[checked]="value() === option.value"
|
|
1053
1005
|
(change)="onRadioChange(option.value)"
|
|
1054
1006
|
[disabled]="disabled() || option.disabled || false"
|
|
1055
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1007
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1056
1008
|
class="form-check-input"
|
|
1057
1009
|
[id]="name() + '_' + i"
|
|
1058
1010
|
/>
|
|
@@ -1064,11 +1016,10 @@ class BsRadioGroupComponent {
|
|
|
1064
1016
|
}
|
|
1065
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 });
|
|
1066
1018
|
}
|
|
1067
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1019
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsRadioGroupComponent, decorators: [{
|
|
1068
1020
|
type: Component,
|
|
1069
1021
|
args: [{ selector: 'df-bs-radio-group', imports: [DynamicTextPipe, AsyncPipe], template: `
|
|
1070
1022
|
@let props = properties();
|
|
1071
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1072
1023
|
@if (props?.buttonGroup) {
|
|
1073
1024
|
<div class="btn-group" role="group" [attr.aria-label]="label() | dynamicText | async">
|
|
1074
1025
|
@for (option of options(); track option.value; let i = $index) {
|
|
@@ -1079,7 +1030,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1079
1030
|
[checked]="value() === option.value"
|
|
1080
1031
|
(change)="onRadioChange(option.value)"
|
|
1081
1032
|
[disabled]="disabled() || option.disabled || false"
|
|
1082
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1033
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1083
1034
|
class="btn-check"
|
|
1084
1035
|
[id]="name() + '_' + i"
|
|
1085
1036
|
autocomplete="off"
|
|
@@ -1104,7 +1055,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1104
1055
|
[checked]="value() === option.value"
|
|
1105
1056
|
(change)="onRadioChange(option.value)"
|
|
1106
1057
|
[disabled]="disabled() || option.disabled || false"
|
|
1107
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1058
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1108
1059
|
class="form-check-input"
|
|
1109
1060
|
[id]="name() + '_' + i"
|
|
1110
1061
|
/>
|
|
@@ -1142,7 +1093,7 @@ class BsRadioFieldComponent {
|
|
|
1142
1093
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1143
1094
|
// Accessibility
|
|
1144
1095
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1145
|
-
|
|
1096
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1146
1097
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1147
1098
|
ariaInvalid = computed(() => {
|
|
1148
1099
|
const fieldState = this.field()();
|
|
@@ -1151,21 +1102,10 @@ class BsRadioFieldComponent {
|
|
|
1151
1102
|
ariaRequired = computed(() => {
|
|
1152
1103
|
return this.field()().required?.() === true ? true : null;
|
|
1153
1104
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1154
|
-
ariaDescribedBy =
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
ids.push(this.helpTextId());
|
|
1158
|
-
}
|
|
1159
|
-
const errors = this.errorsToDisplay();
|
|
1160
|
-
errors.forEach((_, i) => {
|
|
1161
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1162
|
-
});
|
|
1163
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1164
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1165
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1166
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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: `
|
|
1105
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1106
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1107
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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: `
|
|
1167
1108
|
@let f = field();
|
|
1168
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1169
1109
|
|
|
1170
1110
|
<div class="mb-3">
|
|
1171
1111
|
@if (label(); as label) {
|
|
@@ -1173,27 +1113,25 @@ class BsRadioFieldComponent {
|
|
|
1173
1113
|
}
|
|
1174
1114
|
|
|
1175
1115
|
<df-bs-radio-group
|
|
1176
|
-
[formField]="
|
|
1116
|
+
[formField]="f"
|
|
1177
1117
|
[label]="label()"
|
|
1178
1118
|
[options]="options()"
|
|
1179
1119
|
[properties]="props()"
|
|
1180
|
-
[ariaDescribedBy]="ariaDescribedBy"
|
|
1120
|
+
[ariaDescribedBy]="ariaDescribedBy()"
|
|
1181
1121
|
/>
|
|
1182
1122
|
|
|
1183
|
-
@if (
|
|
1184
|
-
<div class="
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1123
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1124
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1125
|
+
} @else if (props()?.hint; as hint) {
|
|
1126
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1188
1127
|
}
|
|
1189
1128
|
</div>
|
|
1190
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"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1191
1130
|
}
|
|
1192
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1131
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsRadioFieldComponent, decorators: [{
|
|
1193
1132
|
type: Component,
|
|
1194
1133
|
args: [{ selector: 'df-bs-radio', imports: [BsRadioGroupComponent, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1195
1134
|
@let f = field();
|
|
1196
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1197
1135
|
|
|
1198
1136
|
<div class="mb-3">
|
|
1199
1137
|
@if (label(); as label) {
|
|
@@ -1201,18 +1139,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1201
1139
|
}
|
|
1202
1140
|
|
|
1203
1141
|
<df-bs-radio-group
|
|
1204
|
-
[formField]="
|
|
1142
|
+
[formField]="f"
|
|
1205
1143
|
[label]="label()"
|
|
1206
1144
|
[options]="options()"
|
|
1207
1145
|
[properties]="props()"
|
|
1208
|
-
[ariaDescribedBy]="ariaDescribedBy"
|
|
1146
|
+
[ariaDescribedBy]="ariaDescribedBy()"
|
|
1209
1147
|
/>
|
|
1210
1148
|
|
|
1211
|
-
@if (
|
|
1212
|
-
<div class="
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1149
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1150
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1151
|
+
} @else if (props()?.hint; as hint) {
|
|
1152
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1216
1153
|
}
|
|
1217
1154
|
</div>
|
|
1218
1155
|
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
@@ -1258,7 +1195,7 @@ class BsSelectFieldComponent {
|
|
|
1258
1195
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1259
1196
|
// Accessibility
|
|
1260
1197
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1261
|
-
|
|
1198
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1262
1199
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1263
1200
|
ariaInvalid = computed(() => {
|
|
1264
1201
|
const fieldState = this.field()();
|
|
@@ -1267,21 +1204,10 @@ class BsSelectFieldComponent {
|
|
|
1267
1204
|
ariaRequired = computed(() => {
|
|
1268
1205
|
return this.field()().required?.() === true ? true : null;
|
|
1269
1206
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1270
|
-
ariaDescribedBy =
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
}
|
|
1275
|
-
const errors = this.errorsToDisplay();
|
|
1276
|
-
errors.forEach((_, i) => {
|
|
1277
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1278
|
-
});
|
|
1279
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1280
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1281
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1282
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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: `
|
|
1283
|
-
@let f = field(); @let selectId = key() + '-select'; @let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1284
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1207
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1208
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1209
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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';
|
|
1285
1211
|
|
|
1286
1212
|
<div class="mb-3">
|
|
1287
1213
|
@if (label(); as label) {
|
|
@@ -1296,9 +1222,9 @@ class BsSelectFieldComponent {
|
|
|
1296
1222
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
1297
1223
|
[multiple]="props()?.multiple || false"
|
|
1298
1224
|
[size]="props()?.htmlSize"
|
|
1299
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1300
|
-
[attr.aria-required]="ariaRequired"
|
|
1301
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1225
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1226
|
+
[attr.aria-required]="ariaRequired()"
|
|
1227
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1302
1228
|
>
|
|
1303
1229
|
@if (placeholder(); as placeholder) {
|
|
1304
1230
|
<option value="" disabled [selected]="!f().value()">{{ placeholder | dynamicText | async }}</option>
|
|
@@ -1310,20 +1236,18 @@ class BsSelectFieldComponent {
|
|
|
1310
1236
|
}
|
|
1311
1237
|
</select>
|
|
1312
1238
|
|
|
1313
|
-
@if (
|
|
1314
|
-
<div class="
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1239
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1240
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1241
|
+
} @else if (props()?.hint; as hint) {
|
|
1242
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1318
1243
|
}
|
|
1319
1244
|
</div>
|
|
1320
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"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1321
1246
|
}
|
|
1322
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1247
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsSelectFieldComponent, decorators: [{
|
|
1323
1248
|
type: Component,
|
|
1324
1249
|
args: [{ selector: 'df-bs-select', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1325
|
-
@let f = field(); @let selectId = key() + '-select';
|
|
1326
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1250
|
+
@let f = field(); @let selectId = key() + '-select';
|
|
1327
1251
|
|
|
1328
1252
|
<div class="mb-3">
|
|
1329
1253
|
@if (label(); as label) {
|
|
@@ -1338,9 +1262,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1338
1262
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
1339
1263
|
[multiple]="props()?.multiple || false"
|
|
1340
1264
|
[size]="props()?.htmlSize"
|
|
1341
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1342
|
-
[attr.aria-required]="ariaRequired"
|
|
1343
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1265
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1266
|
+
[attr.aria-required]="ariaRequired()"
|
|
1267
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1344
1268
|
>
|
|
1345
1269
|
@if (placeholder(); as placeholder) {
|
|
1346
1270
|
<option value="" disabled [selected]="!f().value()">{{ placeholder | dynamicText | async }}</option>
|
|
@@ -1352,11 +1276,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1352
1276
|
}
|
|
1353
1277
|
</select>
|
|
1354
1278
|
|
|
1355
|
-
@if (
|
|
1356
|
-
<div class="
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1279
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1280
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1281
|
+
} @else if (props()?.hint; as hint) {
|
|
1282
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1360
1283
|
}
|
|
1361
1284
|
</div>
|
|
1362
1285
|
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
@@ -1396,7 +1319,7 @@ class BsSliderFieldComponent {
|
|
|
1396
1319
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1397
1320
|
// Accessibility
|
|
1398
1321
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1399
|
-
|
|
1322
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1400
1323
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1401
1324
|
ariaInvalid = computed(() => {
|
|
1402
1325
|
const fieldState = this.field()();
|
|
@@ -1405,21 +1328,10 @@ class BsSliderFieldComponent {
|
|
|
1405
1328
|
ariaRequired = computed(() => {
|
|
1406
1329
|
return this.field()().required?.() === true ? true : null;
|
|
1407
1330
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1408
|
-
ariaDescribedBy =
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
}
|
|
1413
|
-
const errors = this.errorsToDisplay();
|
|
1414
|
-
errors.forEach((_, i) => {
|
|
1415
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1416
|
-
});
|
|
1417
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1418
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1419
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1420
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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: `
|
|
1421
|
-
@let f = field(); @let inputId = key() + '-input'; @let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1422
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1331
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1332
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1333
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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';
|
|
1423
1335
|
|
|
1424
1336
|
<div class="mb-3">
|
|
1425
1337
|
@if (label(); as label) {
|
|
@@ -1440,28 +1352,24 @@ class BsSliderFieldComponent {
|
|
|
1440
1352
|
[dfMax]="props()?.max ?? max()"
|
|
1441
1353
|
[dfStep]="props()?.step ?? step()"
|
|
1442
1354
|
[attr.tabindex]="tabIndex()"
|
|
1443
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1444
|
-
[attr.aria-required]="ariaRequired"
|
|
1445
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1355
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1356
|
+
[attr.aria-required]="ariaRequired()"
|
|
1357
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1446
1358
|
class="form-range"
|
|
1447
1359
|
/>
|
|
1448
1360
|
|
|
1449
|
-
@if (
|
|
1450
|
-
<div class="
|
|
1451
|
-
|
|
1452
|
-
</div>
|
|
1453
|
-
}
|
|
1454
|
-
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1455
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1361
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1362
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1363
|
+
} @else if (props()?.hint; as hint) {
|
|
1364
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1456
1365
|
}
|
|
1457
1366
|
</div>
|
|
1458
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"] }, { 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 });
|
|
1459
1368
|
}
|
|
1460
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsSliderFieldComponent, decorators: [{
|
|
1461
1370
|
type: Component,
|
|
1462
1371
|
args: [{ selector: 'df-bs-slider', imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective], template: `
|
|
1463
|
-
@let f = field(); @let inputId = key() + '-input';
|
|
1464
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1372
|
+
@let f = field(); @let inputId = key() + '-input';
|
|
1465
1373
|
|
|
1466
1374
|
<div class="mb-3">
|
|
1467
1375
|
@if (label(); as label) {
|
|
@@ -1482,19 +1390,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1482
1390
|
[dfMax]="props()?.max ?? max()"
|
|
1483
1391
|
[dfStep]="props()?.step ?? step()"
|
|
1484
1392
|
[attr.tabindex]="tabIndex()"
|
|
1485
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1486
|
-
[attr.aria-required]="ariaRequired"
|
|
1487
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1393
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1394
|
+
[attr.aria-required]="ariaRequired()"
|
|
1395
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1488
1396
|
class="form-range"
|
|
1489
1397
|
/>
|
|
1490
1398
|
|
|
1491
|
-
@if (
|
|
1492
|
-
<div class="
|
|
1493
|
-
|
|
1494
|
-
</div>
|
|
1495
|
-
}
|
|
1496
|
-
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1497
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1399
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1400
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1401
|
+
} @else if (props()?.hint; as hint) {
|
|
1402
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1498
1403
|
}
|
|
1499
1404
|
</div>
|
|
1500
1405
|
`, host: {
|
|
@@ -1531,7 +1436,7 @@ class BsTextareaFieldComponent {
|
|
|
1531
1436
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1532
1437
|
// Accessibility
|
|
1533
1438
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1534
|
-
|
|
1439
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1535
1440
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1536
1441
|
ariaInvalid = computed(() => {
|
|
1537
1442
|
const fieldState = this.field()();
|
|
@@ -1540,21 +1445,10 @@ class BsTextareaFieldComponent {
|
|
|
1540
1445
|
ariaRequired = computed(() => {
|
|
1541
1446
|
return this.field()().required?.() === true ? true : null;
|
|
1542
1447
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1543
|
-
ariaDescribedBy =
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
}
|
|
1548
|
-
const errors = this.errorsToDisplay();
|
|
1549
|
-
errors.forEach((_, i) => {
|
|
1550
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1551
|
-
});
|
|
1552
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1553
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1554
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1555
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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" } }, ngImport: i0, template: `
|
|
1556
|
-
@let f = field(); @let p = props(); @let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1557
|
-
@let ariaDescribedBy = this.ariaDescribedBy(); @let textareaId = key() + '-textarea';
|
|
1448
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1449
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1450
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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" } }, ngImport: i0, template: `
|
|
1451
|
+
@let f = field(); @let p = props(); @let textareaId = key() + '-textarea';
|
|
1558
1452
|
@if (p?.floatingLabel) {
|
|
1559
1453
|
<!-- Floating label variant -->
|
|
1560
1454
|
<div class="form-floating mb-3">
|
|
@@ -1563,9 +1457,9 @@ class BsTextareaFieldComponent {
|
|
|
1563
1457
|
[id]="textareaId"
|
|
1564
1458
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1565
1459
|
[attr.tabindex]="tabIndex()"
|
|
1566
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1567
|
-
[attr.aria-required]="ariaRequired"
|
|
1568
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1460
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1461
|
+
[attr.aria-required]="ariaRequired()"
|
|
1462
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1569
1463
|
class="form-control"
|
|
1570
1464
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
1571
1465
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -1581,8 +1475,8 @@ class BsTextareaFieldComponent {
|
|
|
1581
1475
|
{{ p?.validFeedback | dynamicText | async }}
|
|
1582
1476
|
</div>
|
|
1583
1477
|
}
|
|
1584
|
-
@
|
|
1585
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
1478
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1479
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1586
1480
|
}
|
|
1587
1481
|
</div>
|
|
1588
1482
|
} @else {
|
|
@@ -1597,9 +1491,9 @@ class BsTextareaFieldComponent {
|
|
|
1597
1491
|
[id]="textareaId"
|
|
1598
1492
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1599
1493
|
[attr.tabindex]="tabIndex()"
|
|
1600
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1601
|
-
[attr.aria-required]="ariaRequired"
|
|
1602
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1494
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1495
|
+
[attr.aria-required]="ariaRequired()"
|
|
1496
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1603
1497
|
class="form-control"
|
|
1604
1498
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
1605
1499
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -1607,28 +1501,24 @@ class BsTextareaFieldComponent {
|
|
|
1607
1501
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
1608
1502
|
></textarea>
|
|
1609
1503
|
|
|
1610
|
-
@if (p?.helpText) {
|
|
1611
|
-
<div class="form-text" [id]="helpTextId()">
|
|
1612
|
-
{{ p?.helpText | dynamicText | async }}
|
|
1613
|
-
</div>
|
|
1614
|
-
}
|
|
1615
1504
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
1616
1505
|
<div class="valid-feedback d-block">
|
|
1617
1506
|
{{ p?.validFeedback | dynamicText | async }}
|
|
1618
1507
|
</div>
|
|
1619
1508
|
}
|
|
1620
|
-
@
|
|
1621
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
1509
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1510
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1511
|
+
} @else if (p?.hint) {
|
|
1512
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
1622
1513
|
}
|
|
1623
1514
|
</div>
|
|
1624
1515
|
}
|
|
1625
1516
|
`, 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"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1626
1517
|
}
|
|
1627
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1518
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsTextareaFieldComponent, decorators: [{
|
|
1628
1519
|
type: Component,
|
|
1629
1520
|
args: [{ selector: 'df-bs-textarea', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1630
|
-
@let f = field(); @let p = props(); @let
|
|
1631
|
-
@let ariaDescribedBy = this.ariaDescribedBy(); @let textareaId = key() + '-textarea';
|
|
1521
|
+
@let f = field(); @let p = props(); @let textareaId = key() + '-textarea';
|
|
1632
1522
|
@if (p?.floatingLabel) {
|
|
1633
1523
|
<!-- Floating label variant -->
|
|
1634
1524
|
<div class="form-floating mb-3">
|
|
@@ -1637,9 +1527,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1637
1527
|
[id]="textareaId"
|
|
1638
1528
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1639
1529
|
[attr.tabindex]="tabIndex()"
|
|
1640
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1641
|
-
[attr.aria-required]="ariaRequired"
|
|
1642
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1530
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1531
|
+
[attr.aria-required]="ariaRequired()"
|
|
1532
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1643
1533
|
class="form-control"
|
|
1644
1534
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
1645
1535
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -1655,8 +1545,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1655
1545
|
{{ p?.validFeedback | dynamicText | async }}
|
|
1656
1546
|
</div>
|
|
1657
1547
|
}
|
|
1658
|
-
@
|
|
1659
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
1548
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1549
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1660
1550
|
}
|
|
1661
1551
|
</div>
|
|
1662
1552
|
} @else {
|
|
@@ -1671,9 +1561,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1671
1561
|
[id]="textareaId"
|
|
1672
1562
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1673
1563
|
[attr.tabindex]="tabIndex()"
|
|
1674
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1675
|
-
[attr.aria-required]="ariaRequired"
|
|
1676
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1564
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1565
|
+
[attr.aria-required]="ariaRequired()"
|
|
1566
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1677
1567
|
class="form-control"
|
|
1678
1568
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
1679
1569
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -1681,18 +1571,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1681
1571
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
1682
1572
|
></textarea>
|
|
1683
1573
|
|
|
1684
|
-
@if (p?.helpText) {
|
|
1685
|
-
<div class="form-text" [id]="helpTextId()">
|
|
1686
|
-
{{ p?.helpText | dynamicText | async }}
|
|
1687
|
-
</div>
|
|
1688
|
-
}
|
|
1689
1574
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
1690
1575
|
<div class="valid-feedback d-block">
|
|
1691
1576
|
{{ p?.validFeedback | dynamicText | async }}
|
|
1692
1577
|
</div>
|
|
1693
1578
|
}
|
|
1694
|
-
@
|
|
1695
|
-
<div class="invalid-feedback d-block" [id]="errorId()
|
|
1579
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1580
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1581
|
+
} @else if (p?.hint) {
|
|
1582
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
1696
1583
|
}
|
|
1697
1584
|
</div>
|
|
1698
1585
|
}
|
|
@@ -1730,7 +1617,7 @@ class BsToggleFieldComponent {
|
|
|
1730
1617
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1731
1618
|
// Accessibility
|
|
1732
1619
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1733
|
-
|
|
1620
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1734
1621
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1735
1622
|
ariaInvalid = computed(() => {
|
|
1736
1623
|
const fieldState = this.field()();
|
|
@@ -1739,21 +1626,10 @@ class BsToggleFieldComponent {
|
|
|
1739
1626
|
ariaRequired = computed(() => {
|
|
1740
1627
|
return this.field()().required?.() === true ? true : null;
|
|
1741
1628
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1742
|
-
ariaDescribedBy =
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
}
|
|
1747
|
-
const errors = this.errorsToDisplay();
|
|
1748
|
-
errors.forEach((_, i) => {
|
|
1749
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1750
|
-
});
|
|
1751
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1752
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1753
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1754
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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: `
|
|
1755
|
-
@let f = field(); @let inputId = key() + '-input'; @let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1756
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1629
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1630
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1631
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", 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: `
|
|
1632
|
+
@let f = field(); @let inputId = key() + '-input';
|
|
1757
1633
|
|
|
1758
1634
|
<div
|
|
1759
1635
|
class="form-check form-switch"
|
|
@@ -1770,30 +1646,26 @@ class BsToggleFieldComponent {
|
|
|
1770
1646
|
class="form-check-input"
|
|
1771
1647
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
1772
1648
|
[attr.tabindex]="tabIndex()"
|
|
1773
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1774
|
-
[attr.aria-required]="ariaRequired"
|
|
1775
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1649
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1650
|
+
[attr.aria-required]="ariaRequired()"
|
|
1651
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1776
1652
|
/>
|
|
1777
1653
|
<label [for]="inputId" class="form-check-label">
|
|
1778
1654
|
{{ label() | dynamicText | async }}
|
|
1779
1655
|
</label>
|
|
1780
1656
|
</div>
|
|
1781
1657
|
|
|
1782
|
-
@if (
|
|
1783
|
-
<div class="
|
|
1784
|
-
|
|
1785
|
-
</div>
|
|
1786
|
-
}
|
|
1787
|
-
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1788
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1658
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1659
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1660
|
+
} @else if (props()?.hint; as hint) {
|
|
1661
|
+
<div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
|
|
1789
1662
|
}
|
|
1790
1663
|
`, 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"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1791
1664
|
}
|
|
1792
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1665
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsToggleFieldComponent, decorators: [{
|
|
1793
1666
|
type: Component,
|
|
1794
1667
|
args: [{ selector: 'df-bs-toggle', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1795
|
-
@let f = field(); @let inputId = key() + '-input';
|
|
1796
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1668
|
+
@let f = field(); @let inputId = key() + '-input';
|
|
1797
1669
|
|
|
1798
1670
|
<div
|
|
1799
1671
|
class="form-check form-switch"
|
|
@@ -1810,22 +1682,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1810
1682
|
class="form-check-input"
|
|
1811
1683
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
1812
1684
|
[attr.tabindex]="tabIndex()"
|
|
1813
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1814
|
-
[attr.aria-required]="ariaRequired"
|
|
1815
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1685
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1686
|
+
[attr.aria-required]="ariaRequired()"
|
|
1687
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1816
1688
|
/>
|
|
1817
1689
|
<label [for]="inputId" class="form-check-label">
|
|
1818
1690
|
{{ label() | dynamicText | async }}
|
|
1819
1691
|
</label>
|
|
1820
1692
|
</div>
|
|
1821
1693
|
|
|
1822
|
-
@if (
|
|
1823
|
-
<div class="
|
|
1824
|
-
|
|
1825
|
-
</div>
|
|
1826
|
-
}
|
|
1827
|
-
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1828
|
-
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1694
|
+
@if (errorsToDisplay()[0]; as error) {
|
|
1695
|
+
<div class="invalid-feedback d-block" [id]="errorId()" role="alert">{{ error.message }}</div>
|
|
1696
|
+
} @else if (props()?.hint; as hint) {
|
|
1697
|
+
<div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
|
|
1829
1698
|
}
|
|
1830
1699
|
`, host: {
|
|
1831
1700
|
'[class]': 'className()',
|
|
@@ -1873,9 +1742,9 @@ const BsField = {
|
|
|
1873
1742
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1874
1743
|
*/
|
|
1875
1744
|
function buttonFieldMapper(fieldDef) {
|
|
1876
|
-
|
|
1877
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
1745
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
1878
1746
|
return computed(() => {
|
|
1747
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
1879
1748
|
const inputs = {
|
|
1880
1749
|
...baseInputs,
|
|
1881
1750
|
};
|
|
@@ -1913,20 +1782,21 @@ function buttonFieldMapper(fieldDef) {
|
|
|
1913
1782
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1914
1783
|
*/
|
|
1915
1784
|
function submitButtonFieldMapper(fieldDef) {
|
|
1916
|
-
|
|
1917
|
-
const
|
|
1918
|
-
|
|
1919
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
1920
|
-
// Use button-logic-resolver to compute disabled state
|
|
1785
|
+
const rootFormRegistry = inject(RootFormRegistryService);
|
|
1786
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
1787
|
+
const formOptions = inject(FORM_OPTIONS);
|
|
1921
1788
|
const fieldWithLogic = fieldDef;
|
|
1922
|
-
const disabledSignal = resolveSubmitButtonDisabled({
|
|
1923
|
-
form: fieldSignalContext.form,
|
|
1924
|
-
formOptions: fieldSignalContext.formOptions,
|
|
1925
|
-
fieldLogic: fieldWithLogic.logic,
|
|
1926
|
-
explicitlyDisabled: fieldDef.disabled,
|
|
1927
|
-
});
|
|
1928
|
-
// Return computed signal - evaluates disabledSignal inside for reactivity
|
|
1929
1789
|
return computed(() => {
|
|
1790
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
1791
|
+
// Use rootFormRegistry instead of fieldSignalContext.form because when the submit button
|
|
1792
|
+
// is inside a group/array, fieldSignalContext.form points to the nested form tree,
|
|
1793
|
+
// not the root form. We need root form validity for submit button disabled state (#157).
|
|
1794
|
+
const disabledSignal = resolveSubmitButtonDisabled({
|
|
1795
|
+
form: rootFormRegistry.getRootForm(),
|
|
1796
|
+
formOptions: formOptions(),
|
|
1797
|
+
fieldLogic: fieldWithLogic.logic,
|
|
1798
|
+
explicitlyDisabled: fieldDef.disabled,
|
|
1799
|
+
});
|
|
1930
1800
|
const inputs = {
|
|
1931
1801
|
...baseInputs,
|
|
1932
1802
|
// No event - native form submit handles it via form's onNativeSubmit
|
|
@@ -1953,21 +1823,19 @@ function submitButtonFieldMapper(fieldDef) {
|
|
|
1953
1823
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1954
1824
|
*/
|
|
1955
1825
|
function nextButtonFieldMapper(fieldDef) {
|
|
1956
|
-
// Inject field signal context to access form state and options
|
|
1957
1826
|
const fieldSignalContext = inject(FIELD_SIGNAL_CONTEXT);
|
|
1958
|
-
|
|
1959
|
-
const
|
|
1960
|
-
// Use button-logic-resolver to compute disabled state
|
|
1827
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
1828
|
+
const formOptions = inject(FORM_OPTIONS);
|
|
1961
1829
|
const fieldWithLogic = fieldDef;
|
|
1962
|
-
const disabledSignal = resolveNextButtonDisabled({
|
|
1963
|
-
form: fieldSignalContext.form,
|
|
1964
|
-
formOptions: fieldSignalContext.formOptions,
|
|
1965
|
-
fieldLogic: fieldWithLogic.logic,
|
|
1966
|
-
explicitlyDisabled: fieldDef.disabled,
|
|
1967
|
-
currentPageValid: fieldSignalContext.currentPageValid,
|
|
1968
|
-
});
|
|
1969
|
-
// Return computed signal - evaluates disabledSignal inside for reactivity
|
|
1970
1830
|
return computed(() => {
|
|
1831
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
1832
|
+
const disabledSignal = resolveNextButtonDisabled({
|
|
1833
|
+
form: fieldSignalContext.form,
|
|
1834
|
+
formOptions: formOptions(),
|
|
1835
|
+
fieldLogic: fieldWithLogic.logic,
|
|
1836
|
+
explicitlyDisabled: fieldDef.disabled,
|
|
1837
|
+
currentPageValid: fieldSignalContext.currentPageValid,
|
|
1838
|
+
});
|
|
1971
1839
|
const inputs = {
|
|
1972
1840
|
...baseInputs,
|
|
1973
1841
|
event: NextPageEvent,
|
|
@@ -1988,9 +1856,9 @@ function nextButtonFieldMapper(fieldDef) {
|
|
|
1988
1856
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1989
1857
|
*/
|
|
1990
1858
|
function previousButtonFieldMapper(fieldDef) {
|
|
1991
|
-
|
|
1992
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
1859
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
1993
1860
|
return computed(() => {
|
|
1861
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
1994
1862
|
const inputs = {
|
|
1995
1863
|
...baseInputs,
|
|
1996
1864
|
event: PreviousPageEvent,
|
|
@@ -2016,10 +1884,9 @@ function previousButtonFieldMapper(fieldDef) {
|
|
|
2016
1884
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
2017
1885
|
*/
|
|
2018
1886
|
function addArrayItemButtonFieldMapper(fieldDef) {
|
|
2019
|
-
// Try to get array context (available when inside an array)
|
|
2020
|
-
// Use optional injection so it doesn't fail when outside an array
|
|
2021
1887
|
const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
2022
1888
|
const logger = inject(DynamicFormLogger);
|
|
1889
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
2023
1890
|
// Determine the target array key
|
|
2024
1891
|
// Priority: explicit arrayKey from fieldDef > arrayKey from context
|
|
2025
1892
|
const targetArrayKey = fieldDef.arrayKey ?? arrayContext?.arrayKey;
|
|
@@ -2027,13 +1894,12 @@ function addArrayItemButtonFieldMapper(fieldDef) {
|
|
|
2027
1894
|
logger.warn(`addArrayItem button "${fieldDef.key}" has no array context. ` +
|
|
2028
1895
|
'Either place it inside an array field, or provide an explicit arrayKey property.');
|
|
2029
1896
|
}
|
|
2030
|
-
// Build base inputs (static, from field definition)
|
|
2031
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
2032
1897
|
// Set default eventArgs for AddArrayItemEvent (arrayKey)
|
|
2033
1898
|
// User can override by providing eventArgs in field definition
|
|
2034
1899
|
const defaultEventArgs = ['$arrayKey'];
|
|
2035
1900
|
const eventArgs = 'eventArgs' in fieldDef && fieldDef.eventArgs !== undefined ? fieldDef.eventArgs : defaultEventArgs;
|
|
2036
1901
|
return computed(() => {
|
|
1902
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
2037
1903
|
// Read signal value if index is a signal (supports differential updates)
|
|
2038
1904
|
const getIndex = () => {
|
|
2039
1905
|
if (!arrayContext)
|
|
@@ -2072,10 +1938,9 @@ function addArrayItemButtonFieldMapper(fieldDef) {
|
|
|
2072
1938
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
2073
1939
|
*/
|
|
2074
1940
|
function removeArrayItemButtonFieldMapper(fieldDef) {
|
|
2075
|
-
// Try to get array context (available when inside an array)
|
|
2076
|
-
// Use optional injection so it doesn't fail when outside an array
|
|
2077
1941
|
const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
2078
1942
|
const logger = inject(DynamicFormLogger);
|
|
1943
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
2079
1944
|
// Determine the target array key
|
|
2080
1945
|
// Priority: explicit arrayKey from fieldDef > arrayKey from context
|
|
2081
1946
|
const targetArrayKey = fieldDef.arrayKey ?? arrayContext?.arrayKey;
|
|
@@ -2083,14 +1948,13 @@ function removeArrayItemButtonFieldMapper(fieldDef) {
|
|
|
2083
1948
|
logger.warn(`removeArrayItem button "${fieldDef.key}" has no array context. ` +
|
|
2084
1949
|
'Either place it inside an array field, or provide an explicit arrayKey property.');
|
|
2085
1950
|
}
|
|
2086
|
-
// Build base inputs (static, from field definition)
|
|
2087
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
2088
1951
|
// Set default eventArgs for RemoveArrayItemEvent (arrayKey, index if inside array)
|
|
2089
1952
|
// When outside array, only pass arrayKey (removes last by default)
|
|
2090
1953
|
// User can override by providing eventArgs in field definition
|
|
2091
1954
|
const defaultEventArgs = arrayContext ? ['$arrayKey', '$index'] : ['$arrayKey'];
|
|
2092
1955
|
const eventArgs = 'eventArgs' in fieldDef && fieldDef.eventArgs !== undefined ? fieldDef.eventArgs : defaultEventArgs;
|
|
2093
1956
|
return computed(() => {
|
|
1957
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
2094
1958
|
// Read signal value if index is a signal (supports differential updates)
|
|
2095
1959
|
const getIndex = () => {
|
|
2096
1960
|
if (!arrayContext)
|