@ng-forge/dynamic-forms-ionic 0.9.0-next.8 → 0.9.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,72 +1,27 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
import { IonButton, IonCheckbox, IonNote, IonInput, IonModal, IonDatetime, IonButtons, IonHeader, IonContent, IonToolbar, IonTitle, IonItem, IonRadioGroup, IonRadio, IonSelect, IonSelectOption, IonRange, IonTextarea, IonToggle } from '@ionic/angular/standalone';
|
|
4
|
-
import { EventBus, ARRAY_CONTEXT, resolveTokens, DynamicTextPipe, DEFAULT_PROPS, buildBaseInputs } from '@ng-forge/dynamic-forms';
|
|
2
|
+
import { input, computed, ChangeDetectionStrategy, Component, signal, inject, Injector, InjectionToken, ElementRef, DestroyRef, forwardRef, linkedSignal, model, isSignal } from '@angular/core';
|
|
3
|
+
import { IonButton, IonCheckbox, IonNote, IonInput, IonModal, IonDatetime, IonButtons, IonHeader, IonContent, IonToolbar, IonTitle, IonIcon, IonSpinner, IonItem, IonRadioGroup, IonRadio, IonSelect, IonSelectOption, IonRange, IonTextarea, IonToggle } from '@ionic/angular/standalone';
|
|
5
4
|
import { AsyncPipe } from '@angular/common';
|
|
5
|
+
import { DynamicTextPipe, runPresetAction, resolveDynamicValue, DfAddonSlot, FIELD_SIGNAL_CONTEXT, DynamicFormLogger, DEFAULT_PROPS, ARRAY_CONTEXT, buildBaseInputs, DynamicFormError, ADDON_KIND_DEFINITIONS } from '@ng-forge/dynamic-forms';
|
|
6
|
+
import * as i1 from '@ng-forge/dynamic-forms/integration';
|
|
7
|
+
import { injectNgForgeAction, NgForgeActionHost, injectNgForgeField, NgForgeControl, NgForgeFieldHost, injectNgForgeAddonAction, NgForgeAddonAction, injectNgForgeAddons, ADDON_PRESET_HANDLER, NgForgeAddons, isEqual, NgForgeHostControl, valueFieldMapper, optionsFieldMapper, checkboxFieldMapper, submitButtonFieldMapper, nextButtonFieldMapper, previousButtonFieldMapper, addArrayItemButtonMapper, prependArrayItemButtonMapper, insertArrayItemButtonMapper, removeArrayItemButtonMapper, popArrayItemButtonMapper, shiftArrayItemButtonMapper, datepickerFieldMapper } from '@ng-forge/dynamic-forms/integration';
|
|
6
8
|
import { FormField } from '@angular/forms/signals';
|
|
7
|
-
import { createResolvedErrorsSignal, shouldShowErrors, setupMetaTracking, isEqual, valueFieldMapper, optionsFieldMapper, checkboxFieldMapper, submitButtonFieldMapper, nextButtonFieldMapper, previousButtonFieldMapper, addArrayItemButtonMapper, prependArrayItemButtonMapper, insertArrayItemButtonMapper, removeArrayItemButtonMapper, popArrayItemButtonMapper, shiftArrayItemButtonMapper, datepickerFieldMapper } from '@ng-forge/dynamic-forms/integration';
|
|
8
9
|
import { format } from 'date-fns';
|
|
9
10
|
import { explicitEffect } from 'ngxtension/explicit-effect';
|
|
10
11
|
|
|
11
12
|
class IonicButtonFieldComponent {
|
|
12
|
-
|
|
13
|
-
arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
14
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
15
|
-
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
16
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
17
|
-
hidden = input(false, ...(ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []));
|
|
18
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
19
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
20
|
-
/** Event to dispatch on click. Optional for submit buttons (native form submit handles it). */
|
|
21
|
-
event = input(...(ngDevMode ? [undefined, { debugName: "event" }] : /* istanbul ignore next */ []));
|
|
22
|
-
eventArgs = input(...(ngDevMode ? [undefined, { debugName: "eventArgs" }] : /* istanbul ignore next */ []));
|
|
13
|
+
action = injectNgForgeAction();
|
|
23
14
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
24
|
-
eventContext = input(...(ngDevMode ? [undefined, { debugName: "eventContext" }] : /* istanbul ignore next */ []));
|
|
25
|
-
/** Resolved button type - defaults to 'button' if not specified in props */
|
|
26
15
|
buttonType = computed(() => this.props()?.type ?? 'button', ...(ngDevMode ? [{ debugName: "buttonType" }] : /* istanbul ignore next */ []));
|
|
27
|
-
buttonTestId = computed(() => `${this.buttonType()}-${this.key()}`, ...(ngDevMode ? [{ debugName: "buttonTestId" }] : /* istanbul ignore next */ []));
|
|
28
|
-
/**
|
|
29
|
-
* Handle button click.
|
|
30
|
-
* - For submit buttons (type="submit"): do nothing, native form submit handles it
|
|
31
|
-
* - For other buttons: dispatch the configured event via EventBus
|
|
32
|
-
*/
|
|
16
|
+
buttonTestId = computed(() => `${this.buttonType()}-${this.action.key()}`, ...(ngDevMode ? [{ debugName: "buttonTestId" }] : /* istanbul ignore next */ []));
|
|
33
17
|
onClick() {
|
|
34
|
-
|
|
35
|
-
if (this.buttonType() === 'submit') {
|
|
18
|
+
if (this.buttonType() === 'submit')
|
|
36
19
|
return;
|
|
37
|
-
|
|
38
|
-
// Other buttons dispatch their event (if configured)
|
|
39
|
-
const event = this.event();
|
|
40
|
-
if (event) {
|
|
41
|
-
this.dispatchEvent(event);
|
|
42
|
-
}
|
|
20
|
+
this.action.dispatch();
|
|
43
21
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// Build context from injected ARRAY_CONTEXT (with linkedSignal index) or fallback to eventContext
|
|
48
|
-
const context = this.arrayContext
|
|
49
|
-
? {
|
|
50
|
-
key: this.key(),
|
|
51
|
-
// Read signal to get current index (automatically updates via linkedSignal)
|
|
52
|
-
index: this.arrayContext.index(),
|
|
53
|
-
arrayKey: this.arrayContext.arrayKey,
|
|
54
|
-
formValue: this.arrayContext.formValue,
|
|
55
|
-
}
|
|
56
|
-
: this.eventContext() || { key: this.key() };
|
|
57
|
-
// Resolve tokens in event args using the provided context
|
|
58
|
-
const resolvedArgs = resolveTokens(args, context);
|
|
59
|
-
// Dispatch event with resolved args
|
|
60
|
-
this.eventBus.dispatch(event, ...resolvedArgs);
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
// No args, dispatch event without arguments
|
|
64
|
-
this.eventBus.dispatch(event);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: IonicButtonFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
68
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: IonicButtonFieldComponent, isStandalone: true, selector: "df-ion-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()}`", "class": "className()", "attr.data-testid": "key()", "attr.hidden": "hidden() || null" } }, ngImport: i0, template: `
|
|
69
|
-
@let buttonId = key() + '-button';
|
|
22
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicButtonFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
23
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: IonicButtonFieldComponent, isStandalone: true, selector: "df-ion-button", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeActionHost }], ngImport: i0, template: `
|
|
24
|
+
@let buttonId = action.key() + '-button';
|
|
70
25
|
|
|
71
26
|
<ion-button
|
|
72
27
|
[id]="buttonId"
|
|
@@ -77,23 +32,19 @@ class IonicButtonFieldComponent {
|
|
|
77
32
|
[size]="props()?.size"
|
|
78
33
|
[color]="props()?.color || 'primary'"
|
|
79
34
|
[strong]="props()?.strong"
|
|
80
|
-
[disabled]="disabled()"
|
|
35
|
+
[disabled]="action.disabled()"
|
|
36
|
+
[attr.tabindex]="action.tabIndex()"
|
|
81
37
|
[attr.data-testid]="buttonTestId()"
|
|
82
38
|
(click)="onClick()"
|
|
83
39
|
>
|
|
84
|
-
{{ label() | dynamicText | async }}
|
|
40
|
+
{{ action.label() | dynamicText | async }}
|
|
85
41
|
</ion-button>
|
|
86
42
|
`, isInline: true, styles: [":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
87
43
|
}
|
|
88
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
44
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicButtonFieldComponent, decorators: [{
|
|
89
45
|
type: Component,
|
|
90
|
-
args: [{ selector: 'df-ion-button', imports: [IonButton, DynamicTextPipe, AsyncPipe],
|
|
91
|
-
|
|
92
|
-
'[class]': 'className()',
|
|
93
|
-
'[attr.data-testid]': 'key()',
|
|
94
|
-
'[attr.hidden]': 'hidden() || null',
|
|
95
|
-
}, template: `
|
|
96
|
-
@let buttonId = key() + '-button';
|
|
46
|
+
args: [{ selector: 'df-ion-button', imports: [IonButton, DynamicTextPipe, AsyncPipe], hostDirectives: [NgForgeActionHost], template: `
|
|
47
|
+
@let buttonId = action.key() + '-button';
|
|
97
48
|
|
|
98
49
|
<ion-button
|
|
99
50
|
[id]="buttonId"
|
|
@@ -104,14 +55,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
104
55
|
[size]="props()?.size"
|
|
105
56
|
[color]="props()?.color || 'primary'"
|
|
106
57
|
[strong]="props()?.strong"
|
|
107
|
-
[disabled]="disabled()"
|
|
58
|
+
[disabled]="action.disabled()"
|
|
59
|
+
[attr.tabindex]="action.tabIndex()"
|
|
108
60
|
[attr.data-testid]="buttonTestId()"
|
|
109
61
|
(click)="onClick()"
|
|
110
62
|
>
|
|
111
|
-
{{ label() | dynamicText | async }}
|
|
63
|
+
{{ action.label() | dynamicText | async }}
|
|
112
64
|
</ion-button>
|
|
113
65
|
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host([hidden]){display:none!important}\n"] }]
|
|
114
|
-
}], propDecorators: {
|
|
66
|
+
}], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
115
67
|
|
|
116
68
|
var ionicButton_component = /*#__PURE__*/Object.freeze({
|
|
117
69
|
__proto__: null,
|
|
@@ -120,129 +72,60 @@ var ionicButton_component = /*#__PURE__*/Object.freeze({
|
|
|
120
72
|
|
|
121
73
|
// Public API - component
|
|
122
74
|
|
|
123
|
-
/**
|
|
124
|
-
* Creates a signal that computes the aria-describedby value based on errors and hint state.
|
|
125
|
-
* Errors take precedence over hints - when errors are displayed, the hint is hidden.
|
|
126
|
-
* Only the first error is displayed (single error ID, not indexed).
|
|
127
|
-
*
|
|
128
|
-
* @param errorsToDisplay Signal containing the array of errors currently being displayed
|
|
129
|
-
* @param errorId Signal containing the ID for the error element (single error only)
|
|
130
|
-
* @param hintId Signal containing the ID for the hint element
|
|
131
|
-
* @param hasHint Function that returns true if a hint is configured
|
|
132
|
-
* @returns Signal containing the aria-describedby value or null
|
|
133
|
-
*/
|
|
134
|
-
function createAriaDescribedBySignal(errorsToDisplay, errorId, hintId, hasHint) {
|
|
135
|
-
return computed(() => {
|
|
136
|
-
if (errorsToDisplay().length > 0) {
|
|
137
|
-
return errorId();
|
|
138
|
-
}
|
|
139
|
-
if (hasHint()) {
|
|
140
|
-
return hintId();
|
|
141
|
-
}
|
|
142
|
-
return null;
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
75
|
class IonicCheckboxFieldComponent {
|
|
147
|
-
|
|
148
|
-
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
149
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
150
|
-
// Properties
|
|
151
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
152
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
153
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
154
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
76
|
+
ngf = injectNgForgeField();
|
|
155
77
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
showErrors = shouldShowErrors(this.field);
|
|
161
|
-
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
|
|
162
|
-
constructor() {
|
|
163
|
-
// Shadow DOM - apply meta to ion-checkbox element
|
|
164
|
-
setupMetaTracking(this.elementRef, this.meta, {
|
|
165
|
-
selector: 'ion-checkbox',
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
169
|
-
// Accessibility
|
|
170
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
171
|
-
/** Base ID for error elements */
|
|
172
|
-
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
173
|
-
/** Unique ID for the helper text element */
|
|
174
|
-
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
175
|
-
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
176
|
-
ariaInvalid = computed(() => {
|
|
177
|
-
const fieldState = this.field()();
|
|
178
|
-
return fieldState.invalid() && fieldState.touched();
|
|
179
|
-
}, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
|
|
180
|
-
/** Whether the field has a required validator */
|
|
181
|
-
ariaRequired = computed(() => {
|
|
182
|
-
return this.field()().required?.() === true ? true : null;
|
|
183
|
-
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
|
|
184
|
-
/** aria-describedby linking to hint OR error elements (mutually exclusive) */
|
|
185
|
-
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
186
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: IonicCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
187
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: IonicCheckboxFieldComponent, isStandalone: true, selector: "df-ion-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 }, 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: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
188
|
-
@let f = field();
|
|
189
|
-
@let checkboxId = key() + '-checkbox';
|
|
78
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
79
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicCheckboxFieldComponent, isStandalone: true, selector: "df-ion-checkbox", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
|
|
80
|
+
@let f = ngf.field();
|
|
81
|
+
@let checkboxId = ngf.key() + '-checkbox';
|
|
190
82
|
|
|
191
83
|
<ion-checkbox
|
|
84
|
+
ngForgeControl
|
|
192
85
|
[id]="checkboxId"
|
|
193
86
|
[formField]="f"
|
|
194
87
|
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
195
88
|
[justify]="props()?.justify"
|
|
196
89
|
[color]="props()?.color ?? 'primary'"
|
|
197
90
|
[indeterminate]="props()?.indeterminate ?? false"
|
|
198
|
-
[attr.tabindex]="tabIndex()"
|
|
199
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
200
|
-
[attr.aria-required]="ariaRequired()"
|
|
201
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
91
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
202
92
|
>
|
|
203
|
-
{{ label() | dynamicText | async }}
|
|
93
|
+
{{ ngf.label() | dynamicText | async }}
|
|
204
94
|
</ion-checkbox>
|
|
205
95
|
|
|
206
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
207
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
96
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
97
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
208
98
|
} @else if (props()?.hint; as hint) {
|
|
209
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
99
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
210
100
|
}
|
|
211
|
-
`, isInline: true, styles: ["
|
|
101
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
212
102
|
}
|
|
213
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
103
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicCheckboxFieldComponent, decorators: [{
|
|
214
104
|
type: Component,
|
|
215
|
-
args: [{ selector: 'df-ion-checkbox', imports: [IonCheckbox, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
216
|
-
@let f = field();
|
|
217
|
-
@let checkboxId = key() + '-checkbox';
|
|
105
|
+
args: [{ selector: 'df-ion-checkbox', imports: [IonCheckbox, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
|
|
106
|
+
@let f = ngf.field();
|
|
107
|
+
@let checkboxId = ngf.key() + '-checkbox';
|
|
218
108
|
|
|
219
109
|
<ion-checkbox
|
|
110
|
+
ngForgeControl
|
|
220
111
|
[id]="checkboxId"
|
|
221
112
|
[formField]="f"
|
|
222
113
|
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
223
114
|
[justify]="props()?.justify"
|
|
224
115
|
[color]="props()?.color ?? 'primary'"
|
|
225
116
|
[indeterminate]="props()?.indeterminate ?? false"
|
|
226
|
-
[attr.tabindex]="tabIndex()"
|
|
227
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
228
|
-
[attr.aria-required]="ariaRequired()"
|
|
229
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
117
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
230
118
|
>
|
|
231
|
-
{{ label() | dynamicText | async }}
|
|
119
|
+
{{ ngf.label() | dynamicText | async }}
|
|
232
120
|
</ion-checkbox>
|
|
233
121
|
|
|
234
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
235
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
122
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
123
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
236
124
|
} @else if (props()?.hint; as hint) {
|
|
237
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
125
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
238
126
|
}
|
|
239
|
-
`, host: {
|
|
240
|
-
|
|
241
|
-
'[id]': '`${key()}`',
|
|
242
|
-
'[attr.data-testid]': 'key()',
|
|
243
|
-
'[attr.hidden]': 'field()().hidden() || null',
|
|
244
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{display:block;color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{display:block;color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
245
|
-
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
127
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
128
|
+
}], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
246
129
|
|
|
247
130
|
var ionicCheckbox_component = /*#__PURE__*/Object.freeze({
|
|
248
131
|
__proto__: null,
|
|
@@ -250,48 +133,12 @@ var ionicCheckbox_component = /*#__PURE__*/Object.freeze({
|
|
|
250
133
|
});
|
|
251
134
|
|
|
252
135
|
class IonicDatepickerFieldComponent {
|
|
253
|
-
|
|
254
|
-
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
255
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
256
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
257
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
258
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
259
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
136
|
+
ngf = injectNgForgeField();
|
|
260
137
|
minDate = input(null, ...(ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []));
|
|
261
138
|
maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []));
|
|
262
139
|
startAt = input(null, ...(ngDevMode ? [{ debugName: "startAt" }] : /* istanbul ignore next */ []));
|
|
263
140
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
264
|
-
meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
|
|
265
|
-
validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
|
|
266
|
-
defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
|
|
267
|
-
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
268
|
-
showErrors = shouldShowErrors(this.field);
|
|
269
|
-
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
|
|
270
141
|
isModalOpen = signal(false, ...(ngDevMode ? [{ debugName: "isModalOpen" }] : /* istanbul ignore next */ []));
|
|
271
|
-
constructor() {
|
|
272
|
-
// Shadow DOM - apply meta to ion-input element
|
|
273
|
-
setupMetaTracking(this.elementRef, this.meta, {
|
|
274
|
-
selector: 'ion-input',
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
278
|
-
// Accessibility
|
|
279
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
280
|
-
/** Base ID for error elements */
|
|
281
|
-
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
282
|
-
/** Unique ID for the helper text element */
|
|
283
|
-
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
284
|
-
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
285
|
-
ariaInvalid = computed(() => {
|
|
286
|
-
const fieldState = this.field()();
|
|
287
|
-
return fieldState.invalid() && fieldState.touched();
|
|
288
|
-
}, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
|
|
289
|
-
/** Whether the field has a required validator */
|
|
290
|
-
ariaRequired = computed(() => {
|
|
291
|
-
return this.field()().required?.() === true ? true : null;
|
|
292
|
-
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
|
|
293
|
-
/** aria-describedby linking to hint OR error elements (mutually exclusive) */
|
|
294
|
-
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
295
142
|
openModal() {
|
|
296
143
|
this.isModalOpen.set(true);
|
|
297
144
|
}
|
|
@@ -300,14 +147,14 @@ class IonicDatepickerFieldComponent {
|
|
|
300
147
|
}
|
|
301
148
|
onDateChange(event) {
|
|
302
149
|
const value = event.detail.value;
|
|
303
|
-
// ion-datetime emits ISO 8601 strings internally;
|
|
304
|
-
// to match the
|
|
150
|
+
// ion-datetime emits ISO 8601 strings internally; convert to Date | null
|
|
151
|
+
// to match the field tree's value type.
|
|
305
152
|
if (value && typeof value === 'string' && value.length > 0) {
|
|
306
153
|
const date = new Date(value);
|
|
307
|
-
this.field()().value.set(date);
|
|
154
|
+
this.ngf.field()().value.set(date);
|
|
308
155
|
}
|
|
309
156
|
else {
|
|
310
|
-
this.field()().value.set(null);
|
|
157
|
+
this.ngf.field()().value.set(null);
|
|
311
158
|
}
|
|
312
159
|
this.closeModal();
|
|
313
160
|
}
|
|
@@ -338,38 +185,36 @@ class IonicDatepickerFieldComponent {
|
|
|
338
185
|
return format(date, 'MMM d, yyyy');
|
|
339
186
|
}
|
|
340
187
|
}
|
|
341
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
342
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
343
|
-
@let f = field();
|
|
188
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicDatepickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
189
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicDatepickerFieldComponent, isStandalone: true, selector: "df-ion-datepicker", inputs: { minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
|
|
190
|
+
@let f = ngf.field();
|
|
344
191
|
@let dateValue = f().value();
|
|
345
|
-
@let inputId = key() + '-input';
|
|
192
|
+
@let inputId = ngf.key() + '-input';
|
|
346
193
|
|
|
347
194
|
<ion-input
|
|
195
|
+
ngForgeControl
|
|
348
196
|
[id]="inputId"
|
|
349
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
197
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
350
198
|
[labelPlacement]="'stacked'"
|
|
351
|
-
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
199
|
+
[placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
|
|
352
200
|
[disabled]="f().disabled()"
|
|
353
201
|
[value]="formatDisplayDate(dateValue)"
|
|
354
202
|
[readonly]="true"
|
|
355
203
|
[fill]="'outline'"
|
|
356
|
-
[attr.tabindex]="tabIndex()"
|
|
357
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
358
|
-
[attr.aria-required]="ariaRequired()"
|
|
359
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
204
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
360
205
|
(click)="!f().disabled() && openModal()"
|
|
361
206
|
/>
|
|
362
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
363
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
207
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
208
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
364
209
|
} @else if (props()?.hint; as hint) {
|
|
365
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
210
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
366
211
|
}
|
|
367
212
|
|
|
368
213
|
<ion-modal [isOpen]="isModalOpen()" (didDismiss)="closeModal()">
|
|
369
214
|
<ng-template>
|
|
370
215
|
<ion-header>
|
|
371
216
|
<ion-toolbar>
|
|
372
|
-
<ion-title>{{ label() | dynamicText | async }}</ion-title>
|
|
217
|
+
<ion-title>{{ ngf.label() | dynamicText | async }}</ion-title>
|
|
373
218
|
<ion-buttons slot="end">
|
|
374
219
|
<ion-button (click)="closeModal()">Close</ion-button>
|
|
375
220
|
</ion-buttons>
|
|
@@ -394,9 +239,9 @@ class IonicDatepickerFieldComponent {
|
|
|
394
239
|
</ion-content>
|
|
395
240
|
</ng-template>
|
|
396
241
|
</ion-modal>
|
|
397
|
-
`, isInline: true, styles: ["
|
|
242
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", "ion-input{cursor:pointer}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: IonDatetime, selector: "ion-datetime", inputs: ["cancelText", "clearText", "color", "dayValues", "disabled", "doneText", "firstDayOfWeek", "formatOptions", "highlightedDates", "hourCycle", "hourValues", "isDateEnabled", "locale", "max", "min", "minuteValues", "mode", "monthValues", "multiple", "name", "preferWheel", "presentation", "readonly", "showAdjacentDays", "showClearButton", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "titleSelectedDatesFormatter", "value", "yearValues"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
398
243
|
}
|
|
399
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
244
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicDatepickerFieldComponent, decorators: [{
|
|
400
245
|
type: Component,
|
|
401
246
|
args: [{ selector: 'df-ion-datepicker', imports: [
|
|
402
247
|
IonInput,
|
|
@@ -411,37 +256,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
411
256
|
IonButton,
|
|
412
257
|
DynamicTextPipe,
|
|
413
258
|
AsyncPipe,
|
|
414
|
-
|
|
415
|
-
|
|
259
|
+
NgForgeControl,
|
|
260
|
+
], hostDirectives: [NgForgeFieldHost], template: `
|
|
261
|
+
@let f = ngf.field();
|
|
416
262
|
@let dateValue = f().value();
|
|
417
|
-
@let inputId = key() + '-input';
|
|
263
|
+
@let inputId = ngf.key() + '-input';
|
|
418
264
|
|
|
419
265
|
<ion-input
|
|
266
|
+
ngForgeControl
|
|
420
267
|
[id]="inputId"
|
|
421
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
268
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
422
269
|
[labelPlacement]="'stacked'"
|
|
423
|
-
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
270
|
+
[placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
|
|
424
271
|
[disabled]="f().disabled()"
|
|
425
272
|
[value]="formatDisplayDate(dateValue)"
|
|
426
273
|
[readonly]="true"
|
|
427
274
|
[fill]="'outline'"
|
|
428
|
-
[attr.tabindex]="tabIndex()"
|
|
429
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
430
|
-
[attr.aria-required]="ariaRequired()"
|
|
431
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
275
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
432
276
|
(click)="!f().disabled() && openModal()"
|
|
433
277
|
/>
|
|
434
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
435
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
278
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
279
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
436
280
|
} @else if (props()?.hint; as hint) {
|
|
437
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
281
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
438
282
|
}
|
|
439
283
|
|
|
440
284
|
<ion-modal [isOpen]="isModalOpen()" (didDismiss)="closeModal()">
|
|
441
285
|
<ng-template>
|
|
442
286
|
<ion-header>
|
|
443
287
|
<ion-toolbar>
|
|
444
|
-
<ion-title>{{ label() | dynamicText | async }}</ion-title>
|
|
288
|
+
<ion-title>{{ ngf.label() | dynamicText | async }}</ion-title>
|
|
445
289
|
<ion-buttons slot="end">
|
|
446
290
|
<ion-button (click)="closeModal()">Close</ion-button>
|
|
447
291
|
</ion-buttons>
|
|
@@ -466,19 +310,85 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
466
310
|
</ion-content>
|
|
467
311
|
</ng-template>
|
|
468
312
|
</ion-modal>
|
|
469
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
470
|
-
|
|
471
|
-
'[attr.data-testid]': 'key()',
|
|
472
|
-
'[class]': 'className()',
|
|
473
|
-
'[attr.hidden]': 'field()().hidden() || null',
|
|
474
|
-
}, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{display:block;color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{display:block;color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", "ion-input{cursor:pointer}:host([hidden]){display:none!important}\n"] }]
|
|
475
|
-
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
313
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", "ion-input{cursor:pointer}:host([hidden]){display:none!important}\n"] }]
|
|
314
|
+
}], propDecorators: { minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
476
315
|
|
|
477
316
|
var ionicDatepicker_component = /*#__PURE__*/Object.freeze({
|
|
478
317
|
__proto__: null,
|
|
479
318
|
default: IonicDatepickerFieldComponent
|
|
480
319
|
});
|
|
481
320
|
|
|
321
|
+
/** Ionic adapter binding for the shared preset runner. */
|
|
322
|
+
function runIonicPresetAction(preset, ctx, collaborators) {
|
|
323
|
+
return runPresetAction(preset, ctx, collaborators, 'Ionic', 'ion-input');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Inline `ion-button` addon — the host element IS `<ion-button>` so Ionic's
|
|
328
|
+
* `::slotted(ion-button[slot=start|end])` shadow CSS matches and applies its
|
|
329
|
+
* native icon-only sizing. `IonButtonAddonComponent` (tag selector) stays
|
|
330
|
+
* for the universal `<df-addon-slot>` dispatcher when the addon is rendered
|
|
331
|
+
* outside an `<ion-input>` host.
|
|
332
|
+
*/
|
|
333
|
+
class IonInlineButtonAddonComponent {
|
|
334
|
+
injector = inject(Injector);
|
|
335
|
+
action = injectNgForgeAddonAction();
|
|
336
|
+
addon = this.action.addon;
|
|
337
|
+
label = computed(() => this.addon().label, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
338
|
+
ariaLabel = computed(() => this.addon().ariaLabel, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
339
|
+
icon = computed(() => this.addon().icon, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
340
|
+
color = computed(() => this.addon().color, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
341
|
+
fill = computed(() => this.addon().fill ?? 'clear', ...(ngDevMode ? [{ debugName: "fill" }] : /* istanbul ignore next */ []));
|
|
342
|
+
iconOnly = computed(() => !!this.icon() && !this.label(), ...(ngDevMode ? [{ debugName: "iconOnly" }] : /* istanbul ignore next */ []));
|
|
343
|
+
// Host bindings can't use pipes (NG5001), so `DynamicText` is materialised
|
|
344
|
+
// via an effect (resolveDynamicValue's toSignal can't run inside computed).
|
|
345
|
+
_ariaLabelSignal = signal(undefined, ...(ngDevMode ? [{ debugName: "_ariaLabelSignal" }] : /* istanbul ignore next */ []));
|
|
346
|
+
resolvedAriaLabel = computed(() => this._ariaLabelSignal()?.() ?? undefined, ...(ngDevMode ? [{ debugName: "resolvedAriaLabel" }] : /* istanbul ignore next */ []));
|
|
347
|
+
constructor() {
|
|
348
|
+
explicitEffect([this.ariaLabel], ([raw]) => {
|
|
349
|
+
if (raw === undefined) {
|
|
350
|
+
this._ariaLabelSignal.set(undefined);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
this._ariaLabelSignal.set(resolveDynamicValue(raw, undefined, this.injector));
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonInlineButtonAddonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
357
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonInlineButtonAddonComponent, isStandalone: true, selector: "ion-button[df-ion-button-addon]", host: { listeners: { "click": "action.dispatch()" }, properties: { "attr.color": "color() ?? null", "attr.fill": "fill()", "attr.disabled": "action.disabled() || action.loading() ? \"true\" : null", "attr.aria-label": "resolvedAriaLabel() ?? null", "attr.aria-busy": "action.loading() || null" } }, hostDirectives: [{ directive: i1.NgForgeAddonAction }], ngImport: i0, template: `
|
|
358
|
+
@if (action.loading()) {
|
|
359
|
+
<ion-spinner [slot]="iconOnly() ? 'icon-only' : 'start'" name="dots"></ion-spinner>
|
|
360
|
+
<span class="df-ion-sr-only" role="status">Loading…</span>
|
|
361
|
+
} @else if (icon(); as ic) {
|
|
362
|
+
<ion-icon [name]="ic" [slot]="iconOnly() ? 'icon-only' : 'start'"></ion-icon>
|
|
363
|
+
}
|
|
364
|
+
@if (label(); as lbl) {
|
|
365
|
+
{{ lbl | dynamicText | async }}
|
|
366
|
+
}
|
|
367
|
+
`, isInline: true, styles: [".df-ion-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
368
|
+
}
|
|
369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonInlineButtonAddonComponent, decorators: [{
|
|
370
|
+
type: Component,
|
|
371
|
+
args: [{ selector: 'ion-button[df-ion-button-addon]', imports: [IonIcon, IonSpinner, DynamicTextPipe, AsyncPipe], hostDirectives: [NgForgeAddonAction], template: `
|
|
372
|
+
@if (action.loading()) {
|
|
373
|
+
<ion-spinner [slot]="iconOnly() ? 'icon-only' : 'start'" name="dots"></ion-spinner>
|
|
374
|
+
<span class="df-ion-sr-only" role="status">Loading…</span>
|
|
375
|
+
} @else if (icon(); as ic) {
|
|
376
|
+
<ion-icon [name]="ic" [slot]="iconOnly() ? 'icon-only' : 'start'"></ion-icon>
|
|
377
|
+
}
|
|
378
|
+
@if (label(); as lbl) {
|
|
379
|
+
{{ lbl | dynamicText | async }}
|
|
380
|
+
}
|
|
381
|
+
`, host: {
|
|
382
|
+
// Stencil reflects [attr.*] to the underlying ion-button properties.
|
|
383
|
+
'[attr.color]': 'color() ?? null',
|
|
384
|
+
'[attr.fill]': 'fill()',
|
|
385
|
+
'[attr.disabled]': 'action.disabled() || action.loading() ? "true" : null',
|
|
386
|
+
'[attr.aria-label]': 'resolvedAriaLabel() ?? null',
|
|
387
|
+
'[attr.aria-busy]': 'action.loading() || null',
|
|
388
|
+
'(click)': 'action.dispatch()',
|
|
389
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
|
|
390
|
+
}], ctorParameters: () => [] });
|
|
391
|
+
|
|
482
392
|
/**
|
|
483
393
|
* Injection token for Ionic form configuration.
|
|
484
394
|
* Use this to provide global configuration for Ionic form fields.
|
|
@@ -502,59 +412,70 @@ var ionicDatepicker_component = /*#__PURE__*/Object.freeze({
|
|
|
502
412
|
*/
|
|
503
413
|
const IONIC_CONFIG = new InjectionToken('IONIC_CONFIG');
|
|
504
414
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
//
|
|
519
|
-
//
|
|
520
|
-
//
|
|
521
|
-
//
|
|
522
|
-
// camelCase `maxLength` / `minLength` inputs so Signal Forms's setInputOnDirectives
|
|
523
|
-
// auto-wires. See packages/dynamic-forms-primeng/src/lib/fields/textarea/.
|
|
415
|
+
/**
|
|
416
|
+
* Per-field writable signal that overrides the input's `type` attribute.
|
|
417
|
+
*
|
|
418
|
+
* Provided at the `ion-input` field component level. The button addon's
|
|
419
|
+
* `'toggle-password-visibility'` preset writes to it; the field component
|
|
420
|
+
* reads it to compute its effective `type`.
|
|
421
|
+
*
|
|
422
|
+
* Optional from a button's perspective — when the button is hosted inside a
|
|
423
|
+
* field that doesn't provide this token (e.g., textarea or a future
|
|
424
|
+
* non-input field), the toggle preset is a no-op.
|
|
425
|
+
*/
|
|
426
|
+
const IONIC_INPUT_TYPE_OVERRIDE = new InjectionToken('IONIC_INPUT_TYPE_OVERRIDE');
|
|
427
|
+
|
|
428
|
+
// minlength/maxlength bindings: Signal Forms auto-syncs these on NATIVE
|
|
429
|
+
// inputs; <ion-input> is a Stencil web component so we bind directly from
|
|
430
|
+
// FieldState (`f().maxLength?.()` — the signal itself is missing when no
|
|
431
|
+
// validator is configured).
|
|
524
432
|
class IonicInputFieldComponent {
|
|
525
433
|
elementRef = inject((ElementRef));
|
|
526
434
|
ionicConfig = inject(IONIC_CONFIG, { optional: true });
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
530
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
531
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
532
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
435
|
+
ngf = injectNgForgeField();
|
|
436
|
+
ngfa = injectNgForgeAddons();
|
|
533
437
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
438
|
+
/**
|
|
439
|
+
* Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the
|
|
440
|
+
* component level so `setInputIfDeclared` (which uses
|
|
441
|
+
* `reflectComponentType`) can write it.
|
|
442
|
+
*/
|
|
443
|
+
fieldInputs = input(...(ngDevMode ? [undefined, { debugName: "fieldInputs" }] : /* istanbul ignore next */ []));
|
|
444
|
+
/** Per-instance type override populated by `toggle-password-visibility` preset. */
|
|
445
|
+
typeOverride = inject(IONIC_INPUT_TYPE_OVERRIDE);
|
|
446
|
+
fill = computed(() => this.props()?.fill ?? this.ionicConfig?.fill ?? 'solid', ...(ngDevMode ? [{ debugName: "fill" }] : /* istanbul ignore next */ []));
|
|
447
|
+
shape = computed(() => this.props()?.shape ?? this.ionicConfig?.shape, ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
448
|
+
/** Default 'stacked' (label above the input) for adapter parity with Material /
|
|
449
|
+
* Bootstrap / PrimeNG. Consumers can opt into Ionic's native inline 'start'
|
|
450
|
+
* or 'fixed' via props.labelPlacement or the IONIC_CONFIG token. */
|
|
451
|
+
labelPlacement = computed(() => this.props()?.labelPlacement ?? this.ionicConfig?.labelPlacement ?? 'stacked', ...(ngDevMode ? [{ debugName: "labelPlacement" }] : /* istanbul ignore next */ []));
|
|
452
|
+
color = computed(() => this.props()?.color ?? this.ionicConfig?.color, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
453
|
+
/** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */
|
|
454
|
+
type = computed(() => this.typeOverride() ?? this.props()?.type ?? 'text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
455
|
+
/** Per-kind split: ion-button addons render inline via the attribute-
|
|
456
|
+
* selector inline component (so the slotted element is a native
|
|
457
|
+
* <ion-button> Ionic can style); everything else (icon/text/template/
|
|
458
|
+
* component kinds) goes through the universal <df-addon-slot> dispatcher
|
|
459
|
+
* wrapped in <span slot="start|end"> for safe shadow-DOM projection. */
|
|
460
|
+
buttonPrefixAddons = computed(() => this.ngfa.prefixAddons().filter((a) => a.kind === 'ion-button'), ...(ngDevMode ? [{ debugName: "buttonPrefixAddons" }] : /* istanbul ignore next */ []));
|
|
461
|
+
buttonSuffixAddons = computed(() => this.ngfa.suffixAddons().filter((a) => a.kind === 'ion-button'), ...(ngDevMode ? [{ debugName: "buttonSuffixAddons" }] : /* istanbul ignore next */ []));
|
|
462
|
+
decorativePrefixAddons = computed(() => this.ngfa.prefixAddons().filter((a) => a.kind !== 'ion-button'), ...(ngDevMode ? [{ debugName: "decorativePrefixAddons" }] : /* istanbul ignore next */ []));
|
|
463
|
+
decorativeSuffixAddons = computed(() => this.ngfa.suffixAddons().filter((a) => a.kind !== 'ion-button'), ...(ngDevMode ? [{ debugName: "decorativeSuffixAddons" }] : /* istanbul ignore next */ []));
|
|
464
|
+
/** Set when the component is destroyed — guards async aria-describedby sync against teardown. */
|
|
465
|
+
destroyed = false;
|
|
544
466
|
constructor() {
|
|
545
|
-
|
|
546
|
-
setupMetaTracking(this.elementRef, this.meta, {
|
|
547
|
-
selector: 'ion-input',
|
|
548
|
-
});
|
|
467
|
+
inject(DestroyRef).onDestroy(() => (this.destroyed = true));
|
|
549
468
|
// ion-input encapsulates a native <input> in shadow DOM and does not automatically
|
|
550
469
|
// propagate aria-describedby to it. This effect imperatively syncs the attribute
|
|
551
470
|
// after a microtask to ensure Ionic has resolved the internal element.
|
|
552
|
-
explicitEffect([this.ariaDescribedBy], ([describedBy]) => {
|
|
471
|
+
explicitEffect([this.ngf.ariaDescribedBy], ([describedBy]) => {
|
|
553
472
|
queueMicrotask(() => {
|
|
473
|
+
if (this.destroyed)
|
|
474
|
+
return;
|
|
554
475
|
const ionInput = this.elementRef.nativeElement.querySelector('ion-input');
|
|
555
476
|
if (ionInput?.getInputElement) {
|
|
556
477
|
ionInput.getInputElement().then((inputEl) => {
|
|
557
|
-
if (!inputEl)
|
|
478
|
+
if (this.destroyed || !inputEl)
|
|
558
479
|
return;
|
|
559
480
|
if (describedBy) {
|
|
560
481
|
inputEl.setAttribute('aria-describedby', describedBy);
|
|
@@ -567,92 +488,163 @@ class IonicInputFieldComponent {
|
|
|
567
488
|
});
|
|
568
489
|
});
|
|
569
490
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
491
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
492
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicInputFieldComponent, isStandalone: true, selector: "df-ion-input", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, fieldInputs: { classPropertyName: "fieldInputs", publicName: "fieldInputs", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
493
|
+
{
|
|
494
|
+
provide: IONIC_INPUT_TYPE_OVERRIDE,
|
|
495
|
+
useFactory: () => signal(undefined),
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
// Adapter-specific preset semantics for `ion-button` addons (clear /
|
|
499
|
+
// reset / paste / copy / toggle-password-visibility). The directive
|
|
500
|
+
// (`NgForgeAddonAction`) delegates here when an addon configures a
|
|
501
|
+
// `preset`. Per-ion-input-instance so the `typeOverride` signal is
|
|
502
|
+
// scoped to one field.
|
|
503
|
+
provide: ADDON_PRESET_HANDLER,
|
|
504
|
+
useFactory: () => {
|
|
505
|
+
const typeOverride = inject(IONIC_INPUT_TYPE_OVERRIDE);
|
|
506
|
+
const fsc = inject(FIELD_SIGNAL_CONTEXT, { optional: true });
|
|
507
|
+
const logger = inject(DynamicFormLogger);
|
|
508
|
+
// forwardRef for baselineType only — host.props()?.type gates toggle-password-visibility.
|
|
509
|
+
const host = inject(forwardRef(() => IonicInputFieldComponent));
|
|
510
|
+
return {
|
|
511
|
+
run: (preset, ctx) => {
|
|
512
|
+
const fieldKey = ctx.field.key;
|
|
513
|
+
return runIonicPresetAction(preset, ctx, {
|
|
514
|
+
typeOverride,
|
|
515
|
+
fieldValueSetter: ctx.setValue,
|
|
516
|
+
fieldDefaultValueGetter: fsc && fieldKey ? () => fsc.defaultValues()?.[fieldKey] : undefined,
|
|
517
|
+
baselineType: () => host.props()?.type,
|
|
518
|
+
logger,
|
|
519
|
+
});
|
|
520
|
+
},
|
|
521
|
+
};
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
], hostDirectives: [{ directive: i1.NgForgeFieldHost }, { directive: i1.NgForgeAddons }], ngImport: i0, template: `
|
|
525
|
+
@let f = ngf.field();
|
|
526
|
+
@let inputId = ngf.key() + '-input';
|
|
592
527
|
|
|
593
528
|
<ion-input
|
|
529
|
+
ngForgeControl
|
|
594
530
|
[id]="inputId"
|
|
595
|
-
[type]="
|
|
531
|
+
[type]="type()"
|
|
596
532
|
[formField]="f"
|
|
597
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
598
|
-
[labelPlacement]="
|
|
599
|
-
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
533
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
534
|
+
[labelPlacement]="labelPlacement()"
|
|
535
|
+
[placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
|
|
600
536
|
[clearInput]="props()?.clearInput ?? false"
|
|
601
537
|
[counter]="props()?.counter ?? false"
|
|
602
538
|
[minlength]="f().minLength?.()"
|
|
603
539
|
[maxlength]="f().maxLength?.()"
|
|
604
|
-
[color]="
|
|
605
|
-
[fill]="
|
|
606
|
-
[shape]="
|
|
540
|
+
[color]="color()"
|
|
541
|
+
[fill]="fill()"
|
|
542
|
+
[shape]="shape()"
|
|
607
543
|
[readonly]="f().readonly()"
|
|
608
|
-
[helperText]="errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined"
|
|
609
|
-
[attr.tabindex]="tabIndex()"
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
544
|
+
[helperText]="ngf.errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined"
|
|
545
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
546
|
+
>
|
|
547
|
+
@for (a of decorativePrefixAddons(); track $index) {
|
|
548
|
+
<span slot="start">
|
|
549
|
+
<df-addon-slot [addon]="a" [fieldInputs]="fieldInputs()" [hidden]="ngfa.hiddenSignalCache().get(a)" />
|
|
550
|
+
</span>
|
|
551
|
+
}
|
|
552
|
+
@for (a of buttonPrefixAddons(); track $index) {
|
|
553
|
+
<ion-button df-ion-button-addon slot="start" [addon]="a" [fieldInputs]="fieldInputs()"></ion-button>
|
|
554
|
+
}
|
|
555
|
+
@for (a of buttonSuffixAddons(); track $index) {
|
|
556
|
+
<ion-button df-ion-button-addon slot="end" [addon]="a" [fieldInputs]="fieldInputs()"></ion-button>
|
|
557
|
+
}
|
|
558
|
+
@for (a of decorativeSuffixAddons(); track $index) {
|
|
559
|
+
<span slot="end">
|
|
560
|
+
<df-addon-slot [addon]="a" [fieldInputs]="fieldInputs()" [hidden]="ngfa.hiddenSignalCache().get(a)" />
|
|
561
|
+
</span>
|
|
562
|
+
}
|
|
563
|
+
</ion-input>
|
|
564
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
565
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
616
566
|
}
|
|
617
|
-
`, isInline: true, styles: ["
|
|
567
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}:host{--df-ion-addon-prefix-outer-padding: 0;--df-ion-addon-prefix-inner-padding: .5rem;--df-ion-addon-suffix-inner-padding: .5rem;--df-ion-addon-suffix-outer-padding: 0}:host ::ng-deep ion-input [slot=start],:host ::ng-deep ion-input [slot=end]{display:inline-flex;align-items:center;align-self:center;line-height:1}:host ::ng-deep ion-input [slot=start] df-addon-slot,:host ::ng-deep ion-input [slot=end] df-addon-slot,:host ::ng-deep ion-input [slot=start] df-ion-icon-addon,:host ::ng-deep ion-input [slot=end] df-ion-icon-addon{display:inline-flex;align-items:center;line-height:1}:host ::ng-deep ion-input [slot=start]{padding-inline-start:var(--df-ion-addon-prefix-outer-padding);padding-inline-end:var(--df-ion-addon-prefix-inner-padding)}:host ::ng-deep ion-input [slot=end]{padding-inline-start:var(--df-ion-addon-suffix-inner-padding);padding-inline-end:var(--df-ion-addon-suffix-outer-padding)}:host ::ng-deep ion-input ion-icon{color:inherit}\n"], dependencies: [{ kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "component", type: DfAddonSlot, selector: "df-addon-slot", inputs: ["addon", "fieldInputs", "hidden"] }, { kind: "component", type: IonInlineButtonAddonComponent, selector: "ion-button[df-ion-button-addon]" }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
618
568
|
}
|
|
619
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
569
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicInputFieldComponent, decorators: [{
|
|
620
570
|
type: Component,
|
|
621
|
-
args: [{ selector: 'df-ion-input', imports: [IonInput, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
622
|
-
@let f = field();
|
|
623
|
-
@let inputId = key() + '-input';
|
|
571
|
+
args: [{ selector: 'df-ion-input', imports: [IonInput, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl, DfAddonSlot, IonInlineButtonAddonComponent], hostDirectives: [NgForgeFieldHost, NgForgeAddons], template: `
|
|
572
|
+
@let f = ngf.field();
|
|
573
|
+
@let inputId = ngf.key() + '-input';
|
|
624
574
|
|
|
625
575
|
<ion-input
|
|
576
|
+
ngForgeControl
|
|
626
577
|
[id]="inputId"
|
|
627
|
-
[type]="
|
|
578
|
+
[type]="type()"
|
|
628
579
|
[formField]="f"
|
|
629
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
630
|
-
[labelPlacement]="
|
|
631
|
-
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
580
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
581
|
+
[labelPlacement]="labelPlacement()"
|
|
582
|
+
[placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
|
|
632
583
|
[clearInput]="props()?.clearInput ?? false"
|
|
633
584
|
[counter]="props()?.counter ?? false"
|
|
634
585
|
[minlength]="f().minLength?.()"
|
|
635
586
|
[maxlength]="f().maxLength?.()"
|
|
636
|
-
[color]="
|
|
637
|
-
[fill]="
|
|
638
|
-
[shape]="
|
|
587
|
+
[color]="color()"
|
|
588
|
+
[fill]="fill()"
|
|
589
|
+
[shape]="shape()"
|
|
639
590
|
[readonly]="f().readonly()"
|
|
640
|
-
[helperText]="errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined"
|
|
641
|
-
[attr.tabindex]="tabIndex()"
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
591
|
+
[helperText]="ngf.errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined"
|
|
592
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
593
|
+
>
|
|
594
|
+
@for (a of decorativePrefixAddons(); track $index) {
|
|
595
|
+
<span slot="start">
|
|
596
|
+
<df-addon-slot [addon]="a" [fieldInputs]="fieldInputs()" [hidden]="ngfa.hiddenSignalCache().get(a)" />
|
|
597
|
+
</span>
|
|
598
|
+
}
|
|
599
|
+
@for (a of buttonPrefixAddons(); track $index) {
|
|
600
|
+
<ion-button df-ion-button-addon slot="start" [addon]="a" [fieldInputs]="fieldInputs()"></ion-button>
|
|
601
|
+
}
|
|
602
|
+
@for (a of buttonSuffixAddons(); track $index) {
|
|
603
|
+
<ion-button df-ion-button-addon slot="end" [addon]="a" [fieldInputs]="fieldInputs()"></ion-button>
|
|
604
|
+
}
|
|
605
|
+
@for (a of decorativeSuffixAddons(); track $index) {
|
|
606
|
+
<span slot="end">
|
|
607
|
+
<df-addon-slot [addon]="a" [fieldInputs]="fieldInputs()" [hidden]="ngfa.hiddenSignalCache().get(a)" />
|
|
608
|
+
</span>
|
|
609
|
+
}
|
|
610
|
+
</ion-input>
|
|
611
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
612
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
648
613
|
}
|
|
649
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush,
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
614
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
615
|
+
{
|
|
616
|
+
provide: IONIC_INPUT_TYPE_OVERRIDE,
|
|
617
|
+
useFactory: () => signal(undefined),
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
// Adapter-specific preset semantics for `ion-button` addons (clear /
|
|
621
|
+
// reset / paste / copy / toggle-password-visibility). The directive
|
|
622
|
+
// (`NgForgeAddonAction`) delegates here when an addon configures a
|
|
623
|
+
// `preset`. Per-ion-input-instance so the `typeOverride` signal is
|
|
624
|
+
// scoped to one field.
|
|
625
|
+
provide: ADDON_PRESET_HANDLER,
|
|
626
|
+
useFactory: () => {
|
|
627
|
+
const typeOverride = inject(IONIC_INPUT_TYPE_OVERRIDE);
|
|
628
|
+
const fsc = inject(FIELD_SIGNAL_CONTEXT, { optional: true });
|
|
629
|
+
const logger = inject(DynamicFormLogger);
|
|
630
|
+
// forwardRef for baselineType only — host.props()?.type gates toggle-password-visibility.
|
|
631
|
+
const host = inject(forwardRef(() => IonicInputFieldComponent));
|
|
632
|
+
return {
|
|
633
|
+
run: (preset, ctx) => {
|
|
634
|
+
const fieldKey = ctx.field.key;
|
|
635
|
+
return runIonicPresetAction(preset, ctx, {
|
|
636
|
+
typeOverride,
|
|
637
|
+
fieldValueSetter: ctx.setValue,
|
|
638
|
+
fieldDefaultValueGetter: fsc && fieldKey ? () => fsc.defaultValues()?.[fieldKey] : undefined,
|
|
639
|
+
baselineType: () => host.props()?.type,
|
|
640
|
+
logger,
|
|
641
|
+
});
|
|
642
|
+
},
|
|
643
|
+
};
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
], styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}:host{--df-ion-addon-prefix-outer-padding: 0;--df-ion-addon-prefix-inner-padding: .5rem;--df-ion-addon-suffix-inner-padding: .5rem;--df-ion-addon-suffix-outer-padding: 0}:host ::ng-deep ion-input [slot=start],:host ::ng-deep ion-input [slot=end]{display:inline-flex;align-items:center;align-self:center;line-height:1}:host ::ng-deep ion-input [slot=start] df-addon-slot,:host ::ng-deep ion-input [slot=end] df-addon-slot,:host ::ng-deep ion-input [slot=start] df-ion-icon-addon,:host ::ng-deep ion-input [slot=end] df-ion-icon-addon{display:inline-flex;align-items:center;line-height:1}:host ::ng-deep ion-input [slot=start]{padding-inline-start:var(--df-ion-addon-prefix-outer-padding);padding-inline-end:var(--df-ion-addon-prefix-inner-padding)}:host ::ng-deep ion-input [slot=end]{padding-inline-start:var(--df-ion-addon-suffix-inner-padding);padding-inline-end:var(--df-ion-addon-suffix-outer-padding)}:host ::ng-deep ion-input ion-icon{color:inherit}\n"] }]
|
|
647
|
+
}], ctorParameters: () => [], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], fieldInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldInputs", required: false }] }] } });
|
|
656
648
|
|
|
657
649
|
var ionicInput_component = /*#__PURE__*/Object.freeze({
|
|
658
650
|
__proto__: null,
|
|
@@ -660,41 +652,11 @@ var ionicInput_component = /*#__PURE__*/Object.freeze({
|
|
|
660
652
|
});
|
|
661
653
|
|
|
662
654
|
class IonicMultiCheckboxFieldComponent {
|
|
663
|
-
|
|
664
|
-
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
665
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
666
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
667
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
668
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
669
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
655
|
+
ngf = injectNgForgeField();
|
|
670
656
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
671
657
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
672
|
-
meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
|
|
673
|
-
validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
|
|
674
|
-
defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
|
|
675
|
-
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
676
|
-
showErrors = shouldShowErrors(this.field);
|
|
677
|
-
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
|
|
678
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
679
|
-
// Accessibility
|
|
680
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
681
|
-
/** Base ID for error elements */
|
|
682
|
-
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
683
|
-
/** Unique ID for the helper text element */
|
|
684
|
-
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
685
|
-
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
686
|
-
ariaInvalid = computed(() => {
|
|
687
|
-
const fieldState = this.field()();
|
|
688
|
-
return fieldState.invalid() && fieldState.touched();
|
|
689
|
-
}, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
|
|
690
|
-
/** Whether the field has a required validator */
|
|
691
|
-
ariaRequired = computed(() => {
|
|
692
|
-
return this.field()().required?.() === true ? true : null;
|
|
693
|
-
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
|
|
694
|
-
/** aria-describedby linking to hint OR error elements (mutually exclusive) */
|
|
695
|
-
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
696
658
|
valueViewModel = linkedSignal(() => {
|
|
697
|
-
const currentValues = this.field()().value();
|
|
659
|
+
const currentValues = this.ngf.field()().value();
|
|
698
660
|
return this.options().filter((option) => currentValues.includes(option.value));
|
|
699
661
|
}, { ...(ngDevMode ? { debugName: "valueViewModel" } : /* istanbul ignore next */ {}), equal: isEqual });
|
|
700
662
|
/** Computed map of checked option values for O(1) lookup in template */
|
|
@@ -706,15 +668,10 @@ class IonicMultiCheckboxFieldComponent {
|
|
|
706
668
|
return map;
|
|
707
669
|
}, ...(ngDevMode ? [{ debugName: "checkedValuesMap" }] : /* istanbul ignore next */ []));
|
|
708
670
|
constructor() {
|
|
709
|
-
// Shadow DOM - apply meta to ion-checkbox elements, re-apply when options change
|
|
710
|
-
setupMetaTracking(this.elementRef, this.meta, {
|
|
711
|
-
selector: 'ion-checkbox',
|
|
712
|
-
dependents: [this.options],
|
|
713
|
-
});
|
|
714
671
|
explicitEffect([this.valueViewModel], ([selectedOptions]) => {
|
|
715
672
|
const selectedValues = selectedOptions.map((option) => option.value);
|
|
716
|
-
if (!isEqual(selectedValues, this.field()().value())) {
|
|
717
|
-
this.field()().value.set(selectedValues);
|
|
673
|
+
if (!isEqual(selectedValues, this.ngf.field()().value())) {
|
|
674
|
+
this.ngf.field()().value.set(selectedValues);
|
|
718
675
|
}
|
|
719
676
|
});
|
|
720
677
|
explicitEffect([this.options], ([options]) => {
|
|
@@ -736,26 +693,27 @@ class IonicMultiCheckboxFieldComponent {
|
|
|
736
693
|
}
|
|
737
694
|
});
|
|
738
695
|
}
|
|
739
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
740
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
741
|
-
@let f = field();
|
|
696
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicMultiCheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
697
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicMultiCheckboxFieldComponent, isStandalone: true, selector: "df-ion-multi-checkbox", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
|
|
698
|
+
@let f = ngf.field();
|
|
742
699
|
@let checked = checkedValuesMap();
|
|
743
|
-
@if (label(); as label) {
|
|
700
|
+
@if (ngf.label(); as label) {
|
|
744
701
|
<div class="checkbox-group-label">{{ label | dynamicText | async }}</div>
|
|
745
702
|
}
|
|
746
703
|
|
|
747
704
|
<div
|
|
748
705
|
class="checkbox-group"
|
|
749
706
|
role="group"
|
|
750
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
751
|
-
[attr.aria-required]="ariaRequired()"
|
|
752
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
753
|
-
[class.ion-invalid]="showErrors()"
|
|
754
|
-
[class.ion-touched]="
|
|
707
|
+
[attr.aria-invalid]="ngf.ariaInvalid()"
|
|
708
|
+
[attr.aria-required]="ngf.ariaRequired()"
|
|
709
|
+
[attr.aria-describedby]="ngf.ariaDescribedBy()"
|
|
710
|
+
[class.ion-invalid]="ngf.showErrors()"
|
|
711
|
+
[class.ion-touched]="f().touched()"
|
|
755
712
|
>
|
|
756
713
|
@for (option of options(); track option.value) {
|
|
757
714
|
<ion-item lines="none">
|
|
758
715
|
<ion-checkbox
|
|
716
|
+
ngForgeControl
|
|
759
717
|
[checked]="checked['' + option.value]"
|
|
760
718
|
[disabled]="f().disabled() || option.disabled"
|
|
761
719
|
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
@@ -769,34 +727,35 @@ class IonicMultiCheckboxFieldComponent {
|
|
|
769
727
|
}
|
|
770
728
|
</div>
|
|
771
729
|
|
|
772
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
773
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
730
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
731
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
774
732
|
} @else if (props()?.hint; as hint) {
|
|
775
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
733
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
776
734
|
}
|
|
777
|
-
`, isInline: true, styles: ["
|
|
735
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}.checkbox-group-label{margin-bottom:8px;font-weight:500}.checkbox-group{display:flex;flex-direction:column;gap:4px}ion-item{--padding-start: 0;--inner-padding-end: 0}\n"], dependencies: [{ kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
778
736
|
}
|
|
779
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
737
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicMultiCheckboxFieldComponent, decorators: [{
|
|
780
738
|
type: Component,
|
|
781
|
-
args: [{ selector: 'df-ion-multi-checkbox', imports: [IonCheckbox, IonItem, IonNote, DynamicTextPipe, AsyncPipe], template: `
|
|
782
|
-
@let f = field();
|
|
739
|
+
args: [{ selector: 'df-ion-multi-checkbox', imports: [IonCheckbox, IonItem, IonNote, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
|
|
740
|
+
@let f = ngf.field();
|
|
783
741
|
@let checked = checkedValuesMap();
|
|
784
|
-
@if (label(); as label) {
|
|
742
|
+
@if (ngf.label(); as label) {
|
|
785
743
|
<div class="checkbox-group-label">{{ label | dynamicText | async }}</div>
|
|
786
744
|
}
|
|
787
745
|
|
|
788
746
|
<div
|
|
789
747
|
class="checkbox-group"
|
|
790
748
|
role="group"
|
|
791
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
792
|
-
[attr.aria-required]="ariaRequired()"
|
|
793
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
794
|
-
[class.ion-invalid]="showErrors()"
|
|
795
|
-
[class.ion-touched]="
|
|
749
|
+
[attr.aria-invalid]="ngf.ariaInvalid()"
|
|
750
|
+
[attr.aria-required]="ngf.ariaRequired()"
|
|
751
|
+
[attr.aria-describedby]="ngf.ariaDescribedBy()"
|
|
752
|
+
[class.ion-invalid]="ngf.showErrors()"
|
|
753
|
+
[class.ion-touched]="f().touched()"
|
|
796
754
|
>
|
|
797
755
|
@for (option of options(); track option.value) {
|
|
798
756
|
<ion-item lines="none">
|
|
799
757
|
<ion-checkbox
|
|
758
|
+
ngForgeControl
|
|
800
759
|
[checked]="checked['' + option.value]"
|
|
801
760
|
[disabled]="f().disabled() || option.disabled"
|
|
802
761
|
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
@@ -810,18 +769,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
810
769
|
}
|
|
811
770
|
</div>
|
|
812
771
|
|
|
813
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
814
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
772
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
773
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
815
774
|
} @else if (props()?.hint; as hint) {
|
|
816
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
775
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
817
776
|
}
|
|
818
|
-
`, host: {
|
|
819
|
-
|
|
820
|
-
'[id]': '`${key()}`',
|
|
821
|
-
'[attr.data-testid]': 'key()',
|
|
822
|
-
'[attr.hidden]': 'field()().hidden() || null',
|
|
823
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{display:block;color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{display:block;color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}.checkbox-group-label{margin-bottom:8px;font-weight:500}.checkbox-group{display:flex;flex-direction:column;gap:4px}ion-item{--padding-start: 0;--inner-padding-end: 0}\n"] }]
|
|
824
|
-
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
777
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}.checkbox-group-label{margin-bottom:8px;font-weight:500}.checkbox-group{display:flex;flex-direction:column;gap:4px}ion-item{--padding-start: 0;--inner-padding-end: 0}\n"] }]
|
|
778
|
+
}], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
825
779
|
|
|
826
780
|
var ionicMultiCheckbox_component = /*#__PURE__*/Object.freeze({
|
|
827
781
|
__proto__: null,
|
|
@@ -829,53 +783,15 @@ var ionicMultiCheckbox_component = /*#__PURE__*/Object.freeze({
|
|
|
829
783
|
});
|
|
830
784
|
|
|
831
785
|
class IonicRadioFieldComponent {
|
|
832
|
-
|
|
833
|
-
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
834
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
835
|
-
// Properties
|
|
836
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
837
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
838
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
839
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
786
|
+
ngf = injectNgForgeField();
|
|
840
787
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
841
788
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
842
|
-
meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
|
|
843
|
-
validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
|
|
844
|
-
defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
|
|
845
|
-
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
846
|
-
showErrors = shouldShowErrors(this.field);
|
|
847
|
-
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
|
|
848
789
|
defaultCompare = Object.is;
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
857
|
-
// Accessibility
|
|
858
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
859
|
-
/** Base ID for error elements */
|
|
860
|
-
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
861
|
-
/** Unique ID for the helper text element */
|
|
862
|
-
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
863
|
-
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
864
|
-
ariaInvalid = computed(() => {
|
|
865
|
-
const fieldState = this.field()();
|
|
866
|
-
return fieldState.invalid() && fieldState.touched();
|
|
867
|
-
}, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
|
|
868
|
-
/** Whether the field has a required validator */
|
|
869
|
-
ariaRequired = computed(() => {
|
|
870
|
-
return this.field()().required?.() === true ? true : null;
|
|
871
|
-
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
|
|
872
|
-
/** aria-describedby linking to hint OR error elements (mutually exclusive) */
|
|
873
|
-
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
874
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: IonicRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
875
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: IonicRadioFieldComponent, isStandalone: true, selector: "df-ion-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: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
876
|
-
@let f = field();
|
|
877
|
-
@let radioGroupId = key() + '-radio-group';
|
|
878
|
-
@if (label(); as label) {
|
|
790
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicRadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
791
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicRadioFieldComponent, isStandalone: true, selector: "df-ion-radio", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
|
|
792
|
+
@let f = ngf.field();
|
|
793
|
+
@let radioGroupId = ngf.key() + '-radio-group';
|
|
794
|
+
@if (ngf.label(); as label) {
|
|
879
795
|
<div class="radio-label">{{ label | dynamicText | async }}</div>
|
|
880
796
|
}
|
|
881
797
|
|
|
@@ -883,13 +799,14 @@ class IonicRadioFieldComponent {
|
|
|
883
799
|
[id]="radioGroupId"
|
|
884
800
|
[formField]="f"
|
|
885
801
|
[compareWith]="props()?.compareWith || defaultCompare"
|
|
886
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
887
|
-
[attr.aria-required]="ariaRequired()"
|
|
888
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
802
|
+
[attr.aria-invalid]="ngf.ariaInvalid()"
|
|
803
|
+
[attr.aria-required]="ngf.ariaRequired()"
|
|
804
|
+
[attr.aria-describedby]="ngf.ariaDescribedBy()"
|
|
889
805
|
>
|
|
890
806
|
@for (option of options(); track option.value) {
|
|
891
807
|
<ion-item [lines]="'none'">
|
|
892
808
|
<ion-radio
|
|
809
|
+
ngForgeControl
|
|
893
810
|
[value]="option.value"
|
|
894
811
|
[disabled]="option.disabled || false"
|
|
895
812
|
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
@@ -902,19 +819,19 @@ class IonicRadioFieldComponent {
|
|
|
902
819
|
}
|
|
903
820
|
</ion-radio-group>
|
|
904
821
|
|
|
905
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
906
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
822
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
823
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
907
824
|
} @else if (props()?.hint; as hint) {
|
|
908
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
825
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
909
826
|
}
|
|
910
|
-
`, isInline: true, styles: ["
|
|
827
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}.radio-label{font-size:.875rem;font-weight:500;margin-bottom:.5rem;color:var(--ion-text-color)}\n"], dependencies: [{ kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
911
828
|
}
|
|
912
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
829
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicRadioFieldComponent, decorators: [{
|
|
913
830
|
type: Component,
|
|
914
|
-
args: [{ selector: 'df-ion-radio', imports: [IonRadioGroup, IonRadio, IonItem, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
915
|
-
@let f = field();
|
|
916
|
-
@let radioGroupId = key() + '-radio-group';
|
|
917
|
-
@if (label(); as label) {
|
|
831
|
+
args: [{ selector: 'df-ion-radio', imports: [IonRadioGroup, IonRadio, IonItem, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
|
|
832
|
+
@let f = ngf.field();
|
|
833
|
+
@let radioGroupId = ngf.key() + '-radio-group';
|
|
834
|
+
@if (ngf.label(); as label) {
|
|
918
835
|
<div class="radio-label">{{ label | dynamicText | async }}</div>
|
|
919
836
|
}
|
|
920
837
|
|
|
@@ -922,13 +839,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
922
839
|
[id]="radioGroupId"
|
|
923
840
|
[formField]="f"
|
|
924
841
|
[compareWith]="props()?.compareWith || defaultCompare"
|
|
925
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
926
|
-
[attr.aria-required]="ariaRequired()"
|
|
927
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
842
|
+
[attr.aria-invalid]="ngf.ariaInvalid()"
|
|
843
|
+
[attr.aria-required]="ngf.ariaRequired()"
|
|
844
|
+
[attr.aria-describedby]="ngf.ariaDescribedBy()"
|
|
928
845
|
>
|
|
929
846
|
@for (option of options(); track option.value) {
|
|
930
847
|
<ion-item [lines]="'none'">
|
|
931
848
|
<ion-radio
|
|
849
|
+
ngForgeControl
|
|
932
850
|
[value]="option.value"
|
|
933
851
|
[disabled]="option.disabled || false"
|
|
934
852
|
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
@@ -941,18 +859,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
941
859
|
}
|
|
942
860
|
</ion-radio-group>
|
|
943
861
|
|
|
944
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
945
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
862
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
863
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
946
864
|
} @else if (props()?.hint; as hint) {
|
|
947
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
865
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
948
866
|
}
|
|
949
|
-
`, host: {
|
|
950
|
-
|
|
951
|
-
'[id]': '`${key()}`',
|
|
952
|
-
'[attr.data-testid]': 'key()',
|
|
953
|
-
'[attr.hidden]': 'field()().hidden() || null',
|
|
954
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{display:block;color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{display:block;color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}.radio-label{font-size:.875rem;font-weight:500;margin-bottom:.5rem;color:var(--ion-text-color)}\n"] }]
|
|
955
|
-
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
867
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}.radio-label{font-size:.875rem;font-weight:500;margin-bottom:.5rem;color:var(--ion-text-color)}\n"] }]
|
|
868
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
956
869
|
|
|
957
870
|
var ionicRadio_component = /*#__PURE__*/Object.freeze({
|
|
958
871
|
__proto__: null,
|
|
@@ -960,54 +873,22 @@ var ionicRadio_component = /*#__PURE__*/Object.freeze({
|
|
|
960
873
|
});
|
|
961
874
|
|
|
962
875
|
class IonicSelectFieldComponent {
|
|
963
|
-
|
|
964
|
-
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
965
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
966
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
967
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
968
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
969
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
876
|
+
ngf = injectNgForgeField();
|
|
970
877
|
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
971
878
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
972
|
-
meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
|
|
973
|
-
validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
|
|
974
|
-
defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
|
|
975
|
-
constructor() {
|
|
976
|
-
setupMetaTracking(this.elementRef, this.meta, { selector: 'ion-select' });
|
|
977
|
-
}
|
|
978
|
-
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
979
|
-
showErrors = shouldShowErrors(this.field);
|
|
980
|
-
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
|
|
981
879
|
defaultCompare = Object.is;
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
987
|
-
/** Unique ID for the helper text element */
|
|
988
|
-
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
989
|
-
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
990
|
-
ariaInvalid = computed(() => {
|
|
991
|
-
const fieldState = this.field()();
|
|
992
|
-
return fieldState.invalid() && fieldState.touched();
|
|
993
|
-
}, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
|
|
994
|
-
/** Whether the field has a required validator */
|
|
995
|
-
ariaRequired = computed(() => {
|
|
996
|
-
return this.field()().required?.() === true ? true : null;
|
|
997
|
-
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
|
|
998
|
-
/** aria-describedby linking to hint OR error elements (mutually exclusive) */
|
|
999
|
-
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1000
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: IonicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1001
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: IonicSelectFieldComponent, isStandalone: true, selector: "df-ion-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 }, 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: `
|
|
1002
|
-
@let f = field();
|
|
1003
|
-
@let selectId = key() + '-select';
|
|
880
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
881
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicSelectFieldComponent, isStandalone: true, selector: "df-ion-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
|
|
882
|
+
@let f = ngf.field();
|
|
883
|
+
@let selectId = ngf.key() + '-select';
|
|
1004
884
|
|
|
1005
885
|
<ion-select
|
|
886
|
+
ngForgeControl
|
|
1006
887
|
[id]="selectId"
|
|
1007
888
|
[formField]="f"
|
|
1008
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
889
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
1009
890
|
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1010
|
-
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
891
|
+
[placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
|
|
1011
892
|
[multiple]="props()?.multiple ?? false"
|
|
1012
893
|
[compareWith]="props()?.compareWith ?? defaultCompare"
|
|
1013
894
|
[interface]="props()?.interface ?? 'alert'"
|
|
@@ -1017,10 +898,7 @@ class IonicSelectFieldComponent {
|
|
|
1017
898
|
[color]="props()?.color"
|
|
1018
899
|
[fill]="props()?.fill ?? 'outline'"
|
|
1019
900
|
[shape]="props()?.shape"
|
|
1020
|
-
[attr.tabindex]="tabIndex()"
|
|
1021
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
1022
|
-
[attr.aria-required]="ariaRequired()"
|
|
1023
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
901
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
1024
902
|
>
|
|
1025
903
|
@for (option of options(); track option.value) {
|
|
1026
904
|
<ion-select-option [value]="option.value" [disabled]="option.disabled || false">
|
|
@@ -1028,25 +906,26 @@ class IonicSelectFieldComponent {
|
|
|
1028
906
|
</ion-select-option>
|
|
1029
907
|
}
|
|
1030
908
|
</ion-select>
|
|
1031
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
1032
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
909
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
910
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1033
911
|
} @else if (props()?.hint; as hint) {
|
|
1034
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
912
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1035
913
|
}
|
|
1036
|
-
`, isInline: true, styles: ["
|
|
914
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1037
915
|
}
|
|
1038
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
916
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicSelectFieldComponent, decorators: [{
|
|
1039
917
|
type: Component,
|
|
1040
|
-
args: [{ selector: 'df-ion-select', imports: [IonSelect, IonSelectOption, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1041
|
-
@let f = field();
|
|
1042
|
-
@let selectId = key() + '-select';
|
|
918
|
+
args: [{ selector: 'df-ion-select', imports: [IonSelect, IonSelectOption, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
|
|
919
|
+
@let f = ngf.field();
|
|
920
|
+
@let selectId = ngf.key() + '-select';
|
|
1043
921
|
|
|
1044
922
|
<ion-select
|
|
923
|
+
ngForgeControl
|
|
1045
924
|
[id]="selectId"
|
|
1046
925
|
[formField]="f"
|
|
1047
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
926
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
1048
927
|
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1049
|
-
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
928
|
+
[placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
|
|
1050
929
|
[multiple]="props()?.multiple ?? false"
|
|
1051
930
|
[compareWith]="props()?.compareWith ?? defaultCompare"
|
|
1052
931
|
[interface]="props()?.interface ?? 'alert'"
|
|
@@ -1056,10 +935,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1056
935
|
[color]="props()?.color"
|
|
1057
936
|
[fill]="props()?.fill ?? 'outline'"
|
|
1058
937
|
[shape]="props()?.shape"
|
|
1059
|
-
[attr.tabindex]="tabIndex()"
|
|
1060
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
1061
|
-
[attr.aria-required]="ariaRequired()"
|
|
1062
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
938
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
1063
939
|
>
|
|
1064
940
|
@for (option of options(); track option.value) {
|
|
1065
941
|
<ion-select-option [value]="option.value" [disabled]="option.disabled || false">
|
|
@@ -1067,18 +943,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1067
943
|
</ion-select-option>
|
|
1068
944
|
}
|
|
1069
945
|
</ion-select>
|
|
1070
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
1071
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
946
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
947
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1072
948
|
} @else if (props()?.hint; as hint) {
|
|
1073
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
949
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1074
950
|
}
|
|
1075
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1076
|
-
|
|
1077
|
-
'[attr.data-testid]': 'key()',
|
|
1078
|
-
'[class]': 'className()',
|
|
1079
|
-
'[attr.hidden]': 'field()().hidden() || null',
|
|
1080
|
-
}, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{display:block;color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{display:block;color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host([hidden]){display:none!important}\n"] }]
|
|
1081
|
-
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
951
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
|
|
952
|
+
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
1082
953
|
|
|
1083
954
|
var ionicSelect_component = /*#__PURE__*/Object.freeze({
|
|
1084
955
|
__proto__: null,
|
|
@@ -1086,52 +957,19 @@ var ionicSelect_component = /*#__PURE__*/Object.freeze({
|
|
|
1086
957
|
});
|
|
1087
958
|
|
|
1088
959
|
class IonicSliderFieldComponent {
|
|
1089
|
-
|
|
1090
|
-
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
1091
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
1092
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1093
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1094
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
1095
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
960
|
+
ngf = injectNgForgeField();
|
|
1096
961
|
step = input(...(ngDevMode ? [undefined, { debugName: "step" }] : /* istanbul ignore next */ []));
|
|
1097
962
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
1098
|
-
meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
|
|
1099
|
-
validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
|
|
1100
|
-
defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
|
|
1101
|
-
constructor() {
|
|
1102
|
-
setupMetaTracking(this.elementRef, this.meta);
|
|
1103
|
-
}
|
|
1104
|
-
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
1105
|
-
showErrors = shouldShowErrors(this.field);
|
|
1106
|
-
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
|
|
1107
963
|
defaultPinFormatter = (value) => String(value);
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
1113
|
-
/** Unique ID for the helper text element */
|
|
1114
|
-
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
1115
|
-
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
1116
|
-
ariaInvalid = computed(() => {
|
|
1117
|
-
const fieldState = this.field()();
|
|
1118
|
-
return fieldState.invalid() && fieldState.touched();
|
|
1119
|
-
}, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
|
|
1120
|
-
/** Whether the field has a required validator */
|
|
1121
|
-
ariaRequired = computed(() => {
|
|
1122
|
-
return this.field()().required?.() === true ? true : null;
|
|
1123
|
-
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
|
|
1124
|
-
/** aria-describedby linking to hint OR error elements (mutually exclusive) */
|
|
1125
|
-
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1126
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: IonicSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1127
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: IonicSliderFieldComponent, isStandalone: true, selector: "df-ion-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 }, step: { classPropertyName: "step", publicName: "step", 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: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
1128
|
-
@let f = field();
|
|
1129
|
-
@let inputId = key() + '-input';
|
|
964
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicSliderFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
965
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicSliderFieldComponent, isStandalone: true, selector: "df-ion-slider", inputs: { step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }, { directive: i1.NgForgeHostControl }], ngImport: i0, template: `
|
|
966
|
+
@let f = ngf.field();
|
|
967
|
+
@let inputId = ngf.key() + '-input';
|
|
1130
968
|
|
|
1131
969
|
<ion-range
|
|
1132
970
|
[id]="inputId"
|
|
1133
971
|
[formField]="f"
|
|
1134
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
972
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
1135
973
|
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1136
974
|
[min]="f().min?.() ?? props()?.min ?? 0"
|
|
1137
975
|
[max]="f().max?.() ?? props()?.max ?? 100"
|
|
@@ -1142,29 +980,25 @@ class IonicSliderFieldComponent {
|
|
|
1142
980
|
[ticks]="props()?.ticks ?? false"
|
|
1143
981
|
[snaps]="props()?.snaps ?? false"
|
|
1144
982
|
[color]="props()?.color ?? 'primary'"
|
|
1145
|
-
[attr.tabindex]="tabIndex()"
|
|
1146
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
1147
|
-
[attr.aria-required]="ariaRequired()"
|
|
1148
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1149
983
|
/>
|
|
1150
984
|
|
|
1151
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
1152
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
985
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
986
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1153
987
|
} @else if (props()?.hint; as hint) {
|
|
1154
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
988
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1155
989
|
}
|
|
1156
|
-
`, isInline: true, styles: ["
|
|
990
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonRange, selector: "ion-range", inputs: ["activeBarStart", "color", "debounce", "disabled", "dualKnobs", "label", "labelPlacement", "max", "min", "mode", "name", "pin", "pinFormatter", "snaps", "step", "ticks", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1157
991
|
}
|
|
1158
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
992
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicSliderFieldComponent, decorators: [{
|
|
1159
993
|
type: Component,
|
|
1160
|
-
args: [{ selector: 'df-ion-slider', imports: [IonRange, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1161
|
-
@let f = field();
|
|
1162
|
-
@let inputId = key() + '-input';
|
|
994
|
+
args: [{ selector: 'df-ion-slider', imports: [IonRange, IonNote, FormField, DynamicTextPipe, AsyncPipe], hostDirectives: [NgForgeFieldHost, NgForgeHostControl], template: `
|
|
995
|
+
@let f = ngf.field();
|
|
996
|
+
@let inputId = ngf.key() + '-input';
|
|
1163
997
|
|
|
1164
998
|
<ion-range
|
|
1165
999
|
[id]="inputId"
|
|
1166
1000
|
[formField]="f"
|
|
1167
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1001
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
1168
1002
|
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1169
1003
|
[min]="f().min?.() ?? props()?.min ?? 0"
|
|
1170
1004
|
[max]="f().max?.() ?? props()?.max ?? 100"
|
|
@@ -1175,24 +1009,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1175
1009
|
[ticks]="props()?.ticks ?? false"
|
|
1176
1010
|
[snaps]="props()?.snaps ?? false"
|
|
1177
1011
|
[color]="props()?.color ?? 'primary'"
|
|
1178
|
-
[attr.tabindex]="tabIndex()"
|
|
1179
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
1180
|
-
[attr.aria-required]="ariaRequired()"
|
|
1181
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1182
1012
|
/>
|
|
1183
1013
|
|
|
1184
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
1185
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1014
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
1015
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1186
1016
|
} @else if (props()?.hint; as hint) {
|
|
1187
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1017
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1188
1018
|
}
|
|
1189
|
-
`, host: {
|
|
1190
|
-
|
|
1191
|
-
'[id]': '`${key()}`',
|
|
1192
|
-
'[attr.data-testid]': 'key()',
|
|
1193
|
-
'[attr.hidden]': 'field()().hidden() || null',
|
|
1194
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{display:block;color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{display:block;color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
1195
|
-
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1019
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
1020
|
+
}], propDecorators: { step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
1196
1021
|
|
|
1197
1022
|
var ionicSlider_component = /*#__PURE__*/Object.freeze({
|
|
1198
1023
|
__proto__: null,
|
|
@@ -1201,28 +1026,13 @@ var ionicSlider_component = /*#__PURE__*/Object.freeze({
|
|
|
1201
1026
|
|
|
1202
1027
|
class IonicTextareaFieldComponent {
|
|
1203
1028
|
elementRef = inject((ElementRef));
|
|
1204
|
-
|
|
1205
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
1206
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1207
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1208
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
1209
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
1029
|
+
ngf = injectNgForgeField();
|
|
1210
1030
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
1211
|
-
meta = input(...(ngDevMode ? [undefined, { debugName: "meta" }] : /* istanbul ignore next */ []));
|
|
1212
|
-
validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
|
|
1213
|
-
defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
|
|
1214
|
-
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
1215
|
-
showErrors = shouldShowErrors(this.field);
|
|
1216
|
-
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
|
|
1217
1031
|
constructor() {
|
|
1218
|
-
// Shadow DOM - apply meta to ion-textarea element
|
|
1219
|
-
setupMetaTracking(this.elementRef, this.meta, {
|
|
1220
|
-
selector: 'ion-textarea',
|
|
1221
|
-
});
|
|
1222
1032
|
// ion-textarea encapsulates a native <textarea> in shadow DOM and does not automatically
|
|
1223
1033
|
// propagate aria-describedby to it. This effect imperatively syncs the attribute
|
|
1224
1034
|
// after a microtask to ensure Ionic has resolved the internal element.
|
|
1225
|
-
explicitEffect([this.ariaDescribedBy], ([describedBy]) => {
|
|
1035
|
+
explicitEffect([this.ngf.ariaDescribedBy], ([describedBy]) => {
|
|
1226
1036
|
queueMicrotask(() => {
|
|
1227
1037
|
const ionTextarea = this.elementRef.nativeElement.querySelector('ion-textarea');
|
|
1228
1038
|
if (ionTextarea?.getInputElement) {
|
|
@@ -1240,35 +1050,18 @@ class IonicTextareaFieldComponent {
|
|
|
1240
1050
|
});
|
|
1241
1051
|
});
|
|
1242
1052
|
}
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
1248
|
-
/** Unique ID for the helper text element */
|
|
1249
|
-
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
1250
|
-
/** Whether the field is currently in an invalid state (invalid AND touched) */
|
|
1251
|
-
ariaInvalid = computed(() => {
|
|
1252
|
-
const fieldState = this.field()();
|
|
1253
|
-
return fieldState.invalid() && fieldState.touched();
|
|
1254
|
-
}, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
|
|
1255
|
-
/** Whether the field has a required validator */
|
|
1256
|
-
ariaRequired = computed(() => {
|
|
1257
|
-
return this.field()().required?.() === true ? true : null;
|
|
1258
|
-
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
|
|
1259
|
-
/** aria-describedby linking to hint OR error elements (mutually exclusive) */
|
|
1260
|
-
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1261
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: IonicTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1262
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: IonicTextareaFieldComponent, isStandalone: true, selector: "df-ion-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 }, 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: `
|
|
1263
|
-
@let f = field();
|
|
1264
|
-
@let textareaId = key() + '-textarea';
|
|
1053
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicTextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1054
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicTextareaFieldComponent, isStandalone: true, selector: "df-ion-textarea", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
|
|
1055
|
+
@let f = ngf.field();
|
|
1056
|
+
@let textareaId = ngf.key() + '-textarea';
|
|
1265
1057
|
|
|
1266
1058
|
<ion-textarea
|
|
1059
|
+
ngForgeControl
|
|
1267
1060
|
[id]="textareaId"
|
|
1268
1061
|
[formField]="f"
|
|
1269
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1062
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
1270
1063
|
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1271
|
-
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1064
|
+
[placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
|
|
1272
1065
|
[rows]="props()?.rows ?? 4"
|
|
1273
1066
|
[autoGrow]="props()?.autoGrow ?? false"
|
|
1274
1067
|
[counter]="props()?.counter ?? false"
|
|
@@ -1278,29 +1071,27 @@ class IonicTextareaFieldComponent {
|
|
|
1278
1071
|
[fill]="props()?.fill ?? 'outline'"
|
|
1279
1072
|
[shape]="props()?.shape"
|
|
1280
1073
|
[readonly]="f().readonly()"
|
|
1281
|
-
[helperText]="errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined"
|
|
1282
|
-
[attr.tabindex]="tabIndex()"
|
|
1283
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
1284
|
-
[attr.aria-required]="ariaRequired()"
|
|
1285
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1074
|
+
[helperText]="ngf.errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined"
|
|
1075
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
1286
1076
|
/>
|
|
1287
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
1288
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1077
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
1078
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1289
1079
|
}
|
|
1290
|
-
`, isInline: true, styles: ["
|
|
1080
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1291
1081
|
}
|
|
1292
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1082
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicTextareaFieldComponent, decorators: [{
|
|
1293
1083
|
type: Component,
|
|
1294
|
-
args: [{ selector: 'df-ion-textarea', imports: [IonTextarea, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1295
|
-
@let f = field();
|
|
1296
|
-
@let textareaId = key() + '-textarea';
|
|
1084
|
+
args: [{ selector: 'df-ion-textarea', imports: [IonTextarea, IonNote, FormField, DynamicTextPipe, AsyncPipe, NgForgeControl], hostDirectives: [NgForgeFieldHost], template: `
|
|
1085
|
+
@let f = ngf.field();
|
|
1086
|
+
@let textareaId = ngf.key() + '-textarea';
|
|
1297
1087
|
|
|
1298
1088
|
<ion-textarea
|
|
1089
|
+
ngForgeControl
|
|
1299
1090
|
[id]="textareaId"
|
|
1300
1091
|
[formField]="f"
|
|
1301
|
-
[label]="(label() | dynamicText | async) ?? undefined"
|
|
1092
|
+
[label]="(ngf.label() | dynamicText | async) ?? undefined"
|
|
1302
1093
|
[labelPlacement]="props()?.labelPlacement ?? 'stacked'"
|
|
1303
|
-
[placeholder]="(placeholder() | dynamicText | async) ?? ''"
|
|
1094
|
+
[placeholder]="(ngf.placeholder() | dynamicText | async) ?? ''"
|
|
1304
1095
|
[rows]="props()?.rows ?? 4"
|
|
1305
1096
|
[autoGrow]="props()?.autoGrow ?? false"
|
|
1306
1097
|
[counter]="props()?.counter ?? false"
|
|
@@ -1310,22 +1101,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1310
1101
|
[fill]="props()?.fill ?? 'outline'"
|
|
1311
1102
|
[shape]="props()?.shape"
|
|
1312
1103
|
[readonly]="f().readonly()"
|
|
1313
|
-
[helperText]="errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined"
|
|
1314
|
-
[attr.tabindex]="tabIndex()"
|
|
1315
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
1316
|
-
[attr.aria-required]="ariaRequired()"
|
|
1317
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1104
|
+
[helperText]="ngf.errorsToDisplay().length === 0 ? ((props()?.hint | dynamicText | async) ?? undefined) : undefined"
|
|
1105
|
+
[attr.tabindex]="ngf.tabIndex()"
|
|
1318
1106
|
/>
|
|
1319
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
1320
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1107
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
1108
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1321
1109
|
}
|
|
1322
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1323
|
-
|
|
1324
|
-
'[attr.data-testid]': 'key()',
|
|
1325
|
-
'[class]': 'className()',
|
|
1326
|
-
'[attr.hidden]': 'field()().hidden() || null',
|
|
1327
|
-
}, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{display:block;color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{display:block;color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host([hidden]){display:none!important}\n"] }]
|
|
1328
|
-
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1110
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host([hidden]){display:none!important}\n"] }]
|
|
1111
|
+
}], ctorParameters: () => [], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
1329
1112
|
|
|
1330
1113
|
var ionicTextarea_component = /*#__PURE__*/Object.freeze({
|
|
1331
1114
|
__proto__: null,
|
|
@@ -1333,14 +1116,11 @@ var ionicTextarea_component = /*#__PURE__*/Object.freeze({
|
|
|
1333
1116
|
});
|
|
1334
1117
|
|
|
1335
1118
|
/**
|
|
1336
|
-
*
|
|
1337
|
-
*
|
|
1338
|
-
*
|
|
1339
|
-
* We use FormCheckboxControl because ion-toggle is a boolean checkbox-like control.
|
|
1340
|
-
* The Field directive binds to the `checked` model for checkbox controls.
|
|
1119
|
+
* ion-toggle wrapper implementing FormCheckboxControl. Rendered inside
|
|
1120
|
+
* `df-ion-toggle`. `NgForgeControl` on `<ion-toggle>` claims the ambient
|
|
1121
|
+
* parent NgForgeField and routes meta + aria onto that element.
|
|
1341
1122
|
*/
|
|
1342
1123
|
class IonicToggleControlComponent {
|
|
1343
|
-
elementRef = inject((ElementRef));
|
|
1344
1124
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
1345
1125
|
// FormCheckboxControl implementation
|
|
1346
1126
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -1364,29 +1144,9 @@ class IonicToggleControlComponent {
|
|
|
1364
1144
|
color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
1365
1145
|
enableOnOffLabels = input(false, ...(ngDevMode ? [{ debugName: "enableOnOffLabels" }] : /* istanbul ignore next */ []));
|
|
1366
1146
|
tabIndex = input(undefined, ...(ngDevMode ? [{ debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
// Shadow DOM - apply meta to ion-toggle element
|
|
1371
|
-
setupMetaTracking(this.elementRef, this.meta, {
|
|
1372
|
-
selector: 'ion-toggle',
|
|
1373
|
-
});
|
|
1374
|
-
}
|
|
1375
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1376
|
-
// Computed ARIA attributes
|
|
1377
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1378
|
-
/** aria-invalid: true when field is invalid AND touched */
|
|
1379
|
-
ariaInvalid = computed(() => {
|
|
1380
|
-
return this.invalid() && this.touched();
|
|
1381
|
-
}, ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
|
|
1382
|
-
/** aria-required: true if field is required, null otherwise */
|
|
1383
|
-
ariaRequired = computed(() => {
|
|
1384
|
-
return this.required() ? true : null;
|
|
1385
|
-
}, ...(ngDevMode ? [{ debugName: "ariaRequired" }] : /* istanbul ignore next */ []));
|
|
1386
|
-
/** aria-readonly: true if field is readonly, null otherwise */
|
|
1387
|
-
ariaReadonly = computed(() => {
|
|
1388
|
-
return this.readonly() ? true : null;
|
|
1389
|
-
}, ...(ngDevMode ? [{ debugName: "ariaReadonly" }] : /* istanbul ignore next */ []));
|
|
1147
|
+
// aria-invalid / aria-required / aria-describedby are written to <ion-toggle>
|
|
1148
|
+
// by NgForgeControl. aria-readonly is Ionic-specific and stays template-side.
|
|
1149
|
+
ariaReadonly = computed(() => (this.readonly() ? true : null), ...(ngDevMode ? [{ debugName: "ariaReadonly" }] : /* istanbul ignore next */ []));
|
|
1390
1150
|
/** Computed checked state - ensures proper boolean conversion for ion-toggle */
|
|
1391
1151
|
isChecked = computed(() => {
|
|
1392
1152
|
return this.checked() === true;
|
|
@@ -1409,9 +1169,10 @@ class IonicToggleControlComponent {
|
|
|
1409
1169
|
onBlur() {
|
|
1410
1170
|
this.touched.set(true);
|
|
1411
1171
|
}
|
|
1412
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1413
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.
|
|
1172
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicToggleControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1173
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: IonicToggleControlComponent, isStandalone: true, selector: "df-ion-toggle-control", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", 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 }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, labelPlacement: { classPropertyName: "labelPlacement", publicName: "labelPlacement", isSignal: true, isRequired: false, transformFunction: null }, justify: { classPropertyName: "justify", publicName: "justify", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, enableOnOffLabels: { classPropertyName: "enableOnOffLabels", publicName: "enableOnOffLabels", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touched: "touchedChange" }, host: { styleAttribute: "display: block" }, ngImport: i0, template: `
|
|
1414
1174
|
<ion-toggle
|
|
1175
|
+
ngForgeControl
|
|
1415
1176
|
[checked]="isChecked()"
|
|
1416
1177
|
(ionChange)="onToggleChange($event)"
|
|
1417
1178
|
(ionBlur)="onBlur()"
|
|
@@ -1421,19 +1182,17 @@ class IonicToggleControlComponent {
|
|
|
1421
1182
|
[enableOnOffLabels]="enableOnOffLabels()"
|
|
1422
1183
|
[disabled]="isEffectivelyDisabled()"
|
|
1423
1184
|
[attr.tabindex]="tabIndex()"
|
|
1424
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
1425
|
-
[attr.aria-required]="ariaRequired()"
|
|
1426
1185
|
[attr.aria-readonly]="ariaReadonly()"
|
|
1427
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1428
1186
|
>
|
|
1429
1187
|
<ng-content />
|
|
1430
1188
|
</ion-toggle>
|
|
1431
|
-
`, isInline: true, styles: ["
|
|
1189
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonToggle, selector: "ion-toggle", inputs: ["checked", "color", "disabled", "enableOnOffLabels", "errorText", "helperText", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "directive", type: NgForgeControl, selector: "[ngForgeControl]", inputs: ["ngForgeControl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1432
1190
|
}
|
|
1433
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1191
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicToggleControlComponent, decorators: [{
|
|
1434
1192
|
type: Component,
|
|
1435
|
-
args: [{ selector: 'df-ion-toggle-control', imports: [IonToggle], template: `
|
|
1193
|
+
args: [{ selector: 'df-ion-toggle-control', imports: [IonToggle, NgForgeControl], template: `
|
|
1436
1194
|
<ion-toggle
|
|
1195
|
+
ngForgeControl
|
|
1437
1196
|
[checked]="isChecked()"
|
|
1438
1197
|
(ionChange)="onToggleChange($event)"
|
|
1439
1198
|
(ionBlur)="onBlur()"
|
|
@@ -1443,104 +1202,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1443
1202
|
[enableOnOffLabels]="enableOnOffLabels()"
|
|
1444
1203
|
[disabled]="isEffectivelyDisabled()"
|
|
1445
1204
|
[attr.tabindex]="tabIndex()"
|
|
1446
|
-
[attr.aria-invalid]="ariaInvalid()"
|
|
1447
|
-
[attr.aria-required]="ariaRequired()"
|
|
1448
1205
|
[attr.aria-readonly]="ariaReadonly()"
|
|
1449
|
-
[attr.aria-describedby]="ariaDescribedBy()"
|
|
1450
1206
|
>
|
|
1451
1207
|
<ng-content />
|
|
1452
1208
|
</ion-toggle>
|
|
1453
1209
|
`, host: {
|
|
1454
1210
|
style: 'display: block',
|
|
1455
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["
|
|
1456
|
-
}],
|
|
1211
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n"] }]
|
|
1212
|
+
}], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], labelPlacement: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPlacement", required: false }] }], justify: [{ type: i0.Input, args: [{ isSignal: true, alias: "justify", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], enableOnOffLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableOnOffLabels", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }] } });
|
|
1457
1213
|
|
|
1458
1214
|
class IonicToggleFieldComponent {
|
|
1459
|
-
|
|
1460
|
-
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
1461
|
-
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
1462
|
-
// Properties
|
|
1463
|
-
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1464
|
-
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1465
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
1466
|
-
tabIndex = input(...(ngDevMode ? [undefined, { debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
1215
|
+
ngf = injectNgForgeField();
|
|
1467
1216
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : /* istanbul ignore next */ []));
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
setupMetaTracking(this.elementRef, this.meta);
|
|
1473
|
-
}
|
|
1474
|
-
resolvedErrors = createResolvedErrorsSignal(this.field, this.validationMessages, this.defaultValidationMessages);
|
|
1475
|
-
showErrors = shouldShowErrors(this.field);
|
|
1476
|
-
errorsToDisplay = computed(() => (this.showErrors() ? this.resolvedErrors() : []), ...(ngDevMode ? [{ debugName: "errorsToDisplay" }] : /* istanbul ignore next */ []));
|
|
1477
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1478
|
-
// Accessibility
|
|
1479
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1480
|
-
/** Base ID for error elements */
|
|
1481
|
-
errorId = computed(() => `${this.key()}-error`, ...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
1482
|
-
/** Unique ID for the helper text element */
|
|
1483
|
-
hintId = computed(() => `${this.key()}-hint`, ...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
1484
|
-
/** aria-describedby linking to hint OR error elements (mutually exclusive) */
|
|
1485
|
-
ariaDescribedBy = createAriaDescribedBySignal(this.errorsToDisplay, this.errorId, this.hintId, () => !!this.props()?.hint);
|
|
1486
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: IonicToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1487
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: IonicToggleFieldComponent, isStandalone: true, selector: "df-ion-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 }, 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: { "class": "className()", "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "field()().hidden() || null" } }, ngImport: i0, template: `
|
|
1488
|
-
@let f = field();
|
|
1489
|
-
@let toggleId = key() + '-toggle';
|
|
1217
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicToggleFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1218
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonicToggleFieldComponent, isStandalone: true, selector: "df-ion-toggle", inputs: { props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1.NgForgeFieldHost }], ngImport: i0, template: `
|
|
1219
|
+
@let f = ngf.field();
|
|
1220
|
+
@let toggleId = ngf.key() + '-toggle';
|
|
1490
1221
|
|
|
1491
1222
|
<df-ion-toggle-control
|
|
1492
1223
|
[id]="toggleId"
|
|
1493
1224
|
[formField]="f"
|
|
1494
|
-
[meta]="meta()"
|
|
1495
1225
|
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
1496
1226
|
[justify]="props()?.justify"
|
|
1497
1227
|
[color]="props()?.color ?? 'primary'"
|
|
1498
1228
|
[enableOnOffLabels]="props()?.enableOnOffLabels ?? false"
|
|
1499
|
-
[tabIndex]="tabIndex()"
|
|
1500
|
-
[ariaDescribedBy]="ariaDescribedBy()"
|
|
1229
|
+
[tabIndex]="ngf.tabIndex()"
|
|
1501
1230
|
>
|
|
1502
|
-
{{ label() | dynamicText | async }}
|
|
1231
|
+
{{ ngf.label() | dynamicText | async }}
|
|
1503
1232
|
</df-ion-toggle-control>
|
|
1504
1233
|
|
|
1505
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
1506
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1234
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
1235
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1507
1236
|
} @else if (props()?.hint; as hint) {
|
|
1508
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1237
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1509
1238
|
}
|
|
1510
|
-
`, isInline: true, styles: ["
|
|
1239
|
+
`, isInline: true, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"], dependencies: [{ kind: "component", type: IonicToggleControlComponent, selector: "df-ion-toggle-control", inputs: ["checked", "touched", "disabled", "readonly", "invalid", "required", "labelPlacement", "justify", "color", "enableOnOffLabels", "tabIndex"], outputs: ["checkedChange", "touchedChange"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1511
1240
|
}
|
|
1512
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1241
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonicToggleFieldComponent, decorators: [{
|
|
1513
1242
|
type: Component,
|
|
1514
|
-
args: [{ selector: 'df-ion-toggle', imports: [IonicToggleControlComponent, IonNote, FormField, DynamicTextPipe, AsyncPipe], template: `
|
|
1515
|
-
@let f = field();
|
|
1516
|
-
@let toggleId = key() + '-toggle';
|
|
1243
|
+
args: [{ selector: 'df-ion-toggle', imports: [IonicToggleControlComponent, IonNote, FormField, DynamicTextPipe, AsyncPipe], hostDirectives: [NgForgeFieldHost], template: `
|
|
1244
|
+
@let f = ngf.field();
|
|
1245
|
+
@let toggleId = ngf.key() + '-toggle';
|
|
1517
1246
|
|
|
1518
1247
|
<df-ion-toggle-control
|
|
1519
1248
|
[id]="toggleId"
|
|
1520
1249
|
[formField]="f"
|
|
1521
|
-
[meta]="meta()"
|
|
1522
1250
|
[labelPlacement]="props()?.labelPlacement ?? 'end'"
|
|
1523
1251
|
[justify]="props()?.justify"
|
|
1524
1252
|
[color]="props()?.color ?? 'primary'"
|
|
1525
1253
|
[enableOnOffLabels]="props()?.enableOnOffLabels ?? false"
|
|
1526
|
-
[tabIndex]="tabIndex()"
|
|
1527
|
-
[ariaDescribedBy]="ariaDescribedBy()"
|
|
1254
|
+
[tabIndex]="ngf.tabIndex()"
|
|
1528
1255
|
>
|
|
1529
|
-
{{ label() | dynamicText | async }}
|
|
1256
|
+
{{ ngf.label() | dynamicText | async }}
|
|
1530
1257
|
</df-ion-toggle-control>
|
|
1531
1258
|
|
|
1532
|
-
@if (errorsToDisplay()[0]; as error) {
|
|
1533
|
-
<ion-note color="danger" class="df-ion-error" [id]="errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1259
|
+
@if (ngf.errorsToDisplay()[0]; as error) {
|
|
1260
|
+
<ion-note color="danger" class="df-ion-error" [id]="ngf.errorId()" role="alert">{{ error.message }}</ion-note>
|
|
1534
1261
|
} @else if (props()?.hint; as hint) {
|
|
1535
|
-
<ion-note class="df-ion-hint" [id]="hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1262
|
+
<ion-note class="df-ion-hint" [id]="ngf.hintId()">{{ hint | dynamicText | async }}</ion-note>
|
|
1536
1263
|
}
|
|
1537
|
-
`, host: {
|
|
1538
|
-
|
|
1539
|
-
'[id]': '`${key()}`',
|
|
1540
|
-
'[attr.data-testid]': 'key()',
|
|
1541
|
-
'[attr.hidden]': 'field()().hidden() || null',
|
|
1542
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{--df-field-gap: .5rem;--df-label-font-weight: 500;--df-label-color: inherit;--df-hint-color: var(--ion-color-medium, #92949c);--df-hint-font-size: .875rem;--df-error-color: var(--ion-color-danger, #eb445a);--df-error-font-size: .875rem}.df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight);color:var(--df-label-color)}.df-ion-hint{display:block;color:var(--df-hint-color);font-size:var(--df-hint-font-size)}.df-ion-error{display:block;color:var(--df-error-color);font-size:var(--df-error-font-size)}:host([hidden]){display:none!important}ion-input.ng-invalid.ng-touched,ion-textarea.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-select.ng-invalid.ng-touched{--highlight-color: var(--ion-color-danger);--border-color: var(--ion-color-danger)}ion-checkbox.ng-invalid.ng-touched{--checkbox-background-checked: var(--ion-color-danger);--border-color: var(--ion-color-danger);--border-color-checked: var(--ion-color-danger)}ion-radio.ng-invalid.ng-touched{--color: var(--ion-color-danger);--color-checked: var(--ion-color-danger)}ion-range.ng-invalid.ng-touched{--bar-background: var(--ion-color-danger);--knob-background: var(--ion-color-danger)}ion-toggle.ng-invalid.ng-touched{--track-background: var(--ion-color-danger-tint);--track-background-checked: var(--ion-color-danger);--handle-background-checked: var(--ion-color-danger-contrast)}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
1543
|
-
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], meta: [{ type: i0.Input, args: [{ isSignal: true, alias: "meta", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
|
|
1264
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-field{display:flex;flex-direction:column;gap:var(--df-field-gap, .5rem);width:100%}.df-ion-label{font-weight:var(--df-label-font-weight, 500);color:var(--df-label-color, inherit)}.df-ion-hint{display:block;color:var(--df-hint-color, var(--ion-color-medium, #92949c));font-size:var(--df-hint-font-size, .875rem)}.df-ion-error{display:block;color:var(--df-error-color, var(--ion-color-danger, #eb445a));font-size:var(--df-error-font-size, .875rem)}:host([hidden]){display:none!important}\n", ":host{display:block}:host([hidden]){display:none!important}\n"] }]
|
|
1265
|
+
}], propDecorators: { props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
1544
1266
|
|
|
1545
1267
|
var ionicToggle_component = /*#__PURE__*/Object.freeze({
|
|
1546
1268
|
__proto__: null,
|
|
@@ -1637,8 +1359,12 @@ function buttonFieldMapper(fieldDef) {
|
|
|
1637
1359
|
* disabled state resolution based on form validity and options.
|
|
1638
1360
|
*/
|
|
1639
1361
|
|
|
1362
|
+
const VALUE_FIELD_TYPES_BASE = {
|
|
1363
|
+
renderReadyWhen: ['field'],
|
|
1364
|
+
};
|
|
1640
1365
|
const BUTTON_FIELD_TYPES_BASE = {
|
|
1641
1366
|
renderReadyWhen: [],
|
|
1367
|
+
valueHandling: 'exclude',
|
|
1642
1368
|
};
|
|
1643
1369
|
/**
|
|
1644
1370
|
* Ionic field type definitions
|
|
@@ -1651,87 +1377,83 @@ const IONIC_FIELD_TYPES = [
|
|
|
1651
1377
|
mapper: valueFieldMapper,
|
|
1652
1378
|
propsToMeta: ['type'],
|
|
1653
1379
|
scope: ['text-input', 'numeric'],
|
|
1380
|
+
addons: {
|
|
1381
|
+
slots: ['prefix', 'suffix'],
|
|
1382
|
+
},
|
|
1383
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1654
1384
|
},
|
|
1655
1385
|
{
|
|
1656
1386
|
name: IonicField.Select,
|
|
1657
1387
|
loadComponent: () => Promise.resolve().then(function () { return ionicSelect_component; }),
|
|
1658
1388
|
mapper: optionsFieldMapper,
|
|
1659
1389
|
scope: 'single-select',
|
|
1390
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1660
1391
|
},
|
|
1661
1392
|
{
|
|
1662
1393
|
name: IonicField.Checkbox,
|
|
1663
1394
|
loadComponent: () => Promise.resolve().then(function () { return ionicCheckbox_component; }),
|
|
1664
1395
|
mapper: checkboxFieldMapper,
|
|
1665
1396
|
scope: 'boolean',
|
|
1397
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1666
1398
|
},
|
|
1667
1399
|
{
|
|
1668
1400
|
name: IonicField.Button,
|
|
1669
1401
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1670
1402
|
mapper: buttonFieldMapper,
|
|
1671
|
-
valueHandling: 'exclude',
|
|
1672
1403
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1673
1404
|
},
|
|
1674
1405
|
{
|
|
1675
1406
|
name: IonicField.Submit,
|
|
1676
1407
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1677
1408
|
mapper: submitButtonFieldMapper,
|
|
1678
|
-
valueHandling: 'exclude',
|
|
1679
1409
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1680
1410
|
},
|
|
1681
1411
|
{
|
|
1682
1412
|
name: IonicField.Next,
|
|
1683
1413
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1684
1414
|
mapper: nextButtonFieldMapper,
|
|
1685
|
-
valueHandling: 'exclude',
|
|
1686
1415
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1687
1416
|
},
|
|
1688
1417
|
{
|
|
1689
1418
|
name: IonicField.Previous,
|
|
1690
1419
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1691
1420
|
mapper: previousButtonFieldMapper,
|
|
1692
|
-
valueHandling: 'exclude',
|
|
1693
1421
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1694
1422
|
},
|
|
1695
1423
|
{
|
|
1696
1424
|
name: IonicField.AddArrayItem,
|
|
1697
1425
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1698
1426
|
mapper: addArrayItemButtonMapper,
|
|
1699
|
-
valueHandling: 'exclude',
|
|
1700
1427
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1701
1428
|
},
|
|
1702
1429
|
{
|
|
1703
1430
|
name: IonicField.PrependArrayItem,
|
|
1704
1431
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1705
1432
|
mapper: prependArrayItemButtonMapper,
|
|
1706
|
-
valueHandling: 'exclude',
|
|
1707
1433
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1708
1434
|
},
|
|
1709
1435
|
{
|
|
1710
1436
|
name: IonicField.InsertArrayItem,
|
|
1711
1437
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1712
1438
|
mapper: insertArrayItemButtonMapper,
|
|
1713
|
-
valueHandling: 'exclude',
|
|
1714
1439
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1715
1440
|
},
|
|
1716
1441
|
{
|
|
1717
1442
|
name: IonicField.RemoveArrayItem,
|
|
1718
1443
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1719
1444
|
mapper: removeArrayItemButtonMapper,
|
|
1720
|
-
valueHandling: 'exclude',
|
|
1721
1445
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1722
1446
|
},
|
|
1723
1447
|
{
|
|
1724
1448
|
name: IonicField.PopArrayItem,
|
|
1725
1449
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1726
1450
|
mapper: popArrayItemButtonMapper,
|
|
1727
|
-
valueHandling: 'exclude',
|
|
1728
1451
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1729
1452
|
},
|
|
1730
1453
|
{
|
|
1731
1454
|
name: IonicField.ShiftArrayItem,
|
|
1732
1455
|
loadComponent: () => Promise.resolve().then(function () { return ionicButton_component; }),
|
|
1733
1456
|
mapper: shiftArrayItemButtonMapper,
|
|
1734
|
-
valueHandling: 'exclude',
|
|
1735
1457
|
...BUTTON_FIELD_TYPES_BASE,
|
|
1736
1458
|
},
|
|
1737
1459
|
{
|
|
@@ -1740,36 +1462,42 @@ const IONIC_FIELD_TYPES = [
|
|
|
1740
1462
|
mapper: valueFieldMapper,
|
|
1741
1463
|
propsToMeta: ['rows'],
|
|
1742
1464
|
scope: 'text-input',
|
|
1465
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1743
1466
|
},
|
|
1744
1467
|
{
|
|
1745
1468
|
name: IonicField.Radio,
|
|
1746
1469
|
loadComponent: () => Promise.resolve().then(function () { return ionicRadio_component; }),
|
|
1747
1470
|
mapper: optionsFieldMapper,
|
|
1748
1471
|
scope: 'single-select',
|
|
1472
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1749
1473
|
},
|
|
1750
1474
|
{
|
|
1751
1475
|
name: IonicField.MultiCheckbox,
|
|
1752
1476
|
loadComponent: () => Promise.resolve().then(function () { return ionicMultiCheckbox_component; }),
|
|
1753
1477
|
mapper: optionsFieldMapper,
|
|
1754
1478
|
scope: 'multi-select',
|
|
1479
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1755
1480
|
},
|
|
1756
1481
|
{
|
|
1757
1482
|
name: IonicField.Datepicker,
|
|
1758
1483
|
loadComponent: () => Promise.resolve().then(function () { return ionicDatepicker_component; }),
|
|
1759
1484
|
mapper: datepickerFieldMapper,
|
|
1760
1485
|
scope: 'date',
|
|
1486
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1761
1487
|
},
|
|
1762
1488
|
{
|
|
1763
1489
|
name: IonicField.Slider,
|
|
1764
1490
|
loadComponent: () => Promise.resolve().then(function () { return ionicSlider_component; }),
|
|
1765
1491
|
mapper: valueFieldMapper,
|
|
1766
1492
|
scope: 'numeric',
|
|
1493
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1767
1494
|
},
|
|
1768
1495
|
{
|
|
1769
1496
|
name: IonicField.Toggle,
|
|
1770
1497
|
loadComponent: () => Promise.resolve().then(function () { return ionicToggle_component; }),
|
|
1771
1498
|
mapper: checkboxFieldMapper,
|
|
1772
1499
|
scope: 'boolean',
|
|
1500
|
+
...VALUE_FIELD_TYPES_BASE,
|
|
1773
1501
|
},
|
|
1774
1502
|
];
|
|
1775
1503
|
|
|
@@ -1780,19 +1508,191 @@ const IONIC_FIELD_TYPES = [
|
|
|
1780
1508
|
*/
|
|
1781
1509
|
|
|
1782
1510
|
function withIonicFields(config) {
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
{
|
|
1511
|
+
// Always include the addons feature — ion-icon / ion-button are part of
|
|
1512
|
+
// the canonical Ionic surface.
|
|
1513
|
+
const base = [...IONIC_FIELD_TYPES, withIonicAddons()];
|
|
1514
|
+
if (config) {
|
|
1515
|
+
base.push({
|
|
1789
1516
|
ɵkind: 'ionic-config',
|
|
1790
1517
|
ɵproviders: [{ provide: IONIC_CONFIG, useValue: config }],
|
|
1791
|
-
}
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
return
|
|
1518
|
+
});
|
|
1519
|
+
return base;
|
|
1520
|
+
}
|
|
1521
|
+
return base;
|
|
1522
|
+
}
|
|
1523
|
+
/* -- Ionic addon kinds ------------------------------------------------- */
|
|
1524
|
+
const ION_ICON_KIND = {
|
|
1525
|
+
kind: 'ion-icon',
|
|
1526
|
+
loadComponent: () => Promise.resolve().then(function () { return ionIconAddon_component; }).then((m) => m.IonIconAddonComponent),
|
|
1527
|
+
validate: (addon, fieldKey) => {
|
|
1528
|
+
if (typeof addon.icon !== 'string' || addon.icon.length === 0) {
|
|
1529
|
+
throw new DynamicFormError(`Addon kind 'ion-icon' requires a non-empty 'icon' string (field: '${fieldKey}').`);
|
|
1530
|
+
}
|
|
1531
|
+
},
|
|
1532
|
+
};
|
|
1533
|
+
const ION_BUTTON_KIND = {
|
|
1534
|
+
kind: 'ion-button',
|
|
1535
|
+
loadComponent: () => Promise.resolve().then(function () { return ionButtonAddon_component; }).then((m) => m.IonButtonAddonComponent),
|
|
1536
|
+
validate: (addon, fieldKey) => {
|
|
1537
|
+
// Exactly one of preset / actionRef / action — validator drops the addon
|
|
1538
|
+
// (with warning) if the rule is violated.
|
|
1539
|
+
const set = [addon.preset, addon.actionRef, addon.action].filter((v) => v !== undefined);
|
|
1540
|
+
if (set.length > 1) {
|
|
1541
|
+
throw new DynamicFormError(`Addon kind 'ion-button' on field '${fieldKey}' has more than one of preset/actionRef/action — exactly one allowed.`);
|
|
1542
|
+
}
|
|
1543
|
+
// Icon-only buttons require ariaLabel for screen readers.
|
|
1544
|
+
if (addon.icon && !addon.label && !addon.ariaLabel) {
|
|
1545
|
+
throw new DynamicFormError(`Addon kind 'ion-button' on field '${fieldKey}' is icon-only — provide 'ariaLabel' for accessibility.`);
|
|
1546
|
+
}
|
|
1547
|
+
},
|
|
1548
|
+
};
|
|
1549
|
+
/**
|
|
1550
|
+
* Register Ionic-shipped addon kinds (`ion-icon`, `ion-button`) standalone.
|
|
1551
|
+
*
|
|
1552
|
+
* **Most users don't need this** — `withIonicFields()` auto-includes
|
|
1553
|
+
* these kinds. Call `withIonicAddons()` directly only when you want
|
|
1554
|
+
* Ionic addon kinds without the Ionic field types (e.g., a custom
|
|
1555
|
+
* field set that wants to render `ion-icon` prefixes), or when you're
|
|
1556
|
+
* stitching addons through a different DI scope.
|
|
1557
|
+
*
|
|
1558
|
+
* @example
|
|
1559
|
+
* ```typescript
|
|
1560
|
+
* // Custom field types + Ionic addon kinds.
|
|
1561
|
+
* provideDynamicForm(
|
|
1562
|
+
* ...myCustomFields(),
|
|
1563
|
+
* withIonicAddons(),
|
|
1564
|
+
* );
|
|
1565
|
+
* ```
|
|
1566
|
+
*
|
|
1567
|
+
* Adapter authors who need to override a kind with a customised renderer
|
|
1568
|
+
* should call `withCustomAddon(...)` directly instead.
|
|
1569
|
+
*/
|
|
1570
|
+
function withIonicAddons() {
|
|
1571
|
+
return {
|
|
1572
|
+
ɵkind: 'addons',
|
|
1573
|
+
ɵproviders: [
|
|
1574
|
+
{ provide: ADDON_KIND_DEFINITIONS, useValue: ION_ICON_KIND, multi: true },
|
|
1575
|
+
{ provide: ADDON_KIND_DEFINITIONS, useValue: ION_BUTTON_KIND, multi: true },
|
|
1576
|
+
],
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/**
|
|
1581
|
+
* Renderer for the `ion-button` addon kind.
|
|
1582
|
+
*
|
|
1583
|
+
* Wraps Ionic's `<ion-button>`. Click dispatch (preset / actionRef /
|
|
1584
|
+
* action precedence, multi-set warning, `disabled` / `loading`
|
|
1585
|
+
* resolution) lives on `NgForgeAddonAction`; this component focuses on
|
|
1586
|
+
* the visual layer. While `action.loading()`, an `<ion-spinner>` is
|
|
1587
|
+
* rendered in place of the icon and the button is disabled.
|
|
1588
|
+
*/
|
|
1589
|
+
class IonButtonAddonComponent {
|
|
1590
|
+
action = injectNgForgeAddonAction();
|
|
1591
|
+
/** Re-exposed for template binding — same signal stored on the directive. */
|
|
1592
|
+
addon = this.action.addon;
|
|
1593
|
+
label = computed(() => this.addon().label, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1594
|
+
ariaLabel = computed(() => this.addon().ariaLabel, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
1595
|
+
icon = computed(() => this.addon().icon, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
1596
|
+
/** Default color is undefined so the button inherits the theme's text color
|
|
1597
|
+
* (Ionic's `medium` would force low-contrast grey, which fails WCAG on dark
|
|
1598
|
+
* surfaces). Consumers can still set `color: 'primary' | 'success' | ...`
|
|
1599
|
+
* explicitly when they want adapter-styled coloring. */
|
|
1600
|
+
color = computed(() => this.addon().color, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
1601
|
+
fill = computed(() => this.addon().fill ?? 'clear', ...(ngDevMode ? [{ debugName: "fill" }] : /* istanbul ignore next */ []));
|
|
1602
|
+
/** Icon-only when there is an icon but no label — drives the `slot` choice.
|
|
1603
|
+
* Truthy check on `label` mirrors Material's heuristic; empty-string label
|
|
1604
|
+
* is treated as "no label" so the button doesn't render an invisible text
|
|
1605
|
+
* slot beside the icon. */
|
|
1606
|
+
iconOnly = computed(() => !!this.icon() && !this.label(), ...(ngDevMode ? [{ debugName: "iconOnly" }] : /* istanbul ignore next */ []));
|
|
1607
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonButtonAddonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1608
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: IonButtonAddonComponent, isStandalone: true, selector: "df-ion-button-addon", hostDirectives: [{ directive: i1.NgForgeAddonAction }], ngImport: i0, template: `
|
|
1609
|
+
<ion-button
|
|
1610
|
+
[attr.color]="color() ?? null"
|
|
1611
|
+
[fill]="fill()"
|
|
1612
|
+
[disabled]="action.disabled() || action.loading()"
|
|
1613
|
+
[attr.aria-label]="(ariaLabel() | dynamicText | async) ?? null"
|
|
1614
|
+
[attr.aria-busy]="action.loading() || null"
|
|
1615
|
+
(click)="action.dispatch()"
|
|
1616
|
+
>
|
|
1617
|
+
@if (action.loading()) {
|
|
1618
|
+
<ion-spinner [slot]="iconOnly() ? 'icon-only' : 'start'" name="dots"></ion-spinner>
|
|
1619
|
+
} @else if (icon(); as ic) {
|
|
1620
|
+
<ion-icon [name]="ic" [slot]="iconOnly() ? 'icon-only' : 'start'"></ion-icon>
|
|
1621
|
+
}
|
|
1622
|
+
@if (label(); as lbl) {
|
|
1623
|
+
{{ lbl | dynamicText | async }}
|
|
1624
|
+
}
|
|
1625
|
+
</ion-button>
|
|
1626
|
+
@if (action.loading()) {
|
|
1627
|
+
<span class="df-ion-sr-only" role="status">Loading…</span>
|
|
1628
|
+
}
|
|
1629
|
+
`, isInline: true, styles: [".df-ion-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1630
|
+
}
|
|
1631
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonButtonAddonComponent, decorators: [{
|
|
1632
|
+
type: Component,
|
|
1633
|
+
args: [{ selector: 'df-ion-button-addon', imports: [IonButton, IonIcon, IonSpinner, DynamicTextPipe, AsyncPipe], hostDirectives: [NgForgeAddonAction], template: `
|
|
1634
|
+
<ion-button
|
|
1635
|
+
[attr.color]="color() ?? null"
|
|
1636
|
+
[fill]="fill()"
|
|
1637
|
+
[disabled]="action.disabled() || action.loading()"
|
|
1638
|
+
[attr.aria-label]="(ariaLabel() | dynamicText | async) ?? null"
|
|
1639
|
+
[attr.aria-busy]="action.loading() || null"
|
|
1640
|
+
(click)="action.dispatch()"
|
|
1641
|
+
>
|
|
1642
|
+
@if (action.loading()) {
|
|
1643
|
+
<ion-spinner [slot]="iconOnly() ? 'icon-only' : 'start'" name="dots"></ion-spinner>
|
|
1644
|
+
} @else if (icon(); as ic) {
|
|
1645
|
+
<ion-icon [name]="ic" [slot]="iconOnly() ? 'icon-only' : 'start'"></ion-icon>
|
|
1646
|
+
}
|
|
1647
|
+
@if (label(); as lbl) {
|
|
1648
|
+
{{ lbl | dynamicText | async }}
|
|
1649
|
+
}
|
|
1650
|
+
</ion-button>
|
|
1651
|
+
@if (action.loading()) {
|
|
1652
|
+
<span class="df-ion-sr-only" role="status">Loading…</span>
|
|
1653
|
+
}
|
|
1654
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".df-ion-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
|
|
1655
|
+
}] });
|
|
1656
|
+
|
|
1657
|
+
var ionButtonAddon_component = /*#__PURE__*/Object.freeze({
|
|
1658
|
+
__proto__: null,
|
|
1659
|
+
IonButtonAddonComponent: IonButtonAddonComponent
|
|
1660
|
+
});
|
|
1661
|
+
|
|
1662
|
+
/**
|
|
1663
|
+
* Renderer for the `ion-icon` addon kind.
|
|
1664
|
+
*
|
|
1665
|
+
* Outputs `<ion-icon [name]="icon">`. The host is set `aria-hidden="true"`
|
|
1666
|
+
* by default; if the addon supplies an `ariaLabel`, it is applied so the
|
|
1667
|
+
* icon is announced by screen readers.
|
|
1668
|
+
*/
|
|
1669
|
+
class IonIconAddonComponent {
|
|
1670
|
+
addon = input.required(...(ngDevMode ? [{ debugName: "addon" }] : /* istanbul ignore next */ []));
|
|
1671
|
+
/** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */
|
|
1672
|
+
fieldInputs = input(...(ngDevMode ? [undefined, { debugName: "fieldInputs" }] : /* istanbul ignore next */ []));
|
|
1673
|
+
iconName = computed(() => this.addon().icon, ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
|
|
1674
|
+
ariaLabel = computed(() => this.addon().ariaLabel, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
1675
|
+
hasAriaLabel = computed(() => this.addon().ariaLabel !== undefined, ...(ngDevMode ? [{ debugName: "hasAriaLabel" }] : /* istanbul ignore next */ []));
|
|
1676
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonIconAddonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1677
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: IonIconAddonComponent, isStandalone: true, selector: "df-ion-icon-addon", inputs: { addon: { classPropertyName: "addon", publicName: "addon", isSignal: true, isRequired: true, transformFunction: null }, fieldInputs: { classPropertyName: "fieldInputs", publicName: "fieldInputs", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.aria-hidden": "hasAriaLabel() ? null : \"true\"" } }, ngImport: i0, template: `<ion-icon [name]="iconName()" [attr.aria-label]="(ariaLabel() | dynamicText | async) ?? null"></ion-icon>`, isInline: true, dependencies: [{ kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1795
1678
|
}
|
|
1679
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: IonIconAddonComponent, decorators: [{
|
|
1680
|
+
type: Component,
|
|
1681
|
+
args: [{
|
|
1682
|
+
selector: 'df-ion-icon-addon',
|
|
1683
|
+
imports: [IonIcon, AsyncPipe, DynamicTextPipe],
|
|
1684
|
+
template: `<ion-icon [name]="iconName()" [attr.aria-label]="(ariaLabel() | dynamicText | async) ?? null"></ion-icon>`,
|
|
1685
|
+
host: {
|
|
1686
|
+
'[attr.aria-hidden]': 'hasAriaLabel() ? null : "true"',
|
|
1687
|
+
},
|
|
1688
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1689
|
+
}]
|
|
1690
|
+
}], propDecorators: { addon: [{ type: i0.Input, args: [{ isSignal: true, alias: "addon", required: true }] }], fieldInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldInputs", required: false }] }] } });
|
|
1691
|
+
|
|
1692
|
+
var ionIconAddon_component = /*#__PURE__*/Object.freeze({
|
|
1693
|
+
__proto__: null,
|
|
1694
|
+
IonIconAddonComponent: IonIconAddonComponent
|
|
1695
|
+
});
|
|
1796
1696
|
|
|
1797
1697
|
// Field fields
|
|
1798
1698
|
|
|
@@ -1800,5 +1700,5 @@ function withIonicFields(config) {
|
|
|
1800
1700
|
* Generated bundle index. Do not edit.
|
|
1801
1701
|
*/
|
|
1802
1702
|
|
|
1803
|
-
export { IONIC_CONFIG, IONIC_FIELD_TYPES, IonicButtonFieldComponent, IonicCheckboxFieldComponent, IonicDatepickerFieldComponent, IonicField, IonicInputFieldComponent, IonicMultiCheckboxFieldComponent, IonicRadioFieldComponent, IonicSelectFieldComponent, IonicSliderFieldComponent, IonicTextareaFieldComponent, IonicToggleFieldComponent, withIonicFields };
|
|
1703
|
+
export { IONIC_CONFIG, IONIC_FIELD_TYPES, IONIC_INPUT_TYPE_OVERRIDE, IonButtonAddonComponent, IonIconAddonComponent, IonicButtonFieldComponent, IonicCheckboxFieldComponent, IonicDatepickerFieldComponent, IonicField, IonicInputFieldComponent, IonicMultiCheckboxFieldComponent, IonicRadioFieldComponent, IonicSelectFieldComponent, IonicSliderFieldComponent, IonicTextareaFieldComponent, IonicToggleFieldComponent, withIonicAddons, withIonicFields };
|
|
1804
1704
|
//# sourceMappingURL=ng-forge-dynamic-forms-ionic.mjs.map
|