@ng-forge/dynamic-forms-bootstrap 0.3.0 → 0.4.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,10 +78,11 @@ 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
|
+
@let buttonId = key() + '-button';
|
|
83
84
|
<button
|
|
84
|
-
[id]="
|
|
85
|
+
[id]="buttonId"
|
|
85
86
|
[type]="buttonType()"
|
|
86
87
|
[disabled]="disabled()"
|
|
87
88
|
[class]="buttonClasses()"
|
|
@@ -93,16 +94,17 @@ class BsButtonFieldComponent {
|
|
|
93
94
|
</button>
|
|
94
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 });
|
|
95
96
|
}
|
|
96
|
-
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: [{
|
|
97
98
|
type: Component,
|
|
98
99
|
args: [{ selector: 'df-bs-button', imports: [DynamicTextPipe, AsyncPipe], host: {
|
|
99
100
|
'[id]': '`${key()}`',
|
|
100
101
|
'[attr.data-testid]': 'key()',
|
|
101
102
|
'[class]': 'className()',
|
|
102
|
-
'[hidden]': 'hidden()',
|
|
103
|
+
'[attr.hidden]': 'hidden() || null',
|
|
103
104
|
}, template: `
|
|
105
|
+
@let buttonId = key() + '-button';
|
|
104
106
|
<button
|
|
105
|
-
[id]="
|
|
107
|
+
[id]="buttonId"
|
|
106
108
|
[type]="buttonType()"
|
|
107
109
|
[disabled]="disabled()"
|
|
108
110
|
[class]="buttonClasses()"
|
|
@@ -122,6 +124,29 @@ var bsButton_component = /*#__PURE__*/Object.freeze({
|
|
|
122
124
|
|
|
123
125
|
// Public API - component
|
|
124
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
|
+
*
|
|
131
|
+
* @param errorsToDisplay Signal containing the array of errors currently being displayed
|
|
132
|
+
* @param errorId Signal containing the base ID for error elements
|
|
133
|
+
* @param hintId Signal containing the ID for the hint element
|
|
134
|
+
* @param hasHint Function that returns true if a hint is configured
|
|
135
|
+
* @returns Signal containing the aria-describedby value (space-separated IDs) or null
|
|
136
|
+
*/
|
|
137
|
+
function createAriaDescribedBySignal(errorsToDisplay, errorId, hintId, hasHint) {
|
|
138
|
+
return computed(() => {
|
|
139
|
+
const errors = errorsToDisplay();
|
|
140
|
+
if (errors.length > 0) {
|
|
141
|
+
return errors.map((_, i) => `${errorId()}-${i}`).join(' ');
|
|
142
|
+
}
|
|
143
|
+
if (hasHint()) {
|
|
144
|
+
return hintId();
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
125
150
|
class BsCheckboxFieldComponent {
|
|
126
151
|
elementRef = inject((ElementRef));
|
|
127
152
|
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
@@ -152,7 +177,7 @@ class BsCheckboxFieldComponent {
|
|
|
152
177
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
153
178
|
// Accessibility
|
|
154
179
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
155
|
-
|
|
180
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
156
181
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
157
182
|
ariaInvalid = computed(() => {
|
|
158
183
|
const fieldState = this.field()();
|
|
@@ -161,22 +186,10 @@ class BsCheckboxFieldComponent {
|
|
|
161
186
|
ariaRequired = computed(() => {
|
|
162
187
|
return this.field()().required?.() === true ? true : null;
|
|
163
188
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
164
|
-
ariaDescribedBy =
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
const errors = this.errorsToDisplay();
|
|
170
|
-
errors.forEach((_, i) => {
|
|
171
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
172
|
-
});
|
|
173
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
174
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
175
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
176
|
-
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: `
|
|
177
|
-
@let f = field();
|
|
178
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
179
|
-
@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';
|
|
180
193
|
|
|
181
194
|
<div
|
|
182
195
|
class="form-check"
|
|
@@ -189,35 +202,32 @@ class BsCheckboxFieldComponent {
|
|
|
189
202
|
#checkboxInput
|
|
190
203
|
type="checkbox"
|
|
191
204
|
[formField]="f"
|
|
192
|
-
[id]="
|
|
205
|
+
[id]="checkboxId"
|
|
193
206
|
class="form-check-input"
|
|
194
207
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
195
208
|
[attr.tabindex]="tabIndex()"
|
|
196
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
197
|
-
[attr.aria-required]="ariaRequired"
|
|
198
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
209
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
210
|
+
[attr.aria-required]="ariaRequired()"
|
|
211
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
199
212
|
/>
|
|
200
|
-
<label [for]="
|
|
213
|
+
<label [for]="checkboxId" class="form-check-label">
|
|
201
214
|
{{ label() | dynamicText | async }}
|
|
202
215
|
</label>
|
|
203
216
|
</div>
|
|
204
217
|
|
|
205
|
-
@if (props()?.helpText; as helpText) {
|
|
206
|
-
<div class="form-text" [id]="helpTextId()" [attr.hidden]="f().hidden() || null">
|
|
207
|
-
{{ helpText | dynamicText | async }}
|
|
208
|
-
</div>
|
|
209
|
-
}
|
|
210
218
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
211
219
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
220
|
+
} @empty {
|
|
221
|
+
@if (props()?.hint; as hint) {
|
|
222
|
+
<div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
|
|
223
|
+
}
|
|
212
224
|
}
|
|
213
225
|
`, 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 });
|
|
214
226
|
}
|
|
215
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
227
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsCheckboxFieldComponent, decorators: [{
|
|
216
228
|
type: Component,
|
|
217
229
|
args: [{ selector: 'df-bs-checkbox', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
218
|
-
@let f = field();
|
|
219
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
220
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
230
|
+
@let f = field(); @let checkboxId = key() + '-checkbox';
|
|
221
231
|
|
|
222
232
|
<div
|
|
223
233
|
class="form-check"
|
|
@@ -230,26 +240,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
230
240
|
#checkboxInput
|
|
231
241
|
type="checkbox"
|
|
232
242
|
[formField]="f"
|
|
233
|
-
[id]="
|
|
243
|
+
[id]="checkboxId"
|
|
234
244
|
class="form-check-input"
|
|
235
245
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
236
246
|
[attr.tabindex]="tabIndex()"
|
|
237
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
238
|
-
[attr.aria-required]="ariaRequired"
|
|
239
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
247
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
248
|
+
[attr.aria-required]="ariaRequired()"
|
|
249
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
240
250
|
/>
|
|
241
|
-
<label [for]="
|
|
251
|
+
<label [for]="checkboxId" class="form-check-label">
|
|
242
252
|
{{ label() | dynamicText | async }}
|
|
243
253
|
</label>
|
|
244
254
|
</div>
|
|
245
255
|
|
|
246
|
-
@if (props()?.helpText; as helpText) {
|
|
247
|
-
<div class="form-text" [id]="helpTextId()" [attr.hidden]="f().hidden() || null">
|
|
248
|
-
{{ helpText | dynamicText | async }}
|
|
249
|
-
</div>
|
|
250
|
-
}
|
|
251
256
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
252
257
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
258
|
+
} @empty {
|
|
259
|
+
@if (props()?.hint; as hint) {
|
|
260
|
+
<div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
|
|
261
|
+
}
|
|
253
262
|
}
|
|
254
263
|
`, host: {
|
|
255
264
|
'[class]': 'className()',
|
|
@@ -299,10 +308,10 @@ class InputConstraintsDirective {
|
|
|
299
308
|
nativeElement.removeAttribute('step');
|
|
300
309
|
}
|
|
301
310
|
});
|
|
302
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0
|
|
303
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0
|
|
311
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: InputConstraintsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
312
|
+
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
313
|
}
|
|
305
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
314
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: InputConstraintsDirective, decorators: [{
|
|
306
315
|
type: Directive,
|
|
307
316
|
args: [{
|
|
308
317
|
selector: '[dfBsInputConstraints]',
|
|
@@ -342,7 +351,7 @@ class BsDatepickerFieldComponent {
|
|
|
342
351
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
343
352
|
// Accessibility
|
|
344
353
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
345
|
-
|
|
354
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
346
355
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
347
356
|
ariaInvalid = computed(() => {
|
|
348
357
|
const fieldState = this.field()();
|
|
@@ -351,36 +360,25 @@ class BsDatepickerFieldComponent {
|
|
|
351
360
|
ariaRequired = computed(() => {
|
|
352
361
|
return this.field()().required?.() === true ? true : null;
|
|
353
362
|
}, ...(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();
|
|
363
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
364
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsDatepickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
365
|
+
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: `
|
|
366
|
+
@let f = field(); @let p = props(); @let inputId = key() + '-input';
|
|
369
367
|
@if (p?.floatingLabel) {
|
|
370
368
|
<!-- Floating label variant -->
|
|
371
369
|
<div class="form-floating mb-3">
|
|
372
370
|
<input
|
|
373
371
|
dfBsInputConstraints
|
|
374
372
|
[formField]="f"
|
|
375
|
-
[id]="
|
|
373
|
+
[id]="inputId"
|
|
376
374
|
type="date"
|
|
377
375
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
378
376
|
[dfMin]="minAsString()"
|
|
379
377
|
[dfMax]="maxAsString()"
|
|
380
378
|
[attr.tabindex]="tabIndex()"
|
|
381
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
382
|
-
[attr.aria-required]="ariaRequired"
|
|
383
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
379
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
380
|
+
[attr.aria-required]="ariaRequired()"
|
|
381
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
384
382
|
class="form-control"
|
|
385
383
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
386
384
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -388,7 +386,7 @@ class BsDatepickerFieldComponent {
|
|
|
388
386
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
389
387
|
/>
|
|
390
388
|
@if (label()) {
|
|
391
|
-
<label [for]="
|
|
389
|
+
<label [for]="inputId">{{ label() | dynamicText | async }}</label>
|
|
392
390
|
}
|
|
393
391
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
394
392
|
<div class="valid-feedback d-block">
|
|
@@ -403,21 +401,21 @@ class BsDatepickerFieldComponent {
|
|
|
403
401
|
<!-- Standard variant -->
|
|
404
402
|
<div class="mb-3">
|
|
405
403
|
@if (label()) {
|
|
406
|
-
<label [for]="
|
|
404
|
+
<label [for]="inputId" class="form-label">{{ label() | dynamicText | async }}</label>
|
|
407
405
|
}
|
|
408
406
|
|
|
409
407
|
<input
|
|
410
408
|
dfBsInputConstraints
|
|
411
409
|
[formField]="f"
|
|
412
|
-
[id]="
|
|
410
|
+
[id]="inputId"
|
|
413
411
|
type="date"
|
|
414
412
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
415
413
|
[dfMin]="minAsString()"
|
|
416
414
|
[dfMax]="maxAsString()"
|
|
417
415
|
[attr.tabindex]="tabIndex()"
|
|
418
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
419
|
-
[attr.aria-required]="ariaRequired"
|
|
420
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
416
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
417
|
+
[attr.aria-required]="ariaRequired()"
|
|
418
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
421
419
|
class="form-control"
|
|
422
420
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
423
421
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -425,11 +423,6 @@ class BsDatepickerFieldComponent {
|
|
|
425
423
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
426
424
|
/>
|
|
427
425
|
|
|
428
|
-
@if (p?.helpText) {
|
|
429
|
-
<div class="form-text" [id]="helpTextId()">
|
|
430
|
-
{{ p?.helpText | dynamicText | async }}
|
|
431
|
-
</div>
|
|
432
|
-
}
|
|
433
426
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
434
427
|
<div class="valid-feedback d-block">
|
|
435
428
|
{{ p?.validFeedback | dynamicText | async }}
|
|
@@ -437,31 +430,34 @@ class BsDatepickerFieldComponent {
|
|
|
437
430
|
}
|
|
438
431
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
439
432
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
433
|
+
} @empty {
|
|
434
|
+
@if (p?.hint) {
|
|
435
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
436
|
+
}
|
|
440
437
|
}
|
|
441
438
|
</div>
|
|
442
439
|
}
|
|
443
440
|
`, 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
441
|
}
|
|
445
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
442
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsDatepickerFieldComponent, decorators: [{
|
|
446
443
|
type: Component,
|
|
447
444
|
args: [{ selector: 'df-bs-datepicker', imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective], template: `
|
|
448
|
-
@let f = field(); @let p = props(); @let
|
|
449
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
445
|
+
@let f = field(); @let p = props(); @let inputId = key() + '-input';
|
|
450
446
|
@if (p?.floatingLabel) {
|
|
451
447
|
<!-- Floating label variant -->
|
|
452
448
|
<div class="form-floating mb-3">
|
|
453
449
|
<input
|
|
454
450
|
dfBsInputConstraints
|
|
455
451
|
[formField]="f"
|
|
456
|
-
[id]="
|
|
452
|
+
[id]="inputId"
|
|
457
453
|
type="date"
|
|
458
454
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
459
455
|
[dfMin]="minAsString()"
|
|
460
456
|
[dfMax]="maxAsString()"
|
|
461
457
|
[attr.tabindex]="tabIndex()"
|
|
462
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
463
|
-
[attr.aria-required]="ariaRequired"
|
|
464
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
458
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
459
|
+
[attr.aria-required]="ariaRequired()"
|
|
460
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
465
461
|
class="form-control"
|
|
466
462
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
467
463
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -469,7 +465,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
469
465
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
470
466
|
/>
|
|
471
467
|
@if (label()) {
|
|
472
|
-
<label [for]="
|
|
468
|
+
<label [for]="inputId">{{ label() | dynamicText | async }}</label>
|
|
473
469
|
}
|
|
474
470
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
475
471
|
<div class="valid-feedback d-block">
|
|
@@ -484,21 +480,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
484
480
|
<!-- Standard variant -->
|
|
485
481
|
<div class="mb-3">
|
|
486
482
|
@if (label()) {
|
|
487
|
-
<label [for]="
|
|
483
|
+
<label [for]="inputId" class="form-label">{{ label() | dynamicText | async }}</label>
|
|
488
484
|
}
|
|
489
485
|
|
|
490
486
|
<input
|
|
491
487
|
dfBsInputConstraints
|
|
492
488
|
[formField]="f"
|
|
493
|
-
[id]="
|
|
489
|
+
[id]="inputId"
|
|
494
490
|
type="date"
|
|
495
491
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
496
492
|
[dfMin]="minAsString()"
|
|
497
493
|
[dfMax]="maxAsString()"
|
|
498
494
|
[attr.tabindex]="tabIndex()"
|
|
499
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
500
|
-
[attr.aria-required]="ariaRequired"
|
|
501
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
495
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
496
|
+
[attr.aria-required]="ariaRequired()"
|
|
497
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
502
498
|
class="form-control"
|
|
503
499
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
504
500
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -506,11 +502,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
506
502
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
507
503
|
/>
|
|
508
504
|
|
|
509
|
-
@if (p?.helpText) {
|
|
510
|
-
<div class="form-text" [id]="helpTextId()">
|
|
511
|
-
{{ p?.helpText | dynamicText | async }}
|
|
512
|
-
</div>
|
|
513
|
-
}
|
|
514
505
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
515
506
|
<div class="valid-feedback d-block">
|
|
516
507
|
{{ p?.validFeedback | dynamicText | async }}
|
|
@@ -518,6 +509,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
518
509
|
}
|
|
519
510
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
520
511
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
512
|
+
} @empty {
|
|
513
|
+
@if (p?.hint) {
|
|
514
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
515
|
+
}
|
|
521
516
|
}
|
|
522
517
|
</div>
|
|
523
518
|
}
|
|
@@ -613,8 +608,8 @@ class BsInputFieldComponent {
|
|
|
613
608
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
614
609
|
// Accessibility
|
|
615
610
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
616
|
-
/** Unique ID for the
|
|
617
|
-
|
|
611
|
+
/** Unique ID for the hint element, used for aria-describedby */
|
|
612
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
618
613
|
/** Base ID for error elements, used for aria-describedby */
|
|
619
614
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
620
615
|
/** aria-invalid: true when field is invalid AND touched, false otherwise */
|
|
@@ -626,46 +621,33 @@ class BsInputFieldComponent {
|
|
|
626
621
|
ariaRequired = computed(() => {
|
|
627
622
|
return this.field()().required?.() === true ? true : null;
|
|
628
623
|
}, ...(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 ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
646
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
647
|
-
@if (effectiveFloatingLabel) {
|
|
624
|
+
/** aria-describedby: links to hint and error messages for screen readers */
|
|
625
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
626
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
627
|
+
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: `
|
|
628
|
+
@let f = field(); @let p = props(); @let inputId = key() + '-input';
|
|
629
|
+
@if (effectiveFloatingLabel()) {
|
|
648
630
|
<!-- Floating label variant -->
|
|
649
631
|
<div class="form-floating mb-3">
|
|
650
632
|
<input
|
|
651
633
|
#inputRef
|
|
652
634
|
[formField]="f"
|
|
653
|
-
[id]="
|
|
635
|
+
[id]="inputId"
|
|
654
636
|
[type]="p?.type ?? 'text'"
|
|
655
637
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
656
638
|
[attr.tabindex]="tabIndex()"
|
|
657
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
658
|
-
[attr.aria-required]="ariaRequired"
|
|
659
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
639
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
640
|
+
[attr.aria-required]="ariaRequired()"
|
|
641
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
660
642
|
class="form-control"
|
|
661
|
-
[class.form-control-sm]="effectiveSize === 'sm'"
|
|
662
|
-
[class.form-control-lg]="effectiveSize === 'lg'"
|
|
643
|
+
[class.form-control-sm]="effectiveSize() === 'sm'"
|
|
644
|
+
[class.form-control-lg]="effectiveSize() === 'lg'"
|
|
663
645
|
[class.form-control-plaintext]="p?.plaintext"
|
|
664
646
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
665
647
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
666
648
|
/>
|
|
667
649
|
@if (label()) {
|
|
668
|
-
<label [for]="
|
|
650
|
+
<label [for]="inputId">{{ label() | dynamicText | async }}</label>
|
|
669
651
|
}
|
|
670
652
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
671
653
|
<div class="valid-feedback d-block">
|
|
@@ -680,30 +662,25 @@ class BsInputFieldComponent {
|
|
|
680
662
|
<!-- Standard variant -->
|
|
681
663
|
<div class="mb-3">
|
|
682
664
|
@if (label()) {
|
|
683
|
-
<label [for]="
|
|
665
|
+
<label [for]="inputId" class="form-label">{{ label() | dynamicText | async }}</label>
|
|
684
666
|
}
|
|
685
667
|
<input
|
|
686
668
|
#inputRef
|
|
687
669
|
[formField]="f"
|
|
688
|
-
[id]="
|
|
670
|
+
[id]="inputId"
|
|
689
671
|
[type]="p?.type ?? 'text'"
|
|
690
672
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
691
673
|
[attr.tabindex]="tabIndex()"
|
|
692
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
693
|
-
[attr.aria-required]="ariaRequired"
|
|
694
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
674
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
675
|
+
[attr.aria-required]="ariaRequired()"
|
|
676
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
695
677
|
class="form-control"
|
|
696
|
-
[class.form-control-sm]="effectiveSize === 'sm'"
|
|
697
|
-
[class.form-control-lg]="effectiveSize === 'lg'"
|
|
678
|
+
[class.form-control-sm]="effectiveSize() === 'sm'"
|
|
679
|
+
[class.form-control-lg]="effectiveSize() === 'lg'"
|
|
698
680
|
[class.form-control-plaintext]="p?.plaintext"
|
|
699
681
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
700
682
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
701
683
|
/>
|
|
702
|
-
@if (p?.helpText) {
|
|
703
|
-
<div class="form-text" [id]="helpTextId()">
|
|
704
|
-
{{ p?.helpText | dynamicText | async }}
|
|
705
|
-
</div>
|
|
706
|
-
}
|
|
707
684
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
708
685
|
<div class="valid-feedback d-block">
|
|
709
686
|
{{ p?.validFeedback | dynamicText | async }}
|
|
@@ -711,40 +688,41 @@ class BsInputFieldComponent {
|
|
|
711
688
|
}
|
|
712
689
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
713
690
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
691
|
+
} @empty {
|
|
692
|
+
@if (p?.hint) {
|
|
693
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
694
|
+
}
|
|
714
695
|
}
|
|
715
696
|
</div>
|
|
716
697
|
}
|
|
717
698
|
`, 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 });
|
|
718
699
|
}
|
|
719
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
700
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsInputFieldComponent, decorators: [{
|
|
720
701
|
type: Component,
|
|
721
702
|
args: [{ selector: 'df-bs-input', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
722
|
-
@let f = field(); @let p = props(); @let
|
|
723
|
-
@
|
|
724
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
725
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
726
|
-
@if (effectiveFloatingLabel) {
|
|
703
|
+
@let f = field(); @let p = props(); @let inputId = key() + '-input';
|
|
704
|
+
@if (effectiveFloatingLabel()) {
|
|
727
705
|
<!-- Floating label variant -->
|
|
728
706
|
<div class="form-floating mb-3">
|
|
729
707
|
<input
|
|
730
708
|
#inputRef
|
|
731
709
|
[formField]="f"
|
|
732
|
-
[id]="
|
|
710
|
+
[id]="inputId"
|
|
733
711
|
[type]="p?.type ?? 'text'"
|
|
734
712
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
735
713
|
[attr.tabindex]="tabIndex()"
|
|
736
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
737
|
-
[attr.aria-required]="ariaRequired"
|
|
738
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
714
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
715
|
+
[attr.aria-required]="ariaRequired()"
|
|
716
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
739
717
|
class="form-control"
|
|
740
|
-
[class.form-control-sm]="effectiveSize === 'sm'"
|
|
741
|
-
[class.form-control-lg]="effectiveSize === 'lg'"
|
|
718
|
+
[class.form-control-sm]="effectiveSize() === 'sm'"
|
|
719
|
+
[class.form-control-lg]="effectiveSize() === 'lg'"
|
|
742
720
|
[class.form-control-plaintext]="p?.plaintext"
|
|
743
721
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
744
722
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
745
723
|
/>
|
|
746
724
|
@if (label()) {
|
|
747
|
-
<label [for]="
|
|
725
|
+
<label [for]="inputId">{{ label() | dynamicText | async }}</label>
|
|
748
726
|
}
|
|
749
727
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
750
728
|
<div class="valid-feedback d-block">
|
|
@@ -759,30 +737,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
759
737
|
<!-- Standard variant -->
|
|
760
738
|
<div class="mb-3">
|
|
761
739
|
@if (label()) {
|
|
762
|
-
<label [for]="
|
|
740
|
+
<label [for]="inputId" class="form-label">{{ label() | dynamicText | async }}</label>
|
|
763
741
|
}
|
|
764
742
|
<input
|
|
765
743
|
#inputRef
|
|
766
744
|
[formField]="f"
|
|
767
|
-
[id]="
|
|
745
|
+
[id]="inputId"
|
|
768
746
|
[type]="p?.type ?? 'text'"
|
|
769
747
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
770
748
|
[attr.tabindex]="tabIndex()"
|
|
771
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
772
|
-
[attr.aria-required]="ariaRequired"
|
|
773
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
749
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
750
|
+
[attr.aria-required]="ariaRequired()"
|
|
751
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
774
752
|
class="form-control"
|
|
775
|
-
[class.form-control-sm]="effectiveSize === 'sm'"
|
|
776
|
-
[class.form-control-lg]="effectiveSize === 'lg'"
|
|
753
|
+
[class.form-control-sm]="effectiveSize() === 'sm'"
|
|
754
|
+
[class.form-control-lg]="effectiveSize() === 'lg'"
|
|
777
755
|
[class.form-control-plaintext]="p?.plaintext"
|
|
778
756
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
779
757
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
780
758
|
/>
|
|
781
|
-
@if (p?.helpText) {
|
|
782
|
-
<div class="form-text" [id]="helpTextId()">
|
|
783
|
-
{{ p?.helpText | dynamicText | async }}
|
|
784
|
-
</div>
|
|
785
|
-
}
|
|
786
759
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
787
760
|
<div class="valid-feedback d-block">
|
|
788
761
|
{{ p?.validFeedback | dynamicText | async }}
|
|
@@ -790,6 +763,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
790
763
|
}
|
|
791
764
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
792
765
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
766
|
+
} @empty {
|
|
767
|
+
@if (p?.hint) {
|
|
768
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
769
|
+
}
|
|
793
770
|
}
|
|
794
771
|
</div>
|
|
795
772
|
}
|
|
@@ -822,6 +799,14 @@ class BsMultiCheckboxFieldComponent {
|
|
|
822
799
|
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
823
800
|
showErrors = shouldShowErrors(this.field);
|
|
824
801
|
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : []));
|
|
802
|
+
/** Computed map of checked option values for O(1) lookup in template */
|
|
803
|
+
checkedValuesMap = computed(() => {
|
|
804
|
+
const map = {};
|
|
805
|
+
for (const opt of this.valueViewModel()) {
|
|
806
|
+
map[String(opt.value)] = true;
|
|
807
|
+
}
|
|
808
|
+
return map;
|
|
809
|
+
}, ...(ngDevMode ? [{ debugName: "checkedValuesMap" }] : []));
|
|
825
810
|
valueViewModel = linkedSignal(() => {
|
|
826
811
|
const currentValues = this.field()().value();
|
|
827
812
|
return this.options().filter((option) => currentValues.includes(option.value));
|
|
@@ -843,23 +828,23 @@ class BsMultiCheckboxFieldComponent {
|
|
|
843
828
|
}
|
|
844
829
|
});
|
|
845
830
|
}
|
|
846
|
-
onCheckboxChange(option,
|
|
831
|
+
onCheckboxChange(option, event) {
|
|
832
|
+
const checked = event.target.checked;
|
|
847
833
|
this.valueViewModel.update((currentOptions) => {
|
|
848
834
|
if (checked) {
|
|
849
|
-
return currentOptions.some((opt) => opt.value === option.value)
|
|
835
|
+
return currentOptions.some((opt) => opt.value === option.value)
|
|
836
|
+
? currentOptions
|
|
837
|
+
: [...currentOptions, option];
|
|
850
838
|
}
|
|
851
839
|
else {
|
|
852
840
|
return currentOptions.filter((opt) => opt.value !== option.value);
|
|
853
841
|
}
|
|
854
842
|
});
|
|
855
843
|
}
|
|
856
|
-
isChecked(option) {
|
|
857
|
-
return this.valueViewModel().some((opt) => opt.value === option.value);
|
|
858
|
-
}
|
|
859
844
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
860
845
|
// Accessibility
|
|
861
846
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
862
|
-
|
|
847
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
863
848
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
864
849
|
ariaInvalid = computed(() => {
|
|
865
850
|
const fieldState = this.field()();
|
|
@@ -868,22 +853,11 @@ class BsMultiCheckboxFieldComponent {
|
|
|
868
853
|
ariaRequired = computed(() => {
|
|
869
854
|
return this.field()().required?.() === true ? true : null;
|
|
870
855
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
871
|
-
ariaDescribedBy =
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
ids.push(this.helpTextId());
|
|
875
|
-
}
|
|
876
|
-
const errors = this.errorsToDisplay();
|
|
877
|
-
errors.forEach((_, i) => {
|
|
878
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
879
|
-
});
|
|
880
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
881
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
882
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
883
|
-
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: `
|
|
856
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
857
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
858
|
+
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: `
|
|
884
859
|
@let f = field();
|
|
885
|
-
@let
|
|
886
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
860
|
+
@let checked = checkedValuesMap();
|
|
887
861
|
@if (label(); as label) {
|
|
888
862
|
<div class="form-label">{{ label | dynamicText | async }}</div>
|
|
889
863
|
}
|
|
@@ -899,15 +873,15 @@ class BsMultiCheckboxFieldComponent {
|
|
|
899
873
|
<input
|
|
900
874
|
type="checkbox"
|
|
901
875
|
[id]="key() + '_' + i"
|
|
902
|
-
[checked]="
|
|
876
|
+
[checked]="checked['' + option.value]"
|
|
903
877
|
[disabled]="f().disabled() || option.disabled"
|
|
904
|
-
(change)="onCheckboxChange(option, $
|
|
878
|
+
(change)="onCheckboxChange(option, $event)"
|
|
905
879
|
class="form-check-input"
|
|
906
880
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
907
881
|
[attr.tabindex]="tabIndex()"
|
|
908
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
909
|
-
[attr.aria-required]="ariaRequired"
|
|
910
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
882
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
883
|
+
[attr.aria-required]="ariaRequired()"
|
|
884
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
911
885
|
/>
|
|
912
886
|
<label [for]="key() + '_' + i" class="form-check-label">
|
|
913
887
|
{{ option.label | dynamicText | async }}
|
|
@@ -916,22 +890,20 @@ class BsMultiCheckboxFieldComponent {
|
|
|
916
890
|
}
|
|
917
891
|
</div>
|
|
918
892
|
|
|
919
|
-
@if (props()?.helpText; as helpText) {
|
|
920
|
-
<div class="form-text" [id]="helpTextId()">
|
|
921
|
-
{{ helpText | dynamicText | async }}
|
|
922
|
-
</div>
|
|
923
|
-
}
|
|
924
893
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
925
894
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
895
|
+
} @empty {
|
|
896
|
+
@if (props()?.hint; as hint) {
|
|
897
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
898
|
+
}
|
|
926
899
|
}
|
|
927
900
|
`, 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 });
|
|
928
901
|
}
|
|
929
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
902
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsMultiCheckboxFieldComponent, decorators: [{
|
|
930
903
|
type: Component,
|
|
931
904
|
args: [{ selector: 'df-bs-multi-checkbox', imports: [DynamicTextPipe, AsyncPipe], template: `
|
|
932
905
|
@let f = field();
|
|
933
|
-
@let
|
|
934
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
906
|
+
@let checked = checkedValuesMap();
|
|
935
907
|
@if (label(); as label) {
|
|
936
908
|
<div class="form-label">{{ label | dynamicText | async }}</div>
|
|
937
909
|
}
|
|
@@ -947,15 +919,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
947
919
|
<input
|
|
948
920
|
type="checkbox"
|
|
949
921
|
[id]="key() + '_' + i"
|
|
950
|
-
[checked]="
|
|
922
|
+
[checked]="checked['' + option.value]"
|
|
951
923
|
[disabled]="f().disabled() || option.disabled"
|
|
952
|
-
(change)="onCheckboxChange(option, $
|
|
924
|
+
(change)="onCheckboxChange(option, $event)"
|
|
953
925
|
class="form-check-input"
|
|
954
926
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
955
927
|
[attr.tabindex]="tabIndex()"
|
|
956
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
957
|
-
[attr.aria-required]="ariaRequired"
|
|
958
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
928
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
929
|
+
[attr.aria-required]="ariaRequired()"
|
|
930
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
959
931
|
/>
|
|
960
932
|
<label [for]="key() + '_' + i" class="form-check-label">
|
|
961
933
|
{{ option.label | dynamicText | async }}
|
|
@@ -964,13 +936,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
964
936
|
}
|
|
965
937
|
</div>
|
|
966
938
|
|
|
967
|
-
@if (props()?.helpText; as helpText) {
|
|
968
|
-
<div class="form-text" [id]="helpTextId()">
|
|
969
|
-
{{ helpText | dynamicText | async }}
|
|
970
|
-
</div>
|
|
971
|
-
}
|
|
972
939
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
973
940
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
941
|
+
} @empty {
|
|
942
|
+
@if (props()?.hint; as hint) {
|
|
943
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
944
|
+
}
|
|
974
945
|
}
|
|
975
946
|
`, host: {
|
|
976
947
|
'[class]': 'className() || ""',
|
|
@@ -1011,10 +982,9 @@ class BsRadioGroupComponent {
|
|
|
1011
982
|
this.value.set(newValue);
|
|
1012
983
|
}
|
|
1013
984
|
}
|
|
1014
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0
|
|
1015
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0
|
|
985
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsRadioGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
986
|
+
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: `
|
|
1016
987
|
@let props = properties();
|
|
1017
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1018
988
|
@if (props?.buttonGroup) {
|
|
1019
989
|
<div class="btn-group" role="group" [attr.aria-label]="label() | dynamicText | async">
|
|
1020
990
|
@for (option of options(); track option.value; let i = $index) {
|
|
@@ -1025,7 +995,7 @@ class BsRadioGroupComponent {
|
|
|
1025
995
|
[checked]="value() === option.value"
|
|
1026
996
|
(change)="onRadioChange(option.value)"
|
|
1027
997
|
[disabled]="disabled() || option.disabled || false"
|
|
1028
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
998
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1029
999
|
class="btn-check"
|
|
1030
1000
|
[id]="name() + '_' + i"
|
|
1031
1001
|
autocomplete="off"
|
|
@@ -1050,7 +1020,7 @@ class BsRadioGroupComponent {
|
|
|
1050
1020
|
[checked]="value() === option.value"
|
|
1051
1021
|
(change)="onRadioChange(option.value)"
|
|
1052
1022
|
[disabled]="disabled() || option.disabled || false"
|
|
1053
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1023
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1054
1024
|
class="form-check-input"
|
|
1055
1025
|
[id]="name() + '_' + i"
|
|
1056
1026
|
/>
|
|
@@ -1062,11 +1032,10 @@ class BsRadioGroupComponent {
|
|
|
1062
1032
|
}
|
|
1063
1033
|
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1064
1034
|
}
|
|
1065
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1035
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsRadioGroupComponent, decorators: [{
|
|
1066
1036
|
type: Component,
|
|
1067
1037
|
args: [{ selector: 'df-bs-radio-group', imports: [DynamicTextPipe, AsyncPipe], template: `
|
|
1068
1038
|
@let props = properties();
|
|
1069
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1070
1039
|
@if (props?.buttonGroup) {
|
|
1071
1040
|
<div class="btn-group" role="group" [attr.aria-label]="label() | dynamicText | async">
|
|
1072
1041
|
@for (option of options(); track option.value; let i = $index) {
|
|
@@ -1077,7 +1046,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1077
1046
|
[checked]="value() === option.value"
|
|
1078
1047
|
(change)="onRadioChange(option.value)"
|
|
1079
1048
|
[disabled]="disabled() || option.disabled || false"
|
|
1080
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1049
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1081
1050
|
class="btn-check"
|
|
1082
1051
|
[id]="name() + '_' + i"
|
|
1083
1052
|
autocomplete="off"
|
|
@@ -1102,7 +1071,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1102
1071
|
[checked]="value() === option.value"
|
|
1103
1072
|
(change)="onRadioChange(option.value)"
|
|
1104
1073
|
[disabled]="disabled() || option.disabled || false"
|
|
1105
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1074
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1106
1075
|
class="form-check-input"
|
|
1107
1076
|
[id]="name() + '_' + i"
|
|
1108
1077
|
/>
|
|
@@ -1140,7 +1109,7 @@ class BsRadioFieldComponent {
|
|
|
1140
1109
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1141
1110
|
// Accessibility
|
|
1142
1111
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1143
|
-
|
|
1112
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1144
1113
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1145
1114
|
ariaInvalid = computed(() => {
|
|
1146
1115
|
const fieldState = this.field()();
|
|
@@ -1149,21 +1118,10 @@ class BsRadioFieldComponent {
|
|
|
1149
1118
|
ariaRequired = computed(() => {
|
|
1150
1119
|
return this.field()().required?.() === true ? true : null;
|
|
1151
1120
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1152
|
-
ariaDescribedBy =
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
ids.push(this.helpTextId());
|
|
1156
|
-
}
|
|
1157
|
-
const errors = this.errorsToDisplay();
|
|
1158
|
-
errors.forEach((_, i) => {
|
|
1159
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1160
|
-
});
|
|
1161
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1162
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1163
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1164
|
-
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: `
|
|
1121
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1122
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1123
|
+
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: `
|
|
1165
1124
|
@let f = field();
|
|
1166
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1167
1125
|
|
|
1168
1126
|
<div class="mb-3">
|
|
1169
1127
|
@if (label(); as label) {
|
|
@@ -1171,27 +1129,27 @@ class BsRadioFieldComponent {
|
|
|
1171
1129
|
}
|
|
1172
1130
|
|
|
1173
1131
|
<df-bs-radio-group
|
|
1174
|
-
[formField]="
|
|
1132
|
+
[formField]="f"
|
|
1175
1133
|
[label]="label()"
|
|
1176
1134
|
[options]="options()"
|
|
1177
1135
|
[properties]="props()"
|
|
1178
|
-
[ariaDescribedBy]="ariaDescribedBy"
|
|
1136
|
+
[ariaDescribedBy]="ariaDescribedBy()"
|
|
1179
1137
|
/>
|
|
1180
1138
|
|
|
1181
|
-
@if (props()?.helpText; as helpText) {
|
|
1182
|
-
<div class="form-text" [id]="helpTextId()">{{ helpText | dynamicText | async }}</div>
|
|
1183
|
-
}
|
|
1184
1139
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1185
1140
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1141
|
+
} @empty {
|
|
1142
|
+
@if (props()?.hint; as hint) {
|
|
1143
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1144
|
+
}
|
|
1186
1145
|
}
|
|
1187
1146
|
</div>
|
|
1188
1147
|
`, 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 });
|
|
1189
1148
|
}
|
|
1190
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1149
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsRadioFieldComponent, decorators: [{
|
|
1191
1150
|
type: Component,
|
|
1192
1151
|
args: [{ selector: 'df-bs-radio', imports: [BsRadioGroupComponent, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1193
1152
|
@let f = field();
|
|
1194
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1195
1153
|
|
|
1196
1154
|
<div class="mb-3">
|
|
1197
1155
|
@if (label(); as label) {
|
|
@@ -1199,18 +1157,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1199
1157
|
}
|
|
1200
1158
|
|
|
1201
1159
|
<df-bs-radio-group
|
|
1202
|
-
[formField]="
|
|
1160
|
+
[formField]="f"
|
|
1203
1161
|
[label]="label()"
|
|
1204
1162
|
[options]="options()"
|
|
1205
1163
|
[properties]="props()"
|
|
1206
|
-
[ariaDescribedBy]="ariaDescribedBy"
|
|
1164
|
+
[ariaDescribedBy]="ariaDescribedBy()"
|
|
1207
1165
|
/>
|
|
1208
1166
|
|
|
1209
|
-
@if (props()?.helpText; as helpText) {
|
|
1210
|
-
<div class="form-text" [id]="helpTextId()">{{ helpText | dynamicText | async }}</div>
|
|
1211
|
-
}
|
|
1212
1167
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1213
1168
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1169
|
+
} @empty {
|
|
1170
|
+
@if (props()?.hint; as hint) {
|
|
1171
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1172
|
+
}
|
|
1214
1173
|
}
|
|
1215
1174
|
</div>
|
|
1216
1175
|
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
@@ -1256,7 +1215,7 @@ class BsSelectFieldComponent {
|
|
|
1256
1215
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1257
1216
|
// Accessibility
|
|
1258
1217
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1259
|
-
|
|
1218
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1260
1219
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1261
1220
|
ariaInvalid = computed(() => {
|
|
1262
1221
|
const fieldState = this.field()();
|
|
@@ -1265,39 +1224,27 @@ class BsSelectFieldComponent {
|
|
|
1265
1224
|
ariaRequired = computed(() => {
|
|
1266
1225
|
return this.field()().required?.() === true ? true : null;
|
|
1267
1226
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1268
|
-
ariaDescribedBy =
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1273
|
-
const errors = this.errorsToDisplay();
|
|
1274
|
-
errors.forEach((_, i) => {
|
|
1275
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1276
|
-
});
|
|
1277
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1278
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1279
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1280
|
-
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: `
|
|
1281
|
-
@let f = field();
|
|
1282
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1283
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1227
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1228
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1229
|
+
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: `
|
|
1230
|
+
@let f = field(); @let selectId = key() + '-select';
|
|
1284
1231
|
|
|
1285
1232
|
<div class="mb-3">
|
|
1286
1233
|
@if (label(); as label) {
|
|
1287
|
-
<label [for]="
|
|
1234
|
+
<label [for]="selectId" class="form-label">{{ label | dynamicText | async }}</label>
|
|
1288
1235
|
}
|
|
1289
1236
|
<select
|
|
1290
1237
|
[formField]="f"
|
|
1291
|
-
[id]="
|
|
1238
|
+
[id]="selectId"
|
|
1292
1239
|
class="form-select"
|
|
1293
1240
|
[class.form-select-sm]="props()?.size === 'sm'"
|
|
1294
1241
|
[class.form-select-lg]="props()?.size === 'lg'"
|
|
1295
1242
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
1296
1243
|
[multiple]="props()?.multiple || false"
|
|
1297
1244
|
[size]="props()?.htmlSize"
|
|
1298
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1299
|
-
[attr.aria-required]="ariaRequired"
|
|
1300
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1245
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1246
|
+
[attr.aria-required]="ariaRequired()"
|
|
1247
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1301
1248
|
>
|
|
1302
1249
|
@if (placeholder(); as placeholder) {
|
|
1303
1250
|
<option value="" disabled [selected]="!f().value()">{{ placeholder | dynamicText | async }}</option>
|
|
@@ -1309,38 +1256,37 @@ class BsSelectFieldComponent {
|
|
|
1309
1256
|
}
|
|
1310
1257
|
</select>
|
|
1311
1258
|
|
|
1312
|
-
@if (props()?.helpText; as helpText) {
|
|
1313
|
-
<div class="form-text" [id]="helpTextId()">{{ helpText | dynamicText | async }}</div>
|
|
1314
|
-
}
|
|
1315
1259
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1316
1260
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1261
|
+
} @empty {
|
|
1262
|
+
@if (props()?.hint; as hint) {
|
|
1263
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1264
|
+
}
|
|
1317
1265
|
}
|
|
1318
1266
|
</div>
|
|
1319
1267
|
`, 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 });
|
|
1320
1268
|
}
|
|
1321
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1269
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsSelectFieldComponent, decorators: [{
|
|
1322
1270
|
type: Component,
|
|
1323
1271
|
args: [{ selector: 'df-bs-select', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1324
|
-
@let f = field();
|
|
1325
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1326
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1272
|
+
@let f = field(); @let selectId = key() + '-select';
|
|
1327
1273
|
|
|
1328
1274
|
<div class="mb-3">
|
|
1329
1275
|
@if (label(); as label) {
|
|
1330
|
-
<label [for]="
|
|
1276
|
+
<label [for]="selectId" class="form-label">{{ label | dynamicText | async }}</label>
|
|
1331
1277
|
}
|
|
1332
1278
|
<select
|
|
1333
1279
|
[formField]="f"
|
|
1334
|
-
[id]="
|
|
1280
|
+
[id]="selectId"
|
|
1335
1281
|
class="form-select"
|
|
1336
1282
|
[class.form-select-sm]="props()?.size === 'sm'"
|
|
1337
1283
|
[class.form-select-lg]="props()?.size === 'lg'"
|
|
1338
1284
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
1339
1285
|
[multiple]="props()?.multiple || false"
|
|
1340
1286
|
[size]="props()?.htmlSize"
|
|
1341
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1342
|
-
[attr.aria-required]="ariaRequired"
|
|
1343
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1287
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1288
|
+
[attr.aria-required]="ariaRequired()"
|
|
1289
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1344
1290
|
>
|
|
1345
1291
|
@if (placeholder(); as placeholder) {
|
|
1346
1292
|
<option value="" disabled [selected]="!f().value()">{{ placeholder | dynamicText | async }}</option>
|
|
@@ -1352,11 +1298,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1352
1298
|
}
|
|
1353
1299
|
</select>
|
|
1354
1300
|
|
|
1355
|
-
@if (props()?.helpText; as helpText) {
|
|
1356
|
-
<div class="form-text" [id]="helpTextId()">{{ helpText | dynamicText | async }}</div>
|
|
1357
|
-
}
|
|
1358
1301
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1359
1302
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1303
|
+
} @empty {
|
|
1304
|
+
@if (props()?.hint; as hint) {
|
|
1305
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1306
|
+
}
|
|
1360
1307
|
}
|
|
1361
1308
|
</div>
|
|
1362
1309
|
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
@@ -1396,7 +1343,7 @@ class BsSliderFieldComponent {
|
|
|
1396
1343
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1397
1344
|
// Accessibility
|
|
1398
1345
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1399
|
-
|
|
1346
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1400
1347
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1401
1348
|
ariaInvalid = computed(() => {
|
|
1402
1349
|
const fieldState = this.field()();
|
|
@@ -1405,26 +1352,14 @@ class BsSliderFieldComponent {
|
|
|
1405
1352
|
ariaRequired = computed(() => {
|
|
1406
1353
|
return this.field()().required?.() === true ? true : null;
|
|
1407
1354
|
}, ...(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();
|
|
1422
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1423
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1355
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1356
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1357
|
+
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: `
|
|
1358
|
+
@let f = field(); @let inputId = key() + '-input';
|
|
1424
1359
|
|
|
1425
1360
|
<div class="mb-3">
|
|
1426
1361
|
@if (label(); as label) {
|
|
1427
|
-
<label [for]="
|
|
1362
|
+
<label [for]="inputId" class="form-label">
|
|
1428
1363
|
{{ label | dynamicText | async }}
|
|
1429
1364
|
@if (props()?.showValue) {
|
|
1430
1365
|
<span class="ms-2 badge bg-secondary"> {{ props()?.valuePrefix }}{{ f().value() }}{{ props()?.valueSuffix }} </span>
|
|
@@ -1436,38 +1371,35 @@ class BsSliderFieldComponent {
|
|
|
1436
1371
|
type="range"
|
|
1437
1372
|
dfBsInputConstraints
|
|
1438
1373
|
[formField]="f"
|
|
1439
|
-
[id]="
|
|
1374
|
+
[id]="inputId"
|
|
1440
1375
|
[dfMin]="props()?.min ?? min()"
|
|
1441
1376
|
[dfMax]="props()?.max ?? max()"
|
|
1442
1377
|
[dfStep]="props()?.step ?? step()"
|
|
1443
1378
|
[attr.tabindex]="tabIndex()"
|
|
1444
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1445
|
-
[attr.aria-required]="ariaRequired"
|
|
1446
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1379
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1380
|
+
[attr.aria-required]="ariaRequired()"
|
|
1381
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1447
1382
|
class="form-range"
|
|
1448
1383
|
/>
|
|
1449
1384
|
|
|
1450
|
-
@if (props()?.helpText; as helpText) {
|
|
1451
|
-
<div class="form-text" [id]="helpTextId()">
|
|
1452
|
-
{{ helpText | dynamicText | async }}
|
|
1453
|
-
</div>
|
|
1454
|
-
}
|
|
1455
1385
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1456
1386
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1387
|
+
} @empty {
|
|
1388
|
+
@if (props()?.hint; as hint) {
|
|
1389
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1390
|
+
}
|
|
1457
1391
|
}
|
|
1458
1392
|
</div>
|
|
1459
1393
|
`, 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 });
|
|
1460
1394
|
}
|
|
1461
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1395
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsSliderFieldComponent, decorators: [{
|
|
1462
1396
|
type: Component,
|
|
1463
1397
|
args: [{ selector: 'df-bs-slider', imports: [FormField, DynamicTextPipe, AsyncPipe, InputConstraintsDirective], template: `
|
|
1464
|
-
@let f = field();
|
|
1465
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1466
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1398
|
+
@let f = field(); @let inputId = key() + '-input';
|
|
1467
1399
|
|
|
1468
1400
|
<div class="mb-3">
|
|
1469
1401
|
@if (label(); as label) {
|
|
1470
|
-
<label [for]="
|
|
1402
|
+
<label [for]="inputId" class="form-label">
|
|
1471
1403
|
{{ label | dynamicText | async }}
|
|
1472
1404
|
@if (props()?.showValue) {
|
|
1473
1405
|
<span class="ms-2 badge bg-secondary"> {{ props()?.valuePrefix }}{{ f().value() }}{{ props()?.valueSuffix }} </span>
|
|
@@ -1479,24 +1411,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1479
1411
|
type="range"
|
|
1480
1412
|
dfBsInputConstraints
|
|
1481
1413
|
[formField]="f"
|
|
1482
|
-
[id]="
|
|
1414
|
+
[id]="inputId"
|
|
1483
1415
|
[dfMin]="props()?.min ?? min()"
|
|
1484
1416
|
[dfMax]="props()?.max ?? max()"
|
|
1485
1417
|
[dfStep]="props()?.step ?? step()"
|
|
1486
1418
|
[attr.tabindex]="tabIndex()"
|
|
1487
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1488
|
-
[attr.aria-required]="ariaRequired"
|
|
1489
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1419
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1420
|
+
[attr.aria-required]="ariaRequired()"
|
|
1421
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1490
1422
|
class="form-range"
|
|
1491
1423
|
/>
|
|
1492
1424
|
|
|
1493
|
-
@if (props()?.helpText; as helpText) {
|
|
1494
|
-
<div class="form-text" [id]="helpTextId()">
|
|
1495
|
-
{{ helpText | dynamicText | async }}
|
|
1496
|
-
</div>
|
|
1497
|
-
}
|
|
1498
1425
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1499
1426
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1427
|
+
} @empty {
|
|
1428
|
+
@if (props()?.hint; as hint) {
|
|
1429
|
+
<div class="form-text" [id]="hintId()">{{ hint | dynamicText | async }}</div>
|
|
1430
|
+
}
|
|
1500
1431
|
}
|
|
1501
1432
|
</div>
|
|
1502
1433
|
`, host: {
|
|
@@ -1533,7 +1464,7 @@ class BsTextareaFieldComponent {
|
|
|
1533
1464
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1534
1465
|
// Accessibility
|
|
1535
1466
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1536
|
-
|
|
1467
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1537
1468
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1538
1469
|
ariaInvalid = computed(() => {
|
|
1539
1470
|
const fieldState = this.field()();
|
|
@@ -1542,32 +1473,21 @@ class BsTextareaFieldComponent {
|
|
|
1542
1473
|
ariaRequired = computed(() => {
|
|
1543
1474
|
return this.field()().required?.() === true ? true : null;
|
|
1544
1475
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1545
|
-
ariaDescribedBy =
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
}
|
|
1550
|
-
const errors = this.errorsToDisplay();
|
|
1551
|
-
errors.forEach((_, i) => {
|
|
1552
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1553
|
-
});
|
|
1554
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1555
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1556
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1557
|
-
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: `
|
|
1558
|
-
@let f = field(); @let p = props(); @let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1559
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1476
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1477
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1478
|
+
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: `
|
|
1479
|
+
@let f = field(); @let p = props(); @let textareaId = key() + '-textarea';
|
|
1560
1480
|
@if (p?.floatingLabel) {
|
|
1561
1481
|
<!-- Floating label variant -->
|
|
1562
1482
|
<div class="form-floating mb-3">
|
|
1563
1483
|
<textarea
|
|
1564
1484
|
[formField]="f"
|
|
1565
|
-
[id]="
|
|
1485
|
+
[id]="textareaId"
|
|
1566
1486
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1567
1487
|
[attr.tabindex]="tabIndex()"
|
|
1568
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1569
|
-
[attr.aria-required]="ariaRequired"
|
|
1570
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1488
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1489
|
+
[attr.aria-required]="ariaRequired()"
|
|
1490
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1571
1491
|
class="form-control"
|
|
1572
1492
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
1573
1493
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -1576,7 +1496,7 @@ class BsTextareaFieldComponent {
|
|
|
1576
1496
|
></textarea>
|
|
1577
1497
|
|
|
1578
1498
|
@if (label()) {
|
|
1579
|
-
<label [for]="
|
|
1499
|
+
<label [for]="textareaId">{{ label() | dynamicText | async }}</label>
|
|
1580
1500
|
}
|
|
1581
1501
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
1582
1502
|
<div class="valid-feedback d-block">
|
|
@@ -1591,17 +1511,17 @@ class BsTextareaFieldComponent {
|
|
|
1591
1511
|
<!-- Standard variant -->
|
|
1592
1512
|
<div class="mb-3">
|
|
1593
1513
|
@if (label()) {
|
|
1594
|
-
<label [for]="
|
|
1514
|
+
<label [for]="textareaId" class="form-label">{{ label() | dynamicText | async }}</label>
|
|
1595
1515
|
}
|
|
1596
1516
|
|
|
1597
1517
|
<textarea
|
|
1598
1518
|
[formField]="f"
|
|
1599
|
-
[id]="
|
|
1519
|
+
[id]="textareaId"
|
|
1600
1520
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1601
1521
|
[attr.tabindex]="tabIndex()"
|
|
1602
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1603
|
-
[attr.aria-required]="ariaRequired"
|
|
1604
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1522
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1523
|
+
[attr.aria-required]="ariaRequired()"
|
|
1524
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1605
1525
|
class="form-control"
|
|
1606
1526
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
1607
1527
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -1609,11 +1529,6 @@ class BsTextareaFieldComponent {
|
|
|
1609
1529
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
1610
1530
|
></textarea>
|
|
1611
1531
|
|
|
1612
|
-
@if (p?.helpText) {
|
|
1613
|
-
<div class="form-text" [id]="helpTextId()">
|
|
1614
|
-
{{ p?.helpText | dynamicText | async }}
|
|
1615
|
-
</div>
|
|
1616
|
-
}
|
|
1617
1532
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
1618
1533
|
<div class="valid-feedback d-block">
|
|
1619
1534
|
{{ p?.validFeedback | dynamicText | async }}
|
|
@@ -1621,27 +1536,30 @@ class BsTextareaFieldComponent {
|
|
|
1621
1536
|
}
|
|
1622
1537
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1623
1538
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1539
|
+
} @empty {
|
|
1540
|
+
@if (p?.hint) {
|
|
1541
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
1542
|
+
}
|
|
1624
1543
|
}
|
|
1625
1544
|
</div>
|
|
1626
1545
|
}
|
|
1627
1546
|
`, 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 });
|
|
1628
1547
|
}
|
|
1629
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1548
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsTextareaFieldComponent, decorators: [{
|
|
1630
1549
|
type: Component,
|
|
1631
1550
|
args: [{ selector: 'df-bs-textarea', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1632
|
-
@let f = field(); @let p = props(); @let
|
|
1633
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1551
|
+
@let f = field(); @let p = props(); @let textareaId = key() + '-textarea';
|
|
1634
1552
|
@if (p?.floatingLabel) {
|
|
1635
1553
|
<!-- Floating label variant -->
|
|
1636
1554
|
<div class="form-floating mb-3">
|
|
1637
1555
|
<textarea
|
|
1638
1556
|
[formField]="f"
|
|
1639
|
-
[id]="
|
|
1557
|
+
[id]="textareaId"
|
|
1640
1558
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1641
1559
|
[attr.tabindex]="tabIndex()"
|
|
1642
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1643
|
-
[attr.aria-required]="ariaRequired"
|
|
1644
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1560
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1561
|
+
[attr.aria-required]="ariaRequired()"
|
|
1562
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1645
1563
|
class="form-control"
|
|
1646
1564
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
1647
1565
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -1650,7 +1568,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1650
1568
|
></textarea>
|
|
1651
1569
|
|
|
1652
1570
|
@if (label()) {
|
|
1653
|
-
<label [for]="
|
|
1571
|
+
<label [for]="textareaId">{{ label() | dynamicText | async }}</label>
|
|
1654
1572
|
}
|
|
1655
1573
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
1656
1574
|
<div class="valid-feedback d-block">
|
|
@@ -1665,17 +1583,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1665
1583
|
<!-- Standard variant -->
|
|
1666
1584
|
<div class="mb-3">
|
|
1667
1585
|
@if (label()) {
|
|
1668
|
-
<label [for]="
|
|
1586
|
+
<label [for]="textareaId" class="form-label">{{ label() | dynamicText | async }}</label>
|
|
1669
1587
|
}
|
|
1670
1588
|
|
|
1671
1589
|
<textarea
|
|
1672
1590
|
[formField]="f"
|
|
1673
|
-
[id]="
|
|
1591
|
+
[id]="textareaId"
|
|
1674
1592
|
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1675
1593
|
[attr.tabindex]="tabIndex()"
|
|
1676
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1677
|
-
[attr.aria-required]="ariaRequired"
|
|
1678
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1594
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1595
|
+
[attr.aria-required]="ariaRequired()"
|
|
1596
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1679
1597
|
class="form-control"
|
|
1680
1598
|
[class.form-control-sm]="p?.size === 'sm'"
|
|
1681
1599
|
[class.form-control-lg]="p?.size === 'lg'"
|
|
@@ -1683,11 +1601,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1683
1601
|
[class.is-valid]="f().valid() && f().touched() && p?.validFeedback"
|
|
1684
1602
|
></textarea>
|
|
1685
1603
|
|
|
1686
|
-
@if (p?.helpText) {
|
|
1687
|
-
<div class="form-text" [id]="helpTextId()">
|
|
1688
|
-
{{ p?.helpText | dynamicText | async }}
|
|
1689
|
-
</div>
|
|
1690
|
-
}
|
|
1691
1604
|
@if (p?.validFeedback && f().valid() && f().touched()) {
|
|
1692
1605
|
<div class="valid-feedback d-block">
|
|
1693
1606
|
{{ p?.validFeedback | dynamicText | async }}
|
|
@@ -1695,6 +1608,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1695
1608
|
}
|
|
1696
1609
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1697
1610
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1611
|
+
} @empty {
|
|
1612
|
+
@if (p?.hint) {
|
|
1613
|
+
<div class="form-text" [id]="hintId()">{{ p?.hint | dynamicText | async }}</div>
|
|
1614
|
+
}
|
|
1698
1615
|
}
|
|
1699
1616
|
</div>
|
|
1700
1617
|
}
|
|
@@ -1732,7 +1649,7 @@ class BsToggleFieldComponent {
|
|
|
1732
1649
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1733
1650
|
// Accessibility
|
|
1734
1651
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1735
|
-
|
|
1652
|
+
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : []));
|
|
1736
1653
|
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : []));
|
|
1737
1654
|
ariaInvalid = computed(() => {
|
|
1738
1655
|
const fieldState = this.field()();
|
|
@@ -1741,22 +1658,10 @@ class BsToggleFieldComponent {
|
|
|
1741
1658
|
ariaRequired = computed(() => {
|
|
1742
1659
|
return this.field()().required?.() === true ? true : null;
|
|
1743
1660
|
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : []));
|
|
1744
|
-
ariaDescribedBy =
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
}
|
|
1749
|
-
const errors = this.errorsToDisplay();
|
|
1750
|
-
errors.forEach((_, i) => {
|
|
1751
|
-
ids.push(`${this.errorId()}-${i}`);
|
|
1752
|
-
});
|
|
1753
|
-
return ids.length > 0 ? ids.join(' ') : null;
|
|
1754
|
-
}, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
|
|
1755
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: BsToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1756
|
-
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: `
|
|
1757
|
-
@let f = field();
|
|
1758
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1759
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1661
|
+
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1662
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1663
|
+
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: `
|
|
1664
|
+
@let f = field(); @let inputId = key() + '-input';
|
|
1760
1665
|
|
|
1761
1666
|
<div
|
|
1762
1667
|
class="form-check form-switch"
|
|
@@ -1769,35 +1674,32 @@ class BsToggleFieldComponent {
|
|
|
1769
1674
|
<input
|
|
1770
1675
|
type="checkbox"
|
|
1771
1676
|
[formField]="f"
|
|
1772
|
-
[id]="
|
|
1677
|
+
[id]="inputId"
|
|
1773
1678
|
class="form-check-input"
|
|
1774
1679
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
1775
1680
|
[attr.tabindex]="tabIndex()"
|
|
1776
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1777
|
-
[attr.aria-required]="ariaRequired"
|
|
1778
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1681
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1682
|
+
[attr.aria-required]="ariaRequired()"
|
|
1683
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1779
1684
|
/>
|
|
1780
|
-
<label [for]="
|
|
1685
|
+
<label [for]="inputId" class="form-check-label">
|
|
1781
1686
|
{{ label() | dynamicText | async }}
|
|
1782
1687
|
</label>
|
|
1783
1688
|
</div>
|
|
1784
1689
|
|
|
1785
|
-
@if (props()?.helpText; as helpText) {
|
|
1786
|
-
<div class="form-text" [id]="helpTextId()" [attr.hidden]="f().hidden() || null">
|
|
1787
|
-
{{ helpText | dynamicText | async }}
|
|
1788
|
-
</div>
|
|
1789
|
-
}
|
|
1790
1690
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1791
1691
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1692
|
+
} @empty {
|
|
1693
|
+
@if (props()?.hint; as hint) {
|
|
1694
|
+
<div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
|
|
1695
|
+
}
|
|
1792
1696
|
}
|
|
1793
1697
|
`, 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 });
|
|
1794
1698
|
}
|
|
1795
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0
|
|
1699
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BsToggleFieldComponent, decorators: [{
|
|
1796
1700
|
type: Component,
|
|
1797
1701
|
args: [{ selector: 'df-bs-toggle', imports: [FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1798
|
-
@let f = field();
|
|
1799
|
-
@let ariaInvalid = this.ariaInvalid(); @let ariaRequired = this.ariaRequired();
|
|
1800
|
-
@let ariaDescribedBy = this.ariaDescribedBy();
|
|
1702
|
+
@let f = field(); @let inputId = key() + '-input';
|
|
1801
1703
|
|
|
1802
1704
|
<div
|
|
1803
1705
|
class="form-check form-switch"
|
|
@@ -1810,26 +1712,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImpor
|
|
|
1810
1712
|
<input
|
|
1811
1713
|
type="checkbox"
|
|
1812
1714
|
[formField]="f"
|
|
1813
|
-
[id]="
|
|
1715
|
+
[id]="inputId"
|
|
1814
1716
|
class="form-check-input"
|
|
1815
1717
|
[class.is-invalid]="f().invalid() && f().touched()"
|
|
1816
1718
|
[attr.tabindex]="tabIndex()"
|
|
1817
|
-
[attr.aria-invalid]="ariaInvalid"
|
|
1818
|
-
[attr.aria-required]="ariaRequired"
|
|
1819
|
-
[attr.aria-describedby]="ariaDescribedBy"
|
|
1719
|
+
[attr.aria-invalid]="ariaInvalid()"
|
|
1720
|
+
[attr.aria-required]="ariaRequired()"
|
|
1721
|
+
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1820
1722
|
/>
|
|
1821
|
-
<label [for]="
|
|
1723
|
+
<label [for]="inputId" class="form-check-label">
|
|
1822
1724
|
{{ label() | dynamicText | async }}
|
|
1823
1725
|
</label>
|
|
1824
1726
|
</div>
|
|
1825
1727
|
|
|
1826
|
-
@if (props()?.helpText; as helpText) {
|
|
1827
|
-
<div class="form-text" [id]="helpTextId()" [attr.hidden]="f().hidden() || null">
|
|
1828
|
-
{{ helpText | dynamicText | async }}
|
|
1829
|
-
</div>
|
|
1830
|
-
}
|
|
1831
1728
|
@for (error of errorsToDisplay(); track error.kind; let i = $index) {
|
|
1832
1729
|
<div class="invalid-feedback d-block" [id]="errorId() + '-' + i" role="alert">{{ error.message }}</div>
|
|
1730
|
+
} @empty {
|
|
1731
|
+
@if (props()?.hint; as hint) {
|
|
1732
|
+
<div class="form-text" [id]="hintId()" [attr.hidden]="f().hidden() || null">{{ hint | dynamicText | async }}</div>
|
|
1733
|
+
}
|
|
1833
1734
|
}
|
|
1834
1735
|
`, host: {
|
|
1835
1736
|
'[class]': 'className()',
|
|
@@ -1877,9 +1778,9 @@ const BsField = {
|
|
|
1877
1778
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1878
1779
|
*/
|
|
1879
1780
|
function buttonFieldMapper(fieldDef) {
|
|
1880
|
-
|
|
1881
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
1781
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
1882
1782
|
return computed(() => {
|
|
1783
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
1883
1784
|
const inputs = {
|
|
1884
1785
|
...baseInputs,
|
|
1885
1786
|
};
|
|
@@ -1917,20 +1818,21 @@ function buttonFieldMapper(fieldDef) {
|
|
|
1917
1818
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1918
1819
|
*/
|
|
1919
1820
|
function submitButtonFieldMapper(fieldDef) {
|
|
1920
|
-
|
|
1921
|
-
const
|
|
1922
|
-
|
|
1923
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
1924
|
-
// Use button-logic-resolver to compute disabled state
|
|
1821
|
+
const rootFormRegistry = inject(RootFormRegistryService);
|
|
1822
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
1823
|
+
const formOptions = inject(FORM_OPTIONS);
|
|
1925
1824
|
const fieldWithLogic = fieldDef;
|
|
1926
|
-
const disabledSignal = resolveSubmitButtonDisabled({
|
|
1927
|
-
form: fieldSignalContext.form,
|
|
1928
|
-
formOptions: fieldSignalContext.formOptions,
|
|
1929
|
-
fieldLogic: fieldWithLogic.logic,
|
|
1930
|
-
explicitlyDisabled: fieldDef.disabled,
|
|
1931
|
-
});
|
|
1932
|
-
// Return computed signal - evaluates disabledSignal inside for reactivity
|
|
1933
1825
|
return computed(() => {
|
|
1826
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
1827
|
+
// Use rootFormRegistry instead of fieldSignalContext.form because when the submit button
|
|
1828
|
+
// is inside a group/array, fieldSignalContext.form points to the nested form tree,
|
|
1829
|
+
// not the root form. We need root form validity for submit button disabled state (#157).
|
|
1830
|
+
const disabledSignal = resolveSubmitButtonDisabled({
|
|
1831
|
+
form: rootFormRegistry.getRootForm(),
|
|
1832
|
+
formOptions: formOptions(),
|
|
1833
|
+
fieldLogic: fieldWithLogic.logic,
|
|
1834
|
+
explicitlyDisabled: fieldDef.disabled,
|
|
1835
|
+
});
|
|
1934
1836
|
const inputs = {
|
|
1935
1837
|
...baseInputs,
|
|
1936
1838
|
// No event - native form submit handles it via form's onNativeSubmit
|
|
@@ -1957,21 +1859,19 @@ function submitButtonFieldMapper(fieldDef) {
|
|
|
1957
1859
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1958
1860
|
*/
|
|
1959
1861
|
function nextButtonFieldMapper(fieldDef) {
|
|
1960
|
-
// Inject field signal context to access form state and options
|
|
1961
1862
|
const fieldSignalContext = inject(FIELD_SIGNAL_CONTEXT);
|
|
1962
|
-
|
|
1963
|
-
const
|
|
1964
|
-
// Use button-logic-resolver to compute disabled state
|
|
1863
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
1864
|
+
const formOptions = inject(FORM_OPTIONS);
|
|
1965
1865
|
const fieldWithLogic = fieldDef;
|
|
1966
|
-
const disabledSignal = resolveNextButtonDisabled({
|
|
1967
|
-
form: fieldSignalContext.form,
|
|
1968
|
-
formOptions: fieldSignalContext.formOptions,
|
|
1969
|
-
fieldLogic: fieldWithLogic.logic,
|
|
1970
|
-
explicitlyDisabled: fieldDef.disabled,
|
|
1971
|
-
currentPageValid: fieldSignalContext.currentPageValid,
|
|
1972
|
-
});
|
|
1973
|
-
// Return computed signal - evaluates disabledSignal inside for reactivity
|
|
1974
1866
|
return computed(() => {
|
|
1867
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
1868
|
+
const disabledSignal = resolveNextButtonDisabled({
|
|
1869
|
+
form: fieldSignalContext.form,
|
|
1870
|
+
formOptions: formOptions(),
|
|
1871
|
+
fieldLogic: fieldWithLogic.logic,
|
|
1872
|
+
explicitlyDisabled: fieldDef.disabled,
|
|
1873
|
+
currentPageValid: fieldSignalContext.currentPageValid,
|
|
1874
|
+
});
|
|
1975
1875
|
const inputs = {
|
|
1976
1876
|
...baseInputs,
|
|
1977
1877
|
event: NextPageEvent,
|
|
@@ -1992,9 +1892,9 @@ function nextButtonFieldMapper(fieldDef) {
|
|
|
1992
1892
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
1993
1893
|
*/
|
|
1994
1894
|
function previousButtonFieldMapper(fieldDef) {
|
|
1995
|
-
|
|
1996
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
1895
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
1997
1896
|
return computed(() => {
|
|
1897
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
1998
1898
|
const inputs = {
|
|
1999
1899
|
...baseInputs,
|
|
2000
1900
|
event: PreviousPageEvent,
|
|
@@ -2020,10 +1920,9 @@ function previousButtonFieldMapper(fieldDef) {
|
|
|
2020
1920
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
2021
1921
|
*/
|
|
2022
1922
|
function addArrayItemButtonFieldMapper(fieldDef) {
|
|
2023
|
-
// Try to get array context (available when inside an array)
|
|
2024
|
-
// Use optional injection so it doesn't fail when outside an array
|
|
2025
1923
|
const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
2026
1924
|
const logger = inject(DynamicFormLogger);
|
|
1925
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
2027
1926
|
// Determine the target array key
|
|
2028
1927
|
// Priority: explicit arrayKey from fieldDef > arrayKey from context
|
|
2029
1928
|
const targetArrayKey = fieldDef.arrayKey ?? arrayContext?.arrayKey;
|
|
@@ -2031,13 +1930,12 @@ function addArrayItemButtonFieldMapper(fieldDef) {
|
|
|
2031
1930
|
logger.warn(`addArrayItem button "${fieldDef.key}" has no array context. ` +
|
|
2032
1931
|
'Either place it inside an array field, or provide an explicit arrayKey property.');
|
|
2033
1932
|
}
|
|
2034
|
-
// Build base inputs (static, from field definition)
|
|
2035
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
2036
1933
|
// Set default eventArgs for AddArrayItemEvent (arrayKey)
|
|
2037
1934
|
// User can override by providing eventArgs in field definition
|
|
2038
1935
|
const defaultEventArgs = ['$arrayKey'];
|
|
2039
1936
|
const eventArgs = 'eventArgs' in fieldDef && fieldDef.eventArgs !== undefined ? fieldDef.eventArgs : defaultEventArgs;
|
|
2040
1937
|
return computed(() => {
|
|
1938
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
2041
1939
|
// Read signal value if index is a signal (supports differential updates)
|
|
2042
1940
|
const getIndex = () => {
|
|
2043
1941
|
if (!arrayContext)
|
|
@@ -2076,10 +1974,9 @@ function addArrayItemButtonFieldMapper(fieldDef) {
|
|
|
2076
1974
|
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
2077
1975
|
*/
|
|
2078
1976
|
function removeArrayItemButtonFieldMapper(fieldDef) {
|
|
2079
|
-
// Try to get array context (available when inside an array)
|
|
2080
|
-
// Use optional injection so it doesn't fail when outside an array
|
|
2081
1977
|
const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
2082
1978
|
const logger = inject(DynamicFormLogger);
|
|
1979
|
+
const defaultProps = inject(DEFAULT_PROPS);
|
|
2083
1980
|
// Determine the target array key
|
|
2084
1981
|
// Priority: explicit arrayKey from fieldDef > arrayKey from context
|
|
2085
1982
|
const targetArrayKey = fieldDef.arrayKey ?? arrayContext?.arrayKey;
|
|
@@ -2087,14 +1984,13 @@ function removeArrayItemButtonFieldMapper(fieldDef) {
|
|
|
2087
1984
|
logger.warn(`removeArrayItem button "${fieldDef.key}" has no array context. ` +
|
|
2088
1985
|
'Either place it inside an array field, or provide an explicit arrayKey property.');
|
|
2089
1986
|
}
|
|
2090
|
-
// Build base inputs (static, from field definition)
|
|
2091
|
-
const baseInputs = buildBaseInputs(fieldDef);
|
|
2092
1987
|
// Set default eventArgs for RemoveArrayItemEvent (arrayKey, index if inside array)
|
|
2093
1988
|
// When outside array, only pass arrayKey (removes last by default)
|
|
2094
1989
|
// User can override by providing eventArgs in field definition
|
|
2095
1990
|
const defaultEventArgs = arrayContext ? ['$arrayKey', '$index'] : ['$arrayKey'];
|
|
2096
1991
|
const eventArgs = 'eventArgs' in fieldDef && fieldDef.eventArgs !== undefined ? fieldDef.eventArgs : defaultEventArgs;
|
|
2097
1992
|
return computed(() => {
|
|
1993
|
+
const baseInputs = buildBaseInputs(fieldDef, defaultProps());
|
|
2098
1994
|
// Read signal value if index is a signal (supports differential updates)
|
|
2099
1995
|
const getIndex = () => {
|
|
2100
1996
|
if (!arrayContext)
|